From 6485e5dcf50a69193d48c4ee85f0fc7eea71d538 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Sun, 3 May 2026 10:18:40 +0200 Subject: [PATCH 001/449] add checker histogram --- PWGUD/Tasks/upcRhoAnalysis.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 18c3eb5f08a..03c6abab77b 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -276,6 +276,7 @@ struct UpcRhoAnalysis { rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); rQC.add("QC/collisions/all/hOccupancyInTime", ";occupancy in time;counts", kTH1D, {{1100, 0.0, 1100.0}}); + rQC.add("QC/collisions/hNumContribVsPVTracks", ";number of track.isPVContributor() per collision;collision.numContrib();counts", kTH2D, {{101, -0.5, 100.5}, {101, -0.5, 100.5}}); // events with selected rho candidates rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); @@ -817,6 +818,14 @@ struct UpcRhoAnalysis { if (selectRuns && getRunIndex(collision.runNumber(), selectedRuns) == 0) return; + // check the number of PV tracks and the number of PV contrubutors + int nPVTracks = 0; + for (const auto& track : tracks) { + if (track.isPVContributor()) + nPVTracks++; + } + rQC.fill(HIST("QC/collisions/hNumContribVsPVTracks"), nPVTracks, collision.numContrib()); + fillCollisionQcHistos<0>(collision); // fill QC histograms before cuts if (!collisionPassesCuts(collision, runIndex)) // apply collision cuts return; From 47d119995d64178efd4e296d45666c9d10b7b77b Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Tue, 19 May 2026 15:26:17 +0200 Subject: [PATCH 002/449] switch on RCT, add pT histo for reweighting --- PWGUD/Tasks/upcRhoAnalysis.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 03c6abab77b..1f9812345f2 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -206,8 +206,8 @@ struct UpcRhoAnalysis { Configurable requireTof{"requireTof", false, "require TOF signal?"}; Configurable useRecoFlag{"useRecoFlag", false, "use UPC/STD reconstruction flag for event selection?"}; Configurable cutRecoFlag{"cutRecoFlag", 1, "0 = std mode, 1 = upc mode"}; - Configurable useRctFlag{"useRctFlag", false, "use RCT flags for event selection?"}; - Configurable cutRctFlag{"cutRctFlag", 0, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; + Configurable useRctFlag{"useRctFlag", true, "use RCT flags for event selection?"}; + Configurable cutRctFlag{"cutRctFlag", 1, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; Configurable selectRuns{"selectRuns", false, "select runs?"}; Configurable> selectedRuns{"selectedRuns", {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}, "list of selected runs"}; @@ -352,6 +352,7 @@ struct UpcRhoAnalysis { rSystem.add("system/all/unlike-sign/hM", ";#it{m} (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); rSystem.add("system/all/unlike-sign/hRecoSettingVsM", ";#it{m} (GeV/#it{c}^{2});reco setting;counts", kTH2D, {mAxis, {2, -0.5, 1.5}}); rSystem.add("system/all/unlike-sign/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + rSystem.add("system/all/unlike-sign/hPtReweighting", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {{40, 0.0, 0.2}}); rSystem.add("system/all/unlike-sign/hPt2", ";#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); rSystem.add("system/all/unlike-sign/hPtVsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); rSystem.add("system/all/unlike-sign/hPt2VsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH2D, {mAxis, pt2Axis}); @@ -499,6 +500,7 @@ struct UpcRhoAnalysis { if (cuts == 0) { rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hM"), mass); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt"), pt); + rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPtReweighting"), pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt2"), pt * pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPtVsM"), mass, pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt2VsM"), mass, pt * pt); @@ -511,6 +513,7 @@ struct UpcRhoAnalysis { } else { rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hM"), mass); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt"), pt); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPtReweighting"), pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt2"), pt * pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPtVsM"), mass, pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt2VsM"), mass, pt * pt); From a7ab47f702ec3b5105e6479c18874ed5374680c9 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Tue, 19 May 2026 15:45:04 +0200 Subject: [PATCH 003/449] add pT-dependence histograms for PID --- PWGUD/Tasks/upcRhoAnalysis.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 1f9812345f2..a323d081680 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -292,9 +292,13 @@ struct UpcRhoAnalysis { rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); // tracks rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hPtVsTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hPtVsTpcNSigmaEl", ";TPC #it{n#sigma}(e);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hPtVsTpcNSigmaKa", ";TPC #it{n#sigma}(K);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hPtVsTpcNSigmaPr", ";TPC #it{n#sigma}(p);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{9, -0.5, 8.5}}); rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); @@ -472,9 +476,13 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hEta"), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPhi"), phi(track.px(), track.py())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPi"), track.tpcNSigmaPi()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaPi"), track.tpcNSigmaPi(), track.pt()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaEl"), track.tpcNSigmaEl()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaEl"), track.tpcNSigmaEl(), track.pt()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaKa"), track.tpcNSigmaKa()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaKa"), track.tpcNSigmaKa(), track.pt()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPr"), track.tpcNSigmaPr()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaPr"), track.tpcNSigmaPr(), track.pt()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hDcaXYZ"), track.dcaZ(), track.dcaXY()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsNCls"), track.itsNCls()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsChi2NCl"), track.itsChi2NCl()); From 88cbf620174369aafa69f5fbdec9066740a9e51d Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Mon, 25 May 2026 14:50:03 +0200 Subject: [PATCH 004/449] add eta dependence for PID --- PWGUD/Tasks/upcRhoAnalysis.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index a323d081680..db20d94afb3 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -257,7 +257,7 @@ struct UpcRhoAnalysis { void init(o2::framework::InitContext& context) { if (context.mOptions.get("processSGdata") || context.mOptions.get("processDGdata")) { - // QA // + // QA // collisions rQC.add("QC/collisions/all/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); rQC.add("QC/collisions/all/hPosZ", ";vertex #it{z} (cm);counts", kTH1D, {{400, -20.0, 20.0}}); @@ -292,13 +292,13 @@ struct UpcRhoAnalysis { rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); // tracks rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsTpcNSigmaEl", ";TPC #it{n#sigma}(e);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaEl", ";TPC #it{n#sigma}(e);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsTpcNSigmaKa", ";TPC #it{n#sigma}(K);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaKa", ";TPC #it{n#sigma}(K);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsTpcNSigmaPr", ";TPC #it{n#sigma}(p);#it{p}_{T} (GeV/#it{c});counts", kTH2D, {nSigmaAxis, ptAxis}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPr", ";TPC #it{n#sigma}(p);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{9, -0.5, 8.5}}); rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); @@ -476,13 +476,13 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hEta"), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPhi"), phi(track.px(), track.py())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPi"), track.tpcNSigmaPi()); - rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaPi"), track.tpcNSigmaPi(), track.pt()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsEtaVsTpcNSigmaPi"), track.tpcNSigmaPi(), track.pt(), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaEl"), track.tpcNSigmaEl()); - rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaEl"), track.tpcNSigmaEl(), track.pt()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsEtaVsTpcNSigmaEl"), track.tpcNSigmaEl(), track.pt(), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaKa"), track.tpcNSigmaKa()); - rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaKa"), track.tpcNSigmaKa(), track.pt()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsEtaVsTpcNSigmaKa"), track.tpcNSigmaKa(), track.pt(), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPr"), track.tpcNSigmaPr()); - rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsTpcNSigmaPr"), track.tpcNSigmaPr(), track.pt()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hPtVsEtaVsTpcNSigmaPr"), track.tpcNSigmaPr(), track.pt(), eta(track.px(), track.py(), track.pz())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hDcaXYZ"), track.dcaZ(), track.dcaXY()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsNCls"), track.itsNCls()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsChi2NCl"), track.itsChi2NCl()); From 175b00e32dc645659a52f83e4ee280c48773728e Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 2 May 2026 13:26:56 +0200 Subject: [PATCH 005/449] [PWGEM/Dilepton] update taggingHFE (#16062) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 139 ++++++++++++++++++++++------ 1 file changed, 110 insertions(+), 29 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 927a6f276ef..9741e58eea1 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -167,6 +167,7 @@ struct taggingHFE { Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; Configurable requirePiKa{"requirePiKa", false, "require hadron to be pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. + Configurable requireKa{"requireKa", false, "require hadron to be kaon"}; // Mostly, kaon is involved in semileptonic decay of charm hadrons. } hadronCut; struct : ConfigurableGroup { @@ -451,6 +452,14 @@ struct taggingHFE { fRegistry.add("Cascade/hMassOmega", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", kTH1F, {{100, 1.62, 1.72}}, false); } + template + bool isKaon(TTrack const& track) + { + bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; + bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; + return is_ka_included_TPC && is_ka_included_TOF; + } + template bool isKaon_or_isPion(TTrack const& track) { @@ -618,6 +627,10 @@ struct taggingHFE { return false; } + if (hadronCut.requireKa && !isKaon(track)) { + return false; + } + return true; } @@ -1023,7 +1036,7 @@ struct taggingHFE { auto mcpos = pos.template mcParticle_as(); auto mcmother = mcpos.template mothers_as()[0]; - bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > -1) || (IsFromBeauty(mcmother, mcParticles) > -1); + bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > 0) || (IsFromBeauty(mcmother, mcParticles) > 0); auto mcCollision = mcpos.template mcCollision_as(); leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), @@ -1054,7 +1067,18 @@ struct taggingHFE { } auto mckaon = kaon.template mcParticle_as(); - bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > -1; + bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; + if (mckaon.has_mothers() && !foundCommonMother) { + auto mcMother_of_kaon = mckaon.template mothers_first_as(); + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); + if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { + foundCommonMother = true; + // LOGF(info, "eK: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } + emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaKa(), kaon.tofNSigmaKa(), @@ -1069,6 +1093,9 @@ struct taggingHFE { // D+ -> e+ K0S nu_e for (const auto& k0Id : k0Ids) { auto v0 = v0s.rawIteratorAt(k0Id); + if (v0.posTrackId() == positronId || v0.negTrackId() == positronId) { + continue; + } const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; @@ -1100,7 +1127,7 @@ struct taggingHFE { int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; - if (mcK0SId > -1) { // true K0S + if (mcK0SId > 0) { // true K0S pdgCodeV0 = 310; auto mcK0S = mcParticles.rawIteratorAt(mcK0SId); auto mcK0 = mcK0S.template mothers_first_as(); // mother of K0S is K0 in simulation. @@ -1108,7 +1135,18 @@ struct taggingHFE { if (std::abs(mcK0.pdgCode()) == 311) { mcK0S = mcK0; } - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcK0S) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcK0S) > 0; + + if (mcK0S.has_mothers() && !foundCommonMother) { + auto mcMother_of_k0s = mcK0S.template mothers_first_as(); + if (mcMother_of_k0s.pdgCode() == -323 || mcMother_of_k0s.pdgCode() == -313 || mcMother_of_k0s.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_k0s); + if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { // proton decay is implemented. reject it. + foundCommonMother = true; + // LOGF(info, "eK0S: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } } emmllv0pair(leptonTable.lastIndex(), @@ -1127,6 +1165,9 @@ struct taggingHFE { // Lc+ -> e+ Lambda nu_e, br = 0.0356, ctau = 60.75 um, m = 2286 MeV/c2 for (const auto& lambdaId : lambdaIds) { auto v0 = v0s.rawIteratorAt(lambdaId); + if (v0.posTrackId() == positronId || v0.negTrackId() == positronId) { + continue; + } const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; @@ -1158,10 +1199,10 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true v0 + if (mcLambdaId > 0) { // true v0 auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); pdgCodeV0 = mcLambda.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcLambda) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcLambda) > 0; } emmllv0pair(leptonTable.lastIndex(), @@ -1179,6 +1220,9 @@ struct taggingHFE { for (const auto& cascadeId : xiMinusIds) { auto cascade = cascades.rawIteratorAt(cascadeId); + if (cascade.posTrackId() == positronId || cascade.negTrackId() == positronId || cascade.bachelorId() == positronId) { + continue; + } const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; @@ -1212,13 +1256,13 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true Lambda + if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcXiId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, 3122, -211, 3312, mcParticles); - if (mcXiId > -1) { // true xiMinus + if (mcXiId > 0) { // true xiMinus auto mcXi = mcParticles.rawIteratorAt(mcXiId); pdgCodeCascade = mcXi.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcXi) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcXi) > 0; } } @@ -1237,6 +1281,9 @@ struct taggingHFE { for (const auto& cascadeId : omegaMinusIds) { auto cascade = cascades.rawIteratorAt(cascadeId); + if (cascade.posTrackId() == positronId || cascade.negTrackId() == positronId || cascade.bachelorId() == positronId) { + continue; + } const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; @@ -1270,13 +1317,13 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true Lambda + if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcOmegaId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, 3122, -321, 3334, mcParticles); - if (mcOmegaId > -1) { // true omegaMinus + if (mcOmegaId > 0) { // true omegaMinus auto mcOmega = mcParticles.rawIteratorAt(mcOmegaId); pdgCodeCascade = mcOmega.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcOmega) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcOmega) > 0; } } @@ -1306,7 +1353,7 @@ struct taggingHFE { auto mcele = ele.template mcParticle_as(); auto mcmother = mcele.template mothers_as()[0]; - bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > -1) || (IsFromBeauty(mcmother, mcParticles) > -1); + bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > 0) || (IsFromBeauty(mcmother, mcParticles) > 0); auto mcCollision = mcele.template mcCollision_as(); leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), @@ -1336,7 +1383,17 @@ struct taggingHFE { } auto mckaon = kaon.template mcParticle_as(); - bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > -1; + bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; + if (mckaon.has_mothers() && !foundCommonMother) { + auto mcMother_of_kaon = mckaon.template mothers_first_as(); + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); + if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { + foundCommonMother = true; + // LOGF(info, "eK: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), @@ -1349,9 +1406,12 @@ struct taggingHFE { } // end of kaon loop - // D- -> e0 anti-K0S anti-nu_e + // D- -> e- anti-K0S anti-nu_e for (const auto& k0Id : k0Ids) { auto v0 = v0s.rawIteratorAt(k0Id); + if (v0.posTrackId() == electronId || v0.negTrackId() == electronId) { + continue; + } const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; @@ -1383,7 +1443,7 @@ struct taggingHFE { int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; - if (mcK0SId > -1) { // true K0S + if (mcK0SId > 0) { // true K0S pdgCodeV0 = 310; auto mcK0S = mcParticles.rawIteratorAt(mcK0SId); auto mcK0 = mcK0S.template mothers_first_as(); // mother of K0S is K0 in simulation. @@ -1391,7 +1451,17 @@ struct taggingHFE { if (std::abs(mcK0.pdgCode()) == 311) { mcK0S = mcK0; } - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcK0S) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcK0S) > 0; + if (mcK0S.has_mothers() && !foundCommonMother) { + auto mcMother_of_k0s = mcK0S.template mothers_first_as(); + if (mcMother_of_k0s.pdgCode() == 323 || mcMother_of_k0s.pdgCode() == 313 || mcMother_of_k0s.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_k0s); + if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { // proton decay is implemented. reject it. + foundCommonMother = true; + // LOGF(info, "eK0S: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } } emmllv0pair(leptonTable.lastIndex(), @@ -1410,6 +1480,9 @@ struct taggingHFE { // Lc- -> e- anti-Lambda anti-nu_e, br = 0.0356, ctau = 60.75 um, m = 2286 MeV/c2 for (const auto& lambdaId : antilambdaIds) { auto v0 = v0s.rawIteratorAt(lambdaId); + if (v0.posTrackId() == electronId || v0.negTrackId() == electronId) { + continue; + } const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; @@ -1441,10 +1514,10 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true v0 + if (mcLambdaId > 0) { // true v0 auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); pdgCodeV0 = mcLambda.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcLambda) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcLambda) > 0; } emmllv0pair(leptonTable.lastIndex(), @@ -1462,6 +1535,9 @@ struct taggingHFE { for (const auto& cascadeId : xiPlusIds) { auto cascade = cascades.rawIteratorAt(cascadeId); + if (cascade.posTrackId() == electronId || cascade.negTrackId() == electronId || cascade.bachelorId() == electronId) { + continue; + } const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; @@ -1495,13 +1571,13 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true Lambda + if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcXiId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, -3122, 211, -3312, mcParticles); - if (mcXiId > -1) { // true xiMinus + if (mcXiId > 0) { // true xiMinus auto mcXi = mcParticles.rawIteratorAt(mcXiId); pdgCodeCascade = mcXi.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcXi) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcXi) > 0; } } @@ -1520,6 +1596,9 @@ struct taggingHFE { for (const auto& cascadeId : omegaPlusIds) { auto cascade = cascades.rawIteratorAt(cascadeId); + if (cascade.posTrackId() == electronId || cascade.negTrackId() == electronId || cascade.bachelorId() == electronId) { + continue; + } const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; @@ -1553,13 +1632,13 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; - if (mcLambdaId > -1) { // true Lambda + if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcOmegaId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, -3122, 321, -3334, mcParticles); - if (mcOmegaId > -1) { // true omegaMinus + if (mcOmegaId > 0) { // true omegaMinus auto mcOmega = mcParticles.rawIteratorAt(mcOmegaId); pdgCodeCascade = mcOmega.pdgCode(); - foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcOmega) > -1; + foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcOmega) > 0; } } @@ -1618,12 +1697,14 @@ struct taggingHFE { auto mcDpms_per_mccollision = mcDpms.sliceBy(perMcCollision, mcCollision.globalIndex()); for (const auto& mcParticle : mcDpms_per_mccollision) { + // LOGF(info, "Dpm: mcParticle.pdgCode() = %d", mcParticle.pdgCode()); // for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { // auto daughter = mcParticles.rawIteratorAt(d); // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); // } - if (isSemiLeptonic(mcParticle, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1, -321) || isSemiLeptonic(mcParticle, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1, 321)) { // D+ -> l+ nul K- pi+ or D- -> l- anti-nul K+ pi- + // if (isSemiLeptonic(mcParticle, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1, -321) || isSemiLeptonic(mcParticle, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1, 321)) { // D+ -> l+ nul K- pi+ or D- -> l- anti-nul K+ pi- + if (isSemiLeptonic(mcParticle, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1, 311) || isSemiLeptonic(mcParticle, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1, 311)) { // D+ -> l+ nul K- pi+ or D- -> l- anti-nul K+ pi- // LOGF(info, "semileptonic decay is found."); float ptLepton = 0, ptHadron = 0, etaLepton = 999.f, etaHadron = 999.f; for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { @@ -1631,7 +1712,7 @@ struct taggingHFE { if (std::abs(daughter.pdgCode()) == cfgPdgLepton) { ptLepton = daughter.pt(); etaLepton = daughter.eta(); - } else if (std::abs(daughter.pdgCode()) == 321) { + } else if (std::abs(daughter.pdgCode()) == 311) { ptHadron = daughter.pt(); etaHadron = daughter.eta(); } @@ -1697,8 +1778,8 @@ struct taggingHFE { Partition mcD0s = nabs(o2::aod::mcparticle::pdgCode) == 421; Partition mcDspms = nabs(o2::aod::mcparticle::pdgCode) == 431; Partition mcLcs = nabs(o2::aod::mcparticle::pdgCode) == 4122; - Partition mcXic0s = nabs(o2::aod::mcparticle::pdgCode) == 4232; - Partition mcOmegac0s = nabs(o2::aod::mcparticle::pdgCode) == 4332; + // Partition mcXic0s = nabs(o2::aod::mcparticle::pdgCode) == 4232; + // Partition mcOmegac0s = nabs(o2::aod::mcparticle::pdgCode) == 4332; SliceCache cache; Preslice perCol = o2::aod::track::collisionId; From 6556b1b7952d2aaae345953544167c0fd98ec9eb Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 2 May 2026 16:55:17 +0200 Subject: [PATCH 006/449] [PWGEM/Dilepton] fix taggingHFE.cxx (#16065) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 125 +++++++++++++--------------- 1 file changed, 58 insertions(+), 67 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 9741e58eea1..7bb44ccc588 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -148,8 +148,8 @@ struct taggingHFE { Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; - Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.8, "min. TPC Ncr/Nf ratio"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 0.7, "max fraction of shared clusters in TPC"}; + Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.f, "min. TPC Ncr/Nf ratio"}; + Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 4, "min ncluster its"}; @@ -181,8 +181,8 @@ struct taggingHFE { Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "min cospa for v0"}; Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 0.1, "max distance between 2 legs for v0"}; // Configurable cfg_min_radius{"cfg_min_radius", 0.1, "min rxy for v"}; - Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.8, "min. TPC Ncr/Nf ratio"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 0.7, "max fraction of shared clusters in TPC"}; + Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.f, "min. TPC Ncr/Nf ratio"}; + Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; @@ -191,14 +191,14 @@ struct taggingHFE { Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; Configurable cfg_min_dcaxy{"cfg_min_dcaxy", 0.1, "min dca XY for v0 legs in cm"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -2, "min n sigma pi in TPC"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +2, "max n sigma pi in TPC"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -2, "min n sigma pr in TPC"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +2, "max n sigma pr in TPC"}; - Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -2, "min n sigma pi in TOF"}; - Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +2, "max n sigma pi in TOF"}; - Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -2, "min n sigma pr in TOF"}; - Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +2, "max n sigma pr in TOF"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3, "min n sigma pi in TPC"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3, "max n sigma pi in TPC"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; + Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; + Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; } v0Cut; struct : ConfigurableGroup { @@ -497,15 +497,6 @@ struct taggingHFE { // return is_el_included_TPC && is_el_included_TOF; // } - template - bool isKaonBachelor(TTrack const& track) - { - // TOFif - bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; - bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; - return is_ka_included_TPC && is_ka_included_TOF; - } - template bool isSelectedTrack(TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) { @@ -569,7 +560,7 @@ struct taggingHFE { } template - bool isSelectedKaon(TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) + bool isSelectedHadron(TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) { if (!track.hasITS() || !track.hasTPC()) { return false; @@ -763,7 +754,7 @@ struct taggingHFE { if (isPion(bachelor)) { fRegistry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); } - if (isKaonBachelor(bachelor)) { + if (isKaon(bachelor)) { fRegistry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); } } @@ -789,7 +780,7 @@ struct taggingHFE { bool is_strhad_involved = false; for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { if (d < mcParticles.size()) { // protect against bad daughter indices - const auto& daughter = mcParticles.rawIteratorAt(d); + auto daughter = mcParticles.rawIteratorAt(d); if (daughter.pdgCode() == pdgLepton) { is_lepton_involved = true; } else if (daughter.pdgCode() == pdgNeutrino) { @@ -842,7 +833,7 @@ struct taggingHFE { used_electronIds.reserve(tracks.size()); for (const auto& collision : collisions) { - const auto& bc = collision.template foundBC_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); if (!collision.has_mcCollision()) { continue; @@ -871,14 +862,14 @@ struct taggingHFE { mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - const auto& trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); electronIds.reserve(trackIdsThisCollision.size()); positronIds.reserve(trackIdsThisCollision.size()); kaonPlusIds.reserve(trackIdsThisCollision.size()); kaonMinusIds.reserve(trackIdsThisCollision.size()); for (const auto& trackId : trackIdsThisCollision) { - const auto& track = trackId.template track_as(); + auto track = trackId.template track_as(); if (!track.hasITS() || !track.hasTPC()) { continue; } @@ -886,7 +877,7 @@ struct taggingHFE { if (!track.has_mcParticle()) { continue; } - const auto& mcParticle = track.template mcParticle_as(); + auto mcParticle = track.template mcParticle_as(); if (!mcParticle.has_mothers()) { continue; } @@ -921,7 +912,7 @@ struct taggingHFE { dcaXY = mDcaInfoCov.getY(); dcaZ = mDcaInfoCov.getZ(); - if (isSelectedKaon(track, trackParCov, dcaXY, dcaZ)) { + if (isSelectedHadron(track, trackParCov, dcaXY, dcaZ)) { // electrons can be included in hadron sample. fRegistry.fill(HIST("Hadron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); fRegistry.fill(HIST("Hadron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Hadron/hTOFbeta"), track.p(), track.beta()); @@ -934,7 +925,7 @@ struct taggingHFE { } // end of track loop for electron selection - const auto& v0s_per_coll = v0s.sliceBy(perCol_v0, collision.globalIndex()); + auto v0s_per_coll = v0s.sliceBy(perCol_v0, collision.globalIndex()); k0Ids.reserve(v0s_per_coll.size()); k0Ids.reserve(v0s_per_coll.size()); lambdaIds.reserve(v0s_per_coll.size()); @@ -960,7 +951,7 @@ struct taggingHFE { } } // end of V0 loop - const auto& cascades_per_coll = cascades.sliceBy(perCol_casc, collision.globalIndex()); + auto cascades_per_coll = cascades.sliceBy(perCol_casc, collision.globalIndex()); xiPlusIds.reserve(cascades_per_coll.size()); xiPlusIds.reserve(cascades_per_coll.size()); xiMinusIds.reserve(cascades_per_coll.size()); @@ -1006,14 +997,14 @@ struct taggingHFE { if (isXi(cascade) && isPion(bachelor)) { xiMinusIds.emplace_back(cascade.globalIndex()); } - if (isOmega(cascade) && isKaonBachelor(bachelor)) { + if (isOmega(cascade) && isKaon(bachelor)) { omegaMinusIds.emplace_back(cascade.globalIndex()); } } else { // Xi+ or Omega+ if (isXi(cascade) && isPion(bachelor)) { xiPlusIds.emplace_back(cascade.globalIndex()); } - if (isOmega(cascade) && isKaonBachelor(bachelor)) { + if (isOmega(cascade) && isKaon(bachelor)) { omegaPlusIds.emplace_back(cascade.globalIndex()); } } @@ -1026,7 +1017,7 @@ struct taggingHFE { // } for (const auto& positronId : positronIds) { - const auto& pos = tracks.rawIteratorAt(positronId); + auto pos = tracks.rawIteratorAt(positronId); mDcaInfoCov.set(999, 999, 999, 999, 999); auto leptonParCov = getTrackParCov(pos); leptonParCov.setPID(o2::track::PID::Electron); @@ -1045,7 +1036,7 @@ struct taggingHFE { // D0 -> e+ nu_e K-, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonMinusIds) { - const auto& kaon = tracks.rawIteratorAt(kaonId); + auto kaon = tracks.rawIteratorAt(kaonId); mDcaInfoCov.set(999, 999, 999, 999, 999); auto trackParCov = getTrackParCov(kaon); trackParCov.setPID(kaon.pidForTracking()); @@ -1057,7 +1048,7 @@ struct taggingHFE { continue; } - const auto& eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, pos, kaon, o2::track::PID::Electron, kaon.pidForTracking()); + auto eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, pos, kaon, o2::track::PID::Electron, kaon.pidForTracking()); if (!eKpair.isOK) { continue; } @@ -1111,7 +1102,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterV0; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackV0, 2.f, matCorr, &impactParameterV0); // trackV0 is TrackParCov object - const auto& eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, pos, v0, o2::track::PID::Electron, o2::track::PID::K0); + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, pos, v0, o2::track::PID::Electron, o2::track::PID::K0); if (!eV0pair.isOK) { continue; @@ -1122,8 +1113,8 @@ struct taggingHFE { auto posLeg = v0.template posTrack_as(); auto negLeg = v0.template negTrack_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; @@ -1183,7 +1174,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterV0; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackV0, 2.f, matCorr, &impactParameterV0); // trackV0 is TrackParCov object - const auto& eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, pos, v0, o2::track::PID::Electron, o2::track::PID::Lambda); + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, pos, v0, o2::track::PID::Electron, o2::track::PID::Lambda); if (!eV0pair.isOK) { continue; @@ -1194,8 +1185,8 @@ struct taggingHFE { auto posLeg = v0.template posTrack_as(); auto negLeg = v0.template negTrack_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; @@ -1238,7 +1229,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterCasc; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object - const auto& eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, pos, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, pos, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); if (!eCpair.isOK) { continue; @@ -1250,9 +1241,9 @@ struct taggingHFE { auto posLeg = cascade.template posTrack_as(); auto negLeg = cascade.template negTrack_as(); auto bachelor = cascade.template bachelor_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); - const auto& mcbachelor = bachelor.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); + auto mcbachelor = bachelor.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; @@ -1299,7 +1290,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterCasc; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object - const auto& eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, pos, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, pos, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); if (!eCpair.isOK) { continue; @@ -1311,9 +1302,9 @@ struct taggingHFE { auto posLeg = cascade.template posTrack_as(); auto negLeg = cascade.template negTrack_as(); auto bachelor = cascade.template bachelor_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); - const auto& mcbachelor = bachelor.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); + auto mcbachelor = bachelor.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; @@ -1343,7 +1334,7 @@ struct taggingHFE { } // end of main positron sample for (const auto& electronId : electronIds) { - const auto& ele = tracks.rawIteratorAt(electronId); + auto ele = tracks.rawIteratorAt(electronId); mDcaInfoCov.set(999, 999, 999, 999, 999); auto leptonParCov = getTrackParCov(ele); leptonParCov.setPID(o2::track::PID::Electron); @@ -1362,7 +1353,7 @@ struct taggingHFE { // D0bar -> e- anti-nu_e K+, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonPlusIds) { - const auto& kaon = tracks.rawIteratorAt(kaonId); + auto kaon = tracks.rawIteratorAt(kaonId); mDcaInfoCov.set(999, 999, 999, 999, 999); auto trackParCov = getTrackParCov(kaon); trackParCov.setPID(kaon.pidForTracking()); @@ -1374,7 +1365,7 @@ struct taggingHFE { continue; } - const auto& eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, ele, kaon, o2::track::PID::Electron, kaon.pidForTracking()); + auto eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, ele, kaon, o2::track::PID::Electron, kaon.pidForTracking()); if (!eKpair.isOK) { continue; } @@ -1427,7 +1418,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterV0; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackV0, 2.f, matCorr, &impactParameterV0); // trackV0 is TrackParCov object - const auto& eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, ele, v0, o2::track::PID::Electron, o2::track::PID::K0); + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, ele, v0, o2::track::PID::Electron, o2::track::PID::K0); if (!eV0pair.isOK) { continue; @@ -1438,8 +1429,8 @@ struct taggingHFE { auto posLeg = v0.template posTrack_as(); auto negLeg = v0.template negTrack_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; @@ -1498,7 +1489,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterV0; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackV0, 2.f, matCorr, &impactParameterV0); // trackV0 is TrackParCov object - const auto& eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, ele, v0, o2::track::PID::Electron, o2::track::PID::Lambda); + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(fitter_eV0, collision, ele, v0, o2::track::PID::Electron, o2::track::PID::Lambda); if (!eV0pair.isOK) { continue; @@ -1509,8 +1500,8 @@ struct taggingHFE { auto posLeg = v0.template posTrack_as(); auto negLeg = v0.template negTrack_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; @@ -1553,7 +1544,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterCasc; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object - const auto& eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, ele, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, ele, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); if (!eCpair.isOK) { continue; @@ -1565,9 +1556,9 @@ struct taggingHFE { auto posLeg = cascade.template posTrack_as(); auto negLeg = cascade.template negTrack_as(); auto bachelor = cascade.template bachelor_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); - const auto& mcbachelor = bachelor.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); + auto mcbachelor = bachelor.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; @@ -1614,7 +1605,7 @@ struct taggingHFE { o2::dataformats::DCA impactParameterCasc; o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object - const auto& eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, ele, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(fitter_eCascade, collision, ele, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); if (!eCpair.isOK) { continue; @@ -1626,9 +1617,9 @@ struct taggingHFE { auto posLeg = cascade.template posTrack_as(); auto negLeg = cascade.template negTrack_as(); auto bachelor = cascade.template bachelor_as(); - const auto& mcposLeg = posLeg.template mcParticle_as(); - const auto& mcnegLeg = negLeg.template mcParticle_as(); - const auto& mcbachelor = bachelor.template mcParticle_as(); + auto mcposLeg = posLeg.template mcParticle_as(); + auto mcnegLeg = negLeg.template mcParticle_as(); + auto mcbachelor = bachelor.template mcParticle_as(); int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; From 7731161913362c990d7e9e4446a5e1551604ad4e Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Sat, 2 May 2026 16:57:10 +0200 Subject: [PATCH 007/449] [PWGCF] FemtoUnivserse: Add RCTFlagChecker (#16064) --- .../TableProducer/femtoUniverseProducerTask.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index ab9ed0fce9d..b514d43615a 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -34,6 +34,7 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" @@ -86,6 +87,7 @@ using namespace o2::analysis::femto_universe; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; +using namespace o2::aod::rctsel; namespace o2::aod { @@ -137,6 +139,8 @@ struct FemtoUniverseProducerTask { Produces outputDebugPartsMC; Produces outputCascParts; + RCTFlagsChecker rctChecker; + Configurable confIsDebug{"confIsDebug", true, "Enable Debug tables"}; Configurable confFillITSPid{"confFillITSPid", false, "Fill ITSPid information"}; Configurable confIsUseCutculator{"confIsUseCutculator", true, "Enable cutculator for track cuts"}; @@ -188,6 +192,7 @@ struct FemtoUniverseProducerTask { Configurable confTPCOccupancyMin{"confTPCOccupancyMin", 0, "Minimum value for TPC Occupancy selection"}; Configurable confTPCOccupancyMax{"confTPCOccupancyMax", 5000, "Maximum value for TPC Occupancy selection"}; Configurable confIsCent{"confIsCent", true, "Centrality or multiplicity selection"}; + Configurable confIsCheckRCTFlags{"confIsCheckRCTFlags", true, "Use RCTFlags"}; } ConfGeneral; Filter customCollCentFilter = (aod::cent::centFT0C > ConfGeneral.confCentFT0Min) && (aod::cent::centFT0C < ConfGeneral.confCentFT0Max); @@ -595,6 +600,7 @@ struct FemtoUniverseProducerTask { } zorroSummary.setObject(zorro.getZorroSummary()); + rctChecker.init("CBT_hadronPID", false, true); colCuts.setCuts(ConfGeneral.confEvtZvtx, ConfGeneral.confEvtTriggerCheck, ConfGeneral.confEvtTriggerSel, ConfGeneral.confEvtOfflineCheck, confIsRun3, ConfGeneral.confCentFT0Min, ConfGeneral.confCentFT0Max); colCuts.init(&qaRegistry); @@ -1053,6 +1059,9 @@ struct FemtoUniverseProducerTask { template bool fillCollisions(CollisionType const& col, TrackType const& tracks) { + if (ConfGeneral.confIsCheckRCTFlags && !rctChecker(col)) { + return false; + } const auto vtxZ = col.posZ(); float mult = 0; int multNtr = 0; From 79473adeae340afce36ea306368170402ab6033e Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sat, 2 May 2026 22:16:32 +0530 Subject: [PATCH 008/449] [PWGLF] Added PDG checks for Kstar and Phi daughters (#16048) Co-authored-by: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> --- PWGLF/Tasks/QC/mcParticlePrediction.cxx | 34 ++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/QC/mcParticlePrediction.cxx b/PWGLF/Tasks/QC/mcParticlePrediction.cxx index 11ac33586be..0da77c92ee9 100644 --- a/PWGLF/Tasks/QC/mcParticlePrediction.cxx +++ b/PWGLF/Tasks/QC/mcParticlePrediction.cxx @@ -180,6 +180,7 @@ struct mcParticlePrediction { "Estimators enabled"}; Configurable selectInelGt0{"selectInelGt0", true, "Select only inelastic events"}; Configurable selectPrimaries{"selectPrimaries", true, "Select only primary particles"}; + Configurable rapidityCut{"rapidityCut", 0.5, "Select only particles within |y| < cut"}; Configurable requireCoincidenceEstimators{"requireCoincidenceEstimators", false, "Asks for a coincidence when two estimators are used"}; Configurable discardkIsGoodZvtxFT0vsPV{"discardkIsGoodZvtxFT0vsPV", false, "Select only collisions with matching BC and MC BC"}; Configurable discardMismatchedBCs{"discardMismatchedBCs", false, "Select only collisions with matching BC and MC BC"}; @@ -493,9 +494,9 @@ struct mcParticlePrediction { continue; } - if (!particle.isPhysicalPrimary()) { - continue; - } + // if (!particle.isPhysicalPrimary()) { + // continue; + // } TParticlePDG* p = pdgDB->GetParticle(particle.pdgCode()); if (p) { @@ -506,7 +507,28 @@ struct mcParticlePrediction { } } - if (std::abs(particle.y()) > 0.5) { + if (std::abs(particle.y()) >= rapidityCut) { + continue; + } + + // Check if particle has daughters (not a final state particle) + auto daughters = particle.daughters_as(); + bool isValid = false; + + if (daughters.size() > 0) { + isValid = true; + for (const auto& daughter : daughters) { + if (!daughter.isPhysicalPrimary()) { + isValid = false; + break; + } + } + } else { + // Final state particle - check if particle itself is physical primary + isValid = particle.isPhysicalPrimary(); + } + + if (!isValid) { continue; } @@ -672,10 +694,10 @@ struct mcParticlePrediction { float nMultRecoMCBC[Estimators::nEstimators] = {0}; if (mcBC.has_ft0()) { const auto& ft0 = mcBC.ft0(); - for (auto amplitude : ft0.amplitudeA()) { + for (const auto& amplitude : ft0.amplitudeA()) { nMultRecoMCBC[Estimators::FT0A] += amplitude; } - for (auto amplitude : ft0.amplitudeC()) { + for (const auto& amplitude : ft0.amplitudeC()) { nMultRecoMCBC[Estimators::FT0C] += amplitude; } nMultRecoMCBC[Estimators::FT0AC] = nMultRecoMCBC[Estimators::FT0A] + nMultRecoMCBC[Estimators::FT0C]; From cd80e1f177732b44d634ddeadd348ac030a26f6f Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Sun, 3 May 2026 03:57:01 +0200 Subject: [PATCH 009/449] [PWGLF] updated code to include timestamp and energy information (#16067) Co-authored-by: Prottay Das --- PWGLF/DataModel/ZDCCalTables.h | 37 +++++++ PWGLF/TableProducer/Common/spvector.cxx | 26 +++++ PWGLF/TableProducer/Common/zdcvector.cxx | 124 ++++++++++++++++------- 3 files changed, 150 insertions(+), 37 deletions(-) diff --git a/PWGLF/DataModel/ZDCCalTables.h b/PWGLF/DataModel/ZDCCalTables.h index 0e80cdbab25..40b5fbdd575 100644 --- a/PWGLF/DataModel/ZDCCalTables.h +++ b/PWGLF/DataModel/ZDCCalTables.h @@ -48,5 +48,42 @@ DECLARE_SOA_TABLE(ZDCCalTables, "AOD", "ZDCCALTABLE", zdccaltable::QyA, zdccaltable::QyC); using ZDCCalTable = ZDCCalTables::iterator; + +// Extra optional linked table. +// This table does NOT duplicate cent, vx, vy, vz, run number, trigger, etc. +// It only stores the ZDC energies and links back to ZDCCalTables. +namespace zdcenergytable +{ +DECLARE_SOA_INDEX_COLUMN(ZDCCalTable, zdcCalTable); + +DECLARE_SOA_COLUMN(ZNACommon, znaCommon, float); +DECLARE_SOA_COLUMN(ZNCCommon, zncCommon, float); + +DECLARE_SOA_COLUMN(ZNA0, zna0, float); +DECLARE_SOA_COLUMN(ZNA1, zna1, float); +DECLARE_SOA_COLUMN(ZNA2, zna2, float); +DECLARE_SOA_COLUMN(ZNA3, zna3, float); + +DECLARE_SOA_COLUMN(ZNC0, znc0, float); +DECLARE_SOA_COLUMN(ZNC1, znc1, float); +DECLARE_SOA_COLUMN(ZNC2, znc2, float); +DECLARE_SOA_COLUMN(ZNC3, znc3, float); +} // namespace zdcenergytable + +DECLARE_SOA_TABLE(ZDCEnergyTables, "AOD", "ZDCENERGY", + zdcenergytable::ZDCCalTableId, + zdcenergytable::ZNACommon, + zdcenergytable::ZNCCommon, + zdcenergytable::ZNA0, + zdcenergytable::ZNA1, + zdcenergytable::ZNA2, + zdcenergytable::ZNA3, + zdcenergytable::ZNC0, + zdcenergytable::ZNC1, + zdcenergytable::ZNC2, + zdcenergytable::ZNC3); + +using ZDCEnergyTable = ZDCEnergyTables::iterator; + } // namespace o2::aod #endif // PWGLF_DATAMODEL_ZDCCALTABLES_H_ diff --git a/PWGLF/TableProducer/Common/spvector.cxx b/PWGLF/TableProducer/Common/spvector.cxx index 02748f5d7be..d3bd49d3cf4 100644 --- a/PWGLF/TableProducer/Common/spvector.cxx +++ b/PWGLF/TableProducer/Common/spvector.cxx @@ -53,6 +53,7 @@ #include #include #include +#include #include using namespace o2; @@ -114,6 +115,9 @@ struct spvector { Configurable CentfineNbins{"CentfineNbins", 16, "Number of bins in cent fine histograms"}; Configurable lfinebinCent{"lfinebinCent", 0.0, "lower bin value in cent fine histograms"}; Configurable hfinebinCent{"hfinebinCent", 80.0, "higher bin value in cent fine histograms"}; + Configurable TimefineNbins{"TimefineNbins", 120, "Number of bins in Time fine histograms"}; + Configurable lfinebinTime{"lfinebinTime", 0, "lower bin value in Time fine histograms"}; + Configurable hfinebinTime{"hfinebinTime", 120, "higher bin value in Time fine histograms"}; } configbins; Configurable useShift{"useShift", false, "shift histograms"}; @@ -217,6 +221,7 @@ struct spvector { AxisSpec vxfineAxis = {configbins.VxfineNbins, configbins.lfinebinVx, configbins.hfinebinVx, "vxfine"}; AxisSpec vyfineAxis = {configbins.VyfineNbins, configbins.lfinebinVy, configbins.hfinebinVy, "vyfine"}; AxisSpec centfineAxis = {configbins.CentfineNbins, configbins.lfinebinCent, configbins.hfinebinCent, "V0M (%) fine"}; + AxisSpec timefineAxis = {configbins.TimefineNbins, configbins.lfinebinTime, configbins.hfinebinTime, "timefine"}; AxisSpec shiftAxis = {10, 0, 10, "shift"}; AxisSpec basisAxis = {2, 0, 2, "basis"}; AxisSpec VxyAxis = {2, 0, 2, "Vxy"}; @@ -255,6 +260,11 @@ struct spvector { histos.add("hvzQyZDCA", "hvzQyZDCA", kTH2F, {{vzfineAxis}, {qxZDCAxis}}); histos.add("hvzQxZDCC", "hvzQxZDCC", kTH2F, {{vzfineAxis}, {qxZDCAxis}}); histos.add("hvzQyZDCC", "hvzQyZDCC", kTH2F, {{vzfineAxis}, {qxZDCAxis}}); + + histos.add("htimeQxZDCA", "htimeQxZDCA", kTH2F, {{timefineAxis}, {qxZDCAxis}}); + histos.add("htimeQyZDCA", "htimeQyZDCA", kTH2F, {{timefineAxis}, {qxZDCAxis}}); + histos.add("htimeQxZDCC", "htimeQxZDCC", kTH2F, {{timefineAxis}, {qxZDCAxis}}); + histos.add("htimeQyZDCC", "htimeQyZDCC", kTH2F, {{timefineAxis}, {qxZDCAxis}}); } histos.add("PsiZDCC", "PsiZDCC", kTH2F, {centfineAxis, phiAxis}); @@ -424,6 +434,17 @@ struct spvector { histos.fill(HIST("hEvtSelInfo"), 1.5); + const uint64_t timestampzdc = bc.timestamp(); // in milliseconds + + // Convert timestamp to hours from run start (approximate) + // Store first timestamp of run to calculate relative time + static std::unordered_map runStartTime; + if (runStartTime.find(currentRunNumber) == runStartTime.end()) { + runStartTime[currentRunNumber] = timestampzdc; + } + + double timeInMinutes = (timestampzdc - runStartTime[currentRunNumber]) / 60000.0; // ms -> minutes + auto zdc = bc.zdc(); auto zncEnergy = zdc.energySectorZNC(); auto znaEnergy = zdc.energySectorZNA(); @@ -750,6 +771,11 @@ struct spvector { histos.fill(HIST("hvzQyZDCA"), vz, qyZDCA); histos.fill(HIST("hvzQxZDCC"), vz, qxZDCC); histos.fill(HIST("hvzQyZDCC"), vz, qyZDCC); + + histos.fill(HIST("htimeQxZDCA"), timeInMinutes, qxZDCA); + histos.fill(HIST("htimeQyZDCA"), timeInMinutes, qyZDCA); + histos.fill(HIST("htimeQxZDCC"), timeInMinutes, qxZDCC); + histos.fill(HIST("htimeQyZDCC"), timeInMinutes, qyZDCC); } histos.fill(HIST("hpCosPsiAPsiC"), centrality, (TMath::Cos(psiZDCA - psiZDCC))); diff --git a/PWGLF/TableProducer/Common/zdcvector.cxx b/PWGLF/TableProducer/Common/zdcvector.cxx index 2d4627a36d9..dd1b9860d05 100644 --- a/PWGLF/TableProducer/Common/zdcvector.cxx +++ b/PWGLF/TableProducer/Common/zdcvector.cxx @@ -58,6 +58,7 @@ using BCsRun3 = soa::Join; struct zdcvector { Produces zdccaltable; + Produces zdcenergytable; // Configurables. struct : ConfigurableGroup { @@ -98,6 +99,8 @@ struct zdcvector { Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; } rctCut; + Configurable storeZdcEnergy{"storeZdcEnergy", true, "Store ZDC tower/common energies in a linked extra table"}; + RCTFlagsChecker rctChecker; void init(o2::framework::InitContext&) @@ -137,8 +140,8 @@ struct zdcvector { int currentRunNumber = -999; int lastRunNumber = -999; - TH2D* gainprofile; - TProfile* gainprofilevxy; + TH2D* gainprofile = nullptr; + TProfile* gainprofilevxy = nullptr; // int lastRunNumberTimeRec = -999; // for time since start of run @@ -176,35 +179,84 @@ struct zdcvector { auto sumA = 0.0; auto sumC = 0.0; + // default values for events without ZDC + float znaEnergycommon = 0.f; + float zncEnergycommon = 0.f; + + float zna0 = 0.f; + float zna1 = 0.f; + float zna2 = 0.f; + float zna3 = 0.f; + + float znc0 = 0.f; + float znc1 = 0.f; + float znc2 = 0.f; + float znc3 = 0.f; + auto bc = collision.foundBC_as(); + // Helper to keep your early-return structure unchanged. + // Every time ZDCCalTables is filled, the optional linked energy table is also filled. + auto fillTables = [&](bool trigger, + float qxA, + float qxC, + float qyA, + float qyC) { + zdccaltable(trigger, + currentRunNumber, + centrality, + vx, + vy, + vz, + qxA, + qxC, + qyA, + qyC); + + if (storeZdcEnergy) { + zdcenergytable(zdccaltable.lastIndex(), + znaEnergycommon, + zncEnergycommon, + zna0, + zna1, + zna2, + zna3, + znc0, + znc1, + znc2, + znc3); + } + }; + if (!bc.has_zdc()) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } - // -------- define time since run start -------- - /*uint64_t ts = bc.timestamp(); - if (currentRunNumber != runForStartTime) { - runStartTime = ts; - runForStartTime = currentRunNumber; - } - double tsec = 1.e-3 * static_cast(ts - runStartTime); - */ histos.fill(HIST("hEvtSelInfo"), 1.5); auto zdc = bc.zdc(); auto zncEnergy = zdc.energySectorZNC(); auto znaEnergy = zdc.energySectorZNA(); - auto zncEnergycommon = zdc.energyCommonZNC(); - auto znaEnergycommon = zdc.energyCommonZNA(); + zncEnergycommon = zdc.energyCommonZNC(); + znaEnergycommon = zdc.energyCommonZNA(); auto beamEne = 5.36 * 0.5; + zna0 = znaEnergy[0]; + zna1 = znaEnergy[1]; + zna2 = znaEnergy[2]; + zna3 = znaEnergy[3]; + + znc0 = zncEnergy[0]; + znc1 = zncEnergy[1]; + znc2 = zncEnergy[2]; + znc3 = zncEnergy[3]; if (znaEnergycommon <= 0.0 || zncEnergycommon <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); return; } @@ -212,16 +264,16 @@ struct zdcvector { if (znaEnergy[0] <= 0.0 || znaEnergy[1] <= 0.0 || znaEnergy[2] <= 0.0 || znaEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); return; } histos.fill(HIST("hEvtSelInfo"), 3.5); if (zncEnergy[0] <= 0.0 || zncEnergy[1] <= 0.0 || zncEnergy[2] <= 0.0 || zncEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); return; } @@ -229,25 +281,17 @@ struct zdcvector { if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); return; } histos.fill(HIST("hEvtSelInfo"), 5.5); - /*histos.fill(HIST("hZNA0"), centrality, znaEnergy[0]); - histos.fill(HIST("hZNA1"), centrality, znaEnergy[1]); - histos.fill(HIST("hZNA2"), centrality, znaEnergy[2]); - histos.fill(HIST("hZNA3"), centrality, znaEnergy[3]); - histos.fill(HIST("hZNC0"), centrality, zncEnergy[0]); - histos.fill(HIST("hZNC1"), centrality, zncEnergy[1]); - histos.fill(HIST("hZNC2"), centrality, zncEnergy[2]); - histos.fill(HIST("hZNC3"), centrality, zncEnergy[3]);*/ if (additionalEvSel && (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } @@ -284,7 +328,8 @@ struct zdcvector { if (znaEnergy[iChA] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } else { double ampl = gainequal * znaEnergy[iChA]; @@ -300,8 +345,8 @@ struct zdcvector { } else { if (zncEnergy[iChA - 4] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } else { double ampl = gainequal * zncEnergy[iChA - 4]; @@ -345,8 +390,8 @@ struct zdcvector { qyZDCA = 0.0; qyZDCC = 0.0; triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); - // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + fillTables(triggerevent, 0.f, 0.f, 0.f, 0.f); return; } @@ -370,7 +415,12 @@ struct zdcvector { lastRunNumber = currentRunNumber; } - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, qxZDCA, qxZDCC, qyZDCA, qyZDCC); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, qxZDCA, qxZDCC, qyZDCA, qyZDCC); + fillTables(triggerevent, + qxZDCA, + qxZDCC, + qyZDCA, + qyZDCC); } }; From f0fa6efffc115540d1772f917a0cf3cfb33234b1 Mon Sep 17 00:00:00 2001 From: swapneshkhade <107178389+swapneshkhade@users.noreply.github.com> Date: Sun, 3 May 2026 13:07:39 +0530 Subject: [PATCH 010/449] [PWGHF] This PR adds D0-specific derived tables for offline event mixing in the D0-hadron correlator (#16063) --- PWGHF/HFC/DataModel/CorrelationTables.h | 51 +++++++++++++++ .../HFC/TableProducer/correlatorD0Hadrons.cxx | 65 +++++++++++++++++-- 2 files changed, 112 insertions(+), 4 deletions(-) diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index 83470e9f26c..c366a3e4186 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -51,6 +51,57 @@ DECLARE_SOA_TABLE(DDbarRecoInfo, "AOD", "DDBARRECOINFO", aod::hf_correlation_d_dbar::MDbar, aod::hf_correlation_d_dbar::SignalStatus); +// Table to store event by event D meson selection information for event mixing in D-hadron correlation analysis +namespace hf_d0_meson +{ +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(PtD, ptD, float); +DECLARE_SOA_COLUMN(MD, mD, float); +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); +DECLARE_SOA_COLUMN(GIndexCol, gIndexCol, int); +DECLARE_SOA_COLUMN(TimeStamp, timeStamp, int64_t); +DECLARE_SOA_COLUMN(SignalStatus, signalStatus, int); +} // namespace hf_d0_meson + +DECLARE_SOA_TABLE(D0, "AOD", "D0", + aod::hf_d0_meson::Phi, + aod::hf_d0_meson::Eta, + aod::hf_d0_meson::PtD, + aod::hf_d0_meson::MD, + aod::hf_d0_meson::PoolBin, + aod::hf_d0_meson::GIndexCol, + aod::hf_d0_meson::TimeStamp, + aod::hf_d0_meson::SignalStatus); + +// Table to store event-by-event associated tracks for offline D0-hadron event mixing +namespace hf_d0_assoc_tracks +{ +DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi of hadron +DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta of hadron +DECLARE_SOA_COLUMN(PtH, ptH, float); //! Transverse momentum of hadron +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity +DECLARE_SOA_COLUMN(GIndexCol, gIndexCol, int); //! Global index for the collision +DECLARE_SOA_COLUMN(TimeStamp, timeStamp, int64_t); //! Timestamp for the collision +DECLARE_SOA_COLUMN(SoftPiStatus, softPiStatus, int); //! Soft-pion status for D0 offline mixing + +enum SoftPionStatus { + NotSoftPi = 0, + SoftPiD0 = 1, + SoftPiD0bar = 2, + SoftPiD0D0bar = 3 +}; +} // namespace hf_d0_assoc_tracks + +DECLARE_SOA_TABLE(D0Hadron, "AOD", "D0HADRON", + aod::hf_d0_assoc_tracks::Phi, + aod::hf_d0_assoc_tracks::Eta, + aod::hf_d0_assoc_tracks::PtH, + aod::hf_d0_assoc_tracks::PoolBin, + aod::hf_d0_assoc_tracks::GIndexCol, + aod::hf_d0_assoc_tracks::TimeStamp, + aod::hf_d0_assoc_tracks::SoftPiStatus); + // definition of columns and tables for D0-Hadron correlation pairs namespace hf_correlation_d0_hadron { diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index 85ec82b5ed9..23161549f4f 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -214,6 +214,8 @@ struct HfCorrelatorD0Hadrons { Produces entryD0CandRecoInfo; Produces entryD0CandGenInfo; Produces entryTrackRecoInfo; + Produces entryD0; + Produces entryD0Hadron; Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; @@ -283,9 +285,9 @@ struct HfCorrelatorD0Hadrons { AxisSpec const axisSignalStatus = {200, 0., 200., "Signal status"}; AxisSpec axisEvtCount = {1, -0.5, 0.5}; AxisSpec const axisTrkCount = {5, 0., 5.}; - AxisSpec axisBdtScoreBkg = {100, 0., 1., "Bdt score background"}; - AxisSpec axisBdtScorePrompt = {100, 0., 1., "Bdt score prompt"}; - AxisSpec axisBdtScoreNonPrompt = {100, 0., 1., "Bdt score Nonprompt"}; + AxisSpec axisBdtScoreBkg = {500, 0., 1., "Bdt score background"}; + AxisSpec axisBdtScorePrompt = {200, 0., 1., "Bdt score prompt"}; + AxisSpec axisBdtScoreNonPrompt = {200, 0., 1., "Bdt score Nonprompt"}; AxisSpec axisOrigin = {10, 0., 10., "Candidate origin"}; AxisSpec axisCent = {binsCentFt0m, "Centrality"}; @@ -306,6 +308,9 @@ struct HfCorrelatorD0Hadrons { registry.add("hMassD0bar1D", "D0bar candidates mass", {HistType::kTH1F, {axisMassD}}); registry.add("hMassD0VsPtVsCent", "D0 candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH3F, {{axisMassD}, {axisPtD}, {axisCent}}}); registry.add("hMLScoresVsMassVsPtVsEtaVsOriginVsCent", "D0, D0bar candidates BkgVspromptVsNonPromptVsMassVsPtVsEtaVsOrigin", {HistType::kTHnSparseD, {{axisBdtScoreBkg}, {axisBdtScorePrompt}, {axisBdtScoreNonPrompt}, {axisMassD}, {axisPtD}, {axisEta}, {axisOrigin}, {axisCent}}}); + registry.add("hTracksBeforeSoftMix", "Tracks before soft pion reject offline mixing", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hTracksAfterSoftMix", "Tracks after soft pion reject offline mixing", {HistType::kTH1F, {axisPtHadron}}); + // Histograms for MC Reco registry.add("hPtCandRec", "D0, D0bar candidates - MC reco", {HistType::kTH1F, {axisPtD}}); registry.add("hPtProng0Rec", "D0, D0bar candidates prong 0 - MC reco", {HistType::kTH1F, {axisPtD}}); @@ -359,9 +364,15 @@ struct HfCorrelatorD0Hadrons { /// D0-h correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) void processData(SelectedCollisions::iterator const& collision, SelectedTracks const& tracks, - SelectedCandidatesDataMl const& candidates) + SelectedCandidatesDataMl const& candidates, + aod::BCsWithTimestamps const&) { BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; + + auto bc = collision.bc_as(); + int gCollisionId = collision.globalIndex(); + int64_t timeStamp = bc.timestamp(); + // find leading particle if (correlateD0WithLeadingParticle) { leadingIndex = findLeadingParticle(tracks, etaTrackMax.value); @@ -397,6 +408,30 @@ struct HfCorrelatorD0Hadrons { std::vector outputMlD0 = {-1., -1., -1.}; std::vector outputMlD0bar = {-1., -1., -1.}; + std::vector softPionTrackIdsForOfflineMixing; + std::vector softPionStatusesForOfflineMixing; + bool hasAcceptedD0ForOfflineMixing = false; + + auto addSoftPionTrackForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId, int softPiStatus) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + softPionStatusesForOfflineMixing[iTrack] |= softPiStatus; + return; + } + } + softPionTrackIdsForOfflineMixing.push_back(trackId); + softPionStatusesForOfflineMixing.push_back(softPiStatus); + }; + + auto getSoftPionStatusForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + return softPionStatusesForOfflineMixing[iTrack]; + } + } + return static_cast(aod::hf_d0_assoc_tracks::NotSoftPi); + }; + for (const auto& candidate : candidates) { if (std::abs(HfHelper::yD0(candidate)) >= yCandMax || candidate.pt() <= ptCandMin || candidate.pt() >= ptTrackMax) { continue; @@ -420,6 +455,10 @@ struct HfCorrelatorD0Hadrons { const auto invMassD0 = HfHelper::invMassD0ToPiK(candidate); const auto invMassD0bar = HfHelper::invMassD0barToKPi(candidate); + if (candidate.isSelD0() >= selectionFlagD0 || candidate.isSelD0bar() >= selectionFlagD0bar) { + hasAcceptedD0ForOfflineMixing = true; + } + // ========================== Fill mass histo ================================ if (candidate.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMass"), invMassD0, candidate.pt(), efficiencyWeight); @@ -430,6 +469,7 @@ struct HfCorrelatorD0Hadrons { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only, cent, efficiencyWeight); + entryD0(candidate.phi(), candidate.eta(), candidate.pt(), invMassD0, poolBin, gCollisionId, timeStamp, (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMass"), invMassD0bar, candidate.pt(), efficiencyWeight); @@ -440,6 +480,7 @@ struct HfCorrelatorD0Hadrons { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly, cent, efficiencyWeight); + entryD0(candidate.phi(), candidate.eta(), candidate.pt(), invMassD0bar, poolBin, gCollisionId, timeStamp, (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); @@ -477,12 +518,14 @@ struct HfCorrelatorD0Hadrons { if (candidate.isSelD0() >= selectionFlagD0) { if ((std::abs(invMassDstar1 - invMassD0) - softPiMass) < ptSoftPionMax) { + addSoftPionTrackForOfflineMixing(track.globalIndex(), aod::hf_d0_assoc_tracks::SoftPiD0); continue; } } if (candidate.isSelD0bar() >= selectionFlagD0bar) { if ((std::abs(invMassDstar2 - invMassD0bar) - softPiMass) < ptSoftPionMax) { + addSoftPionTrackForOfflineMixing(track.globalIndex(), aod::hf_d0_assoc_tracks::SoftPiD0bar); continue; } } @@ -518,6 +561,20 @@ struct HfCorrelatorD0Hadrons { } // end inner loop (tracks) } // end outer loop + + // loop to save tables for offline event mixing + if (hasAcceptedD0ForOfflineMixing) { + for (const auto& track : tracks) { + const auto softPiStatus = getSoftPionStatusForOfflineMixing(track.globalIndex()); + + registry.fill(HIST("hTracksBeforeSoftMix"), track.pt()); + if (softPiStatus == aod::hf_d0_assoc_tracks::NotSoftPi) { + registry.fill(HIST("hTracksAfterSoftMix"), track.pt()); + } + + entryD0Hadron(track.phi(), track.eta(), track.pt(), poolBin, gCollisionId, timeStamp, softPiStatus); + } + } } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processData, "Process data", false); From d296ece8833cf9d0cae793869638cd83f654f837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Sun, 3 May 2026 10:36:46 +0200 Subject: [PATCH 011/449] [ALICE3] Add covariance histograms for track performance (#16068) --- ALICE3/Tasks/alice3TrackingPerformance.cxx | 46 +++++++++++++--------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/ALICE3/Tasks/alice3TrackingPerformance.cxx b/ALICE3/Tasks/alice3TrackingPerformance.cxx index 81470ee2d2e..bb47ffde7da 100644 --- a/ALICE3/Tasks/alice3TrackingPerformance.cxx +++ b/ALICE3/Tasks/alice3TrackingPerformance.cxx @@ -52,20 +52,25 @@ std::map> invPtResolutionVsPt; std::map> invPtResolutionVsEta; std::map> dcaXyResolutionVsPt; std::map> dcaZResolutionVsPt; +std::map> covariancePtPtVsPt; +std::map> covarianceDcaXyDcaXyVsPt; +std::map> covarianceDcaZDcaZVsPt; struct Alice3TrackingPerformance { Configurable> pdgCodes{"pdgCodes", {0, 211}, "List of PDG codes to consider for efficiency calculation. (0 means all)"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Configurable> etaRange{"etaRange", {-5.f, 5.f}, "Eta range for efficiency calculation"}; + ConfigurableAxis ptAxis{"ptAxis", {500, 0, 100}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis etaAxis{"etaAxis", {100, -5.f, 5.f}, "#eta"}; + ConfigurableAxis invPtDeltaAxis{"invPtDeltaAxis", {1000, -0.1f, 0.1f}, "1./#it{p}_{T}^{gen} - 1./#it{p}_{T}^{reco} (GeV/#it{c})^{-1}"}; void init(o2::framework::InitContext&) { - const AxisSpec axisPt{500, 0, 100, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axisEta{100, etaRange.value.first, etaRange.value.second, "#eta"}; const AxisSpec axisPtDelta{100, -1, 1, "(#it{p}_{T}^{reco} - #it{p}_{T}^{gen}) / #it{p}_{T}^{gen}"}; - const AxisSpec axisInvPtDelta{100, -1, 1, "1./#it{p}_{T}^{gen} - 1./#it{p}_{T}^{reco} (GeV/#it{c})^{-1}"}; const AxisSpec axisDcaXy{100, -1, 1, "DCA_{xy} (cm)"}; const AxisSpec axisDcaZ{100, -1, 1, "DCA_{z} (cm)"}; + const AxisSpec axisCovariancePtPt{100, 0, 10, "cov(#it{p}_{T}, #it{p}_{T}) ((GeV/#it{c})^{2})"}; + const AxisSpec axisCovarianceDcaXyDcaXy{100, 0, 1, "cov(DCA_{xy}, DCA_{xy}) (cm^{2})"}; + const AxisSpec axisCovarianceDcaZDcaZ{100, 0, 1, "cov(DCA_{z}, DCA_{z}) (cm^{2})"}; particlePdgCodes = histos.add("particlePdgCodes", "", kTH1D, {AxisSpec{100, -0.5, 99.5, "PDG Code"}}); for (const int& pdg : pdgCodes.value) { std::string prefix = Form("%i", pdg); @@ -74,30 +79,31 @@ struct Alice3TrackingPerformance { } const std::string tag = "_" + prefix; prefix += "/"; - particlePtDistribution[pdg] = histos.add(prefix + "particlePtDistribution" + tag, "", kTH1D, {axisPt}); - particleEtaDistribution[pdg] = histos.add(prefix + "particleEtaDistribution" + tag, "", kTH1D, {axisEta}); + particlePtDistribution[pdg] = histos.add(prefix + "particlePtDistribution" + tag, "", kTH1D, {ptAxis}); + particleEtaDistribution[pdg] = histos.add(prefix + "particleEtaDistribution" + tag, "", kTH1D, {etaAxis}); - ptDistribution[pdg] = histos.add(prefix + "ptDistribution" + tag, "", kTH1D, {axisPt}); - ptResolutionVsPt[pdg] = histos.add(prefix + "ptResolutionVsPt" + tag, "", kTH2D, {axisPt, axisPtDelta}); - ptResolutionVsEta[pdg] = histos.add(prefix + "ptResolutionVsEta" + tag, "", kTProfile2D, {axisPt, axisEta}); - invPtResolutionVsPt[pdg] = histos.add(prefix + "invPtResolutionVsPt" + tag, "", kTH2D, {axisPt, axisInvPtDelta}); - invPtResolutionVsEta[pdg] = histos.add(prefix + "invPtResolutionVsEta" + tag, "", kTProfile2D, {axisPt, axisEta}); - dcaXyResolutionVsPt[pdg] = histos.add(prefix + "dcaXyResolutionVsPt" + tag, "", kTH2D, {axisPt, axisDcaXy}); - dcaZResolutionVsPt[pdg] = histos.add(prefix + "dcaZResolutionVsPt" + tag, "", kTH2D, {axisPt, axisDcaZ}); + ptDistribution[pdg] = histos.add(prefix + "ptDistribution" + tag, "", kTH1D, {ptAxis}); + ptResolutionVsPt[pdg] = histos.add(prefix + "ptResolutionVsPt" + tag, "", kTH2D, {ptAxis, axisPtDelta}); + ptResolutionVsEta[pdg] = histos.add(prefix + "ptResolutionVsEta" + tag, "", kTProfile2D, {ptAxis, etaAxis}); + invPtResolutionVsPt[pdg] = histos.add(prefix + "invPtResolutionVsPt" + tag, "", kTH2D, {ptAxis, invPtDeltaAxis}); + invPtResolutionVsEta[pdg] = histos.add(prefix + "invPtResolutionVsEta" + tag, "", kTProfile2D, {ptAxis, etaAxis}); + dcaXyResolutionVsPt[pdg] = histos.add(prefix + "dcaXyResolutionVsPt" + tag, "", kTH2D, {ptAxis, axisDcaXy}); + dcaZResolutionVsPt[pdg] = histos.add(prefix + "dcaZResolutionVsPt" + tag, "", kTH2D, {ptAxis, axisDcaZ}); + covariancePtPtVsPt[pdg] = histos.add(prefix + "covariancePtPtVsPt" + tag, "", kTH2D, {ptAxis, axisCovariancePtPt}); + covarianceDcaXyDcaXyVsPt[pdg] = histos.add(prefix + "covarianceDcaXyDcaXyVsPt" + tag, "", kTH2D, {ptAxis, axisCovarianceDcaXyDcaXy}); + covarianceDcaZDcaZVsPt[pdg] = histos.add(prefix + "covarianceDcaZDcaZVsPt" + tag, "", kTH2D, {ptAxis, axisCovarianceDcaZDcaZ}); } } - void process(soa::Join const& tracks, + void process(soa::Join const& tracks, aod::McParticles const& mcParticles) { auto isParticleSelected = [&](const o2::aod::McParticle& p) { if (!p.isPhysicalPrimary()) { return false; } - if (p.eta() < etaRange.value.first) { - return false; - } - if (p.eta() > etaRange.value.second) { + const int etaBin = particleEtaDistribution[0]->GetXaxis()->FindBin(p.eta()); + if (etaBin < 1 || etaBin > particleEtaDistribution[0]->GetXaxis()->GetNbins()) { return false; } return true; @@ -123,6 +129,7 @@ struct Alice3TrackingPerformance { const auto& mcParticle = track.mcParticle(); const float ptResolution = (track.pt() - mcParticle.pt()) / mcParticle.pt(); const float invptResolution = 1.f / track.pt() - 1.f / mcParticle.pt(); + const float covariancePtPt = track.sigma1Pt() * track.sigma1Pt() * track.pt() * track.pt() * track.pt() * track.pt(); auto fillResolutionHistograms = [&](const int p) { ptDistribution[p]->Fill(track.pt()); @@ -132,6 +139,9 @@ struct Alice3TrackingPerformance { invPtResolutionVsEta[p]->Fill(mcParticle.pt(), mcParticle.eta(), invptResolution); dcaXyResolutionVsPt[p]->Fill(mcParticle.pt(), track.dcaXY()); dcaZResolutionVsPt[p]->Fill(mcParticle.pt(), track.dcaZ()); + covariancePtPtVsPt[p]->Fill(mcParticle.pt(), covariancePtPt); + covarianceDcaXyDcaXyVsPt[p]->Fill(mcParticle.pt(), track.sigmaDcaXY2()); + covarianceDcaZDcaZVsPt[p]->Fill(mcParticle.pt(), track.sigmaDcaZ2()); }; fillResolutionHistograms(0); From deb8226241ce7277b7370618f4e0634ed4425664 Mon Sep 17 00:00:00 2001 From: HANSEO PARK <53218370+hanseopark@users.noreply.github.com> Date: Sun, 3 May 2026 18:33:05 +0900 Subject: [PATCH 012/449] [PWGJE] Modification 3-prong to n-prong for b-jet (#16044) --- PWGJE/DataModel/JetTagging.h | 11 +- PWGJE/TableProducer/jetTaggerHF.cxx | 10 +- .../secondaryVertexReconstruction.cxx | 133 ++++- PWGJE/Tasks/bjetCentMult.cxx | 168 +++---- PWGJE/Tasks/jetTaggerHFQA.cxx | 455 ++++-------------- 5 files changed, 315 insertions(+), 462 deletions(-) diff --git a/PWGJE/DataModel/JetTagging.h b/PWGJE/DataModel/JetTagging.h index a6b32458543..9ce0ddadb6f 100644 --- a/PWGJE/DataModel/JetTagging.h +++ b/PWGJE/DataModel/JetTagging.h @@ -49,9 +49,9 @@ using JTrackTag = JTracksTag::iterator; namespace secondary_vertex_params { -DECLARE_SOA_COLUMN(XPrimaryVertex, xPVertex, float); // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(YPrimaryVertex, yPVertex, float); // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZPrimaryVertex, zPVertex, float); // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(XPrimaryVertex, xPrimaryVertex, float); +DECLARE_SOA_COLUMN(YPrimaryVertex, yPrimaryVertex, float); +DECLARE_SOA_COLUMN(ZPrimaryVertex, zPrimaryVertex, float); DECLARE_SOA_COLUMN(XSecondaryVertex, xSecondaryVertex, float); DECLARE_SOA_COLUMN(YSecondaryVertex, ySecondaryVertex, float); DECLARE_SOA_COLUMN(ZSecondaryVertex, zSecondaryVertex, float); @@ -75,7 +75,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, [](float xVtxP, float yVtxP DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXY, decayLengthXY, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS) -> float { return RecoDecay::distanceXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}); }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthNormalised, decayLengthNormalised, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float err) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}) / err; }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float err) -> float { return RecoDecay::distanceXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}) / err; }); -DECLARE_SOA_DYNAMIC_COLUMN(CPA, cpa, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); // o2-linter: disable=name/o2-column +DECLARE_SOA_DYNAMIC_COLUMN(Cpa, cpa, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); } // namespace secondary_vertex_params @@ -113,7 +113,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, [](float xVtxP, secondary_vertex_params::DecayLengthXY, \ secondary_vertex_params::DecayLengthNormalised, \ secondary_vertex_params::DecayLengthXYNormalised, \ - secondary_vertex_params::CPA, \ + secondary_vertex_params::Cpa, \ secondary_vertex_params::ImpactParameterXY); \ namespace _name_##indices \ { \ @@ -127,6 +127,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, [](float xVtxP, JETSV_TABLES_DEF(Charged, SecondaryVertex3Prong, "3PRONG"); JETSV_TABLES_DEF(Charged, SecondaryVertex2Prong, "2PRONG"); +JETSV_TABLES_DEF(Charged, SecondaryVertexNProng, "NPRONG"); // Defines the jet tagging table definition namespace jettagging diff --git a/PWGJE/TableProducer/jetTaggerHF.cxx b/PWGJE/TableProducer/jetTaggerHF.cxx index 10cbcef6286..bd8625b676c 100644 --- a/PWGJE/TableProducer/jetTaggerHF.cxx +++ b/PWGJE/TableProducer/jetTaggerHF.cxx @@ -732,13 +732,15 @@ struct JetTaggerHFTask { PROCESS_SWITCH(JetTaggerHFTask, processFillTables, "Fill Tables for tagging decision, jet probability, and ML score on charged jets", false); }; -using JetTaggerhfDataCharged = JetTaggerHFTask, aod::DataSecondaryVertex3ProngIndices, aod::DataSecondaryVertex3Prongs, aod::ChargedJetTags>; -using JetTaggerhfMCDCharged = JetTaggerHFTask, aod::MCDSecondaryVertex3ProngIndices, aod::MCDSecondaryVertex3Prongs, aod::ChargedMCDetectorLevelJetTags>; +using JetTaggerhfDataCharged = JetTaggerHFTask, aod::DataSecondaryVertexNProngIndices, aod::DataSecondaryVertexNProngs, aod::ChargedJetTags>; +using JetTaggerhfMcdCharged = JetTaggerHFTask, aod::MCDSecondaryVertexNProngIndices, aod::MCDSecondaryVertexNProngs, aod::ChargedMCDetectorLevelJetTags>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-taggerhf-data-charged"}), // o2-linter: disable=name/o2-task - adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-taggerhf-mcd-charged"})}; // o2-linter: disable=name/o2-task + adaptAnalysisTask( + cfgc, SetDefaultProcesses{}, TaskName{"jet-taggerhf-data-charged"}), // o2-linter: disable=name/o2-task (custom device name for templated task alias) + adaptAnalysisTask( + cfgc, SetDefaultProcesses{}, TaskName{"jet-taggerhf-mcd-charged"})}; // o2-linter: disable=name/o2-task (custom device name for templated task alias) } diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index 36c17f77ec5..c1ee4dd3b73 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -63,12 +63,19 @@ struct SecondaryVertexReconstruction { Produces sv2prongTableData; Produces sv2prongIndicesTableData; + Produces svnprongTableData; + Produces svnprongIndicesTableData; + Produces sv3prongTableMCD; Produces sv3prongIndicesTableMCD; Produces sv2prongTableMCD; Produces sv2prongIndicesTableMCD; + Produces svnprongTableMCD; + Produces svnprongIndicesTableMCD; + + Configurable nProng{"nProng", 3, "number of prong"}; Configurable magneticField{"magneticField", 20.0f, "magnetic field in kG"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; @@ -241,43 +248,77 @@ struct SecondaryVertexReconstruction { std::fill(massArray.begin(), massArray.end(), o2::constants::physics::MassPiPlus); double massSV = RecoDecay::m(arrayMomenta, massArray); + // calculate momentum + double xMomenta = -1; + double yMomenta = -1; + double zMomenta = -1; + if (numProngs == ThreeProngCount) { + xMomenta = arrayMomenta[0][0] + arrayMomenta[1][0] + arrayMomenta[2][0]; + yMomenta = arrayMomenta[0][1] + arrayMomenta[1][1] + arrayMomenta[2][1]; + zMomenta = arrayMomenta[0][2] + arrayMomenta[1][2] + arrayMomenta[2][2]; + } else if (numProngs == TwoProngCount) { + xMomenta = arrayMomenta[0][0] + arrayMomenta[1][0]; + yMomenta = arrayMomenta[0][1] + arrayMomenta[1][1]; + zMomenta = arrayMomenta[0][2] + arrayMomenta[1][2]; + } else { + LOG(error) << "No process momenta\n"; + } + // fill candidate table rows if ((doprocessData3Prongs || doprocessData3ProngsExternalMagneticField) && numProngs == ThreeProngCount) { sv3prongTableData(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], - arrayMomenta[0][0] + arrayMomenta[1][0] + arrayMomenta[2][0], - arrayMomenta[0][1] + arrayMomenta[1][1] + arrayMomenta[2][1], - arrayMomenta[0][2] + arrayMomenta[1][2] + arrayMomenta[2][2], + xMomenta, + yMomenta, + zMomenta, energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv3prongTableData.lastIndex()); } else if ((doprocessData2Prongs || doprocessData2ProngsExternalMagneticField) && numProngs == TwoProngCount) { sv2prongTableData(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], - arrayMomenta[0][0] + arrayMomenta[1][0], - arrayMomenta[0][1] + arrayMomenta[1][1], - arrayMomenta[0][2] + arrayMomenta[1][2], + xMomenta, + yMomenta, + zMomenta, energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv2prongTableData.lastIndex()); + } else if ((doprocessDataNProngs || doprocessDataNProngsExternalMagneticField) && numProngs == TwoProngCount) { + svnprongTableData(analysisJet.globalIndex(), + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + xMomenta, + yMomenta, + zMomenta, + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); + svIndices.push_back(svnprongTableData.lastIndex()); } else if ((doprocessMCD3Prongs || doprocessMCD3ProngsExternalMagneticField) && numProngs == ThreeProngCount) { sv3prongTableMCD(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], - arrayMomenta[0][0] + arrayMomenta[1][0] + arrayMomenta[2][0], - arrayMomenta[0][1] + arrayMomenta[1][1] + arrayMomenta[2][1], - arrayMomenta[0][2] + arrayMomenta[1][2] + arrayMomenta[2][2], + xMomenta, + yMomenta, + zMomenta, energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv3prongTableMCD.lastIndex()); } else if ((doprocessMCD2Prongs || doprocessMCD2ProngsExternalMagneticField) && numProngs == TwoProngCount) { sv2prongTableMCD(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], - arrayMomenta[0][0] + arrayMomenta[1][0], - arrayMomenta[0][1] + arrayMomenta[1][1], - arrayMomenta[0][2] + arrayMomenta[1][2], + xMomenta, + yMomenta, + zMomenta, energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv2prongTableMCD.lastIndex()); + } else if (doprocessMCDNProngs || doprocessMCDNProngsExternalMagneticField) { + svnprongTableMCD(analysisJet.globalIndex(), + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + xMomenta, + yMomenta, + zMomenta, + energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); + svIndices.push_back(svnprongTableMCD.lastIndex()); } else { LOG(error) << "No process specified\n"; } @@ -357,6 +398,40 @@ struct SecondaryVertexReconstruction { } PROCESS_SWITCH(SecondaryVertexReconstruction, processData2ProngsExternalMagneticField, "Reconstruct the data 2-prong secondary vertex with extrernal magnetic field", false); + void processDataNProngs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& jets, JetTracksData const& tracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + { + for (const auto& jet : jets) { + std::vector svIndices; + if (nProng == ThreeProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df3); + svnprongIndicesTableData(svIndices); + } else if (nProng == TwoProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df2); + svnprongIndicesTableData(svIndices); + } else { + LOG(error) << "set number of prong\n"; + } + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processDataNProngs, "Reconstruct the data mult-prong secondary vertex", false); + + void processDataNProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& jets, JetTracksData const& tracks, OriginalTracks const& /*tracks*/) + { + for (const auto& jet : jets) { + std::vector svIndices; + if (nProng == ThreeProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df3); + svnprongIndicesTableData(svIndices); + } else if (nProng == TwoProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df2); + svnprongIndicesTableData(svIndices); + } else { + LOG(error) << "set number of prong\n"; + } + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processDataNProngsExternalMagneticField, "Reconstruct the data mult-prong secondary vertex with extrernal magnetic field", false); + void processMCD3Prongs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& tracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) { for (const auto& jet : mcdjets) { @@ -396,6 +471,40 @@ struct SecondaryVertexReconstruction { } } PROCESS_SWITCH(SecondaryVertexReconstruction, processMCD2ProngsExternalMagneticField, "Reconstruct the MCD 2-prong secondary vertex with external magnetic field", false); + + void processMCDNProngs(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& tracks, OriginalTracks const& /*tracks*/, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + { + for (const auto& jet : mcdjets) { + std::vector svIndices; + if (nProng == ThreeProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df3); + svnprongIndicesTableMCD(svIndices); + } else if (nProng == TwoProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df2); + svnprongIndicesTableMCD(svIndices); + } else { + LOG(error) << "set number of prong\n"; + } + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processMCDNProngs, "Reconstruct the MCD n-prong secondary vertex", false); + + void processMCDNProngsExternalMagneticField(JetCollisionwPIs::iterator const& collision, aod::Collisions const& /*realColl*/, soa::Join const& mcdjets, JetTracksMCDwPIs const& tracks, OriginalTracks const& /*tracks*/) + { + for (const auto& jet : mcdjets) { + std::vector svIndices; + if (nProng == ThreeProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df3); + svnprongIndicesTableMCD(svIndices); + } else if (nProng == TwoProngCount) { + runCreatorNProng(collision.template collision_as(), jet, tracks, svIndices, df2); + svnprongIndicesTableMCD(svIndices); + } else { + LOG(error) << "set number of prong\n"; + } + } + } + PROCESS_SWITCH(SecondaryVertexReconstruction, processMCDNProngsExternalMagneticField, "Reconstruct the MCD n-prong secondary vertex with external magnetic field", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/bjetCentMult.cxx b/PWGJE/Tasks/bjetCentMult.cxx index 8bd8111b200..fa0beb6081d 100644 --- a/PWGJE/Tasks/bjetCentMult.cxx +++ b/PWGJE/Tasks/bjetCentMult.cxx @@ -143,80 +143,80 @@ struct BjetCentMultTask { registry.add("h_scaled_FT0M_class", "", {HistType::kTH1F, {{axisMultScaledFT0MClass}}}); registry.add("h2_centrality_percentile_multiplicity", "mcd collision centrality; centrality; counts", {HistType::kTH2F, {{axisRebinnedCentrality}, {axisPercentileMultiplicity}}}); } - if (doprocessSV3ProngData) { - registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + if (doprocessSVData) { + registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h2_jet_pt_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); registry.add("h2_jet_eta_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); registry.add("h2_jet_phi_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); if (fillGeneralSVQA) { - registry.add("h2_3prong_nprongs_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); - registry.add("hn_jet_3prong_Sxy_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); + registry.add("h2_nprongs_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); } } - registry.add("hn_jet_3prong_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); } } - if (doprocessRhoAreaSubSV3ProngData) { + if (doprocessRhoAreaSubSVData) { registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h2_jet_pt_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); registry.add("h2_jet_eta_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); registry.add("h2_jet_phi_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); if (fillGeneralSVQA) { - registry.add("h2_3prong_nprongs_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); - registry.add("hn_jet_3prong_Sxy_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); + registry.add("h2_nprongs_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); } } - registry.add("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); } } - if (doprocessSV3ProngMCD || doprocessSV3ProngMCPMCDMatched) { + if (doprocessSVMCD || doprocessSVMCPMCDMatched) { registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h3_jet_pt_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); registry.add("h3_jet_eta_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); registry.add("h3_jet_phi_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); if (fillGeneralSVQA) { - registry.add("h3_3prong_nprongs_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_jet_3prong_Sxy_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_nprongs_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); } } - registry.add("hn_jet_3prong_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); } } - if (doprocessRhoAreaSubSV3ProngMCD || doprocessRhoAreaSubSV3ProngMCPMCDMatched) { + if (doprocessRhoAreaSubSVMCD || doprocessRhoAreaSubSVMCPMCDMatched) { registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h3_jet_pt_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); registry.add("h3_jet_eta_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); registry.add("h3_jet_phi_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); if (fillGeneralSVQA) { - registry.add("h3_3prong_nprongs_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_jet_3prong_Sxy_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_nprongs_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); } } - registry.add("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); } } } @@ -332,7 +332,7 @@ struct BjetCentMultTask { } template - void fillRhoAreaSubtractedHistogramSV3ProngData(T const& jet, U const& /*prongs*/, float centrality, float rho) + void fillRhoAreaSubtractedHistogramSV(T const& jet, U const& /*prongs*/, float centrality, float rho) { if (jet.template secondaryVertices_as().size() < 1) return; @@ -340,11 +340,11 @@ struct BjetCentMultTask { registry.fill(HIST("h2_jet_eta_rhoareasubtracted_centrality"), jet.eta(), centrality); registry.fill(HIST("h2_jet_phi_rhoareasubtracted_centrality"), jet.phi(), centrality); if (fillGeneralSVQA) { - registry.fill(HIST("h2_3prong_nprongs_rhoareasubtracted_centrality"), jet.template secondaryVertices_as().size(), centrality); + registry.fill(HIST("h2_nprongs_rhoareasubtracted_centrality"), jet.template secondaryVertices_as().size(), centrality); for (const auto& prong : jet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality); + registry.fill(HIST("hn_jet_Sxy_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality); if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality); + registry.fill(HIST("hn_jet_Sxyz_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality); } } } @@ -353,9 +353,9 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxy, massSV, centrality); + registry.fill(HIST("hn_jet_Sxy_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxy, massSV, centrality); if (jet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxy, massSV, centrality); + registry.fill(HIST("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxy, massSV, centrality); } } if (fillSVxyz) { @@ -364,16 +364,16 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxyz, massSV, centrality); + registry.fill(HIST("hn_jet_Sxyz_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxyz, massSV, centrality); if (jet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxyz, massSV, centrality); + registry.fill(HIST("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality"), jet.pt() - (rho * jet.area()), maxSxyz, massSV, centrality); } } } } template - void fillHistogramSV3ProngData(T const& jet, U const& /*prongs*/, float centrality) + void fillHistogramSVData(T const& jet, U const& /*prongs*/, float centrality) { if (jet.template secondaryVertices_as().size() < 1) return; @@ -381,11 +381,11 @@ struct BjetCentMultTask { registry.fill(HIST("h2_jet_eta_centrality"), jet.eta(), centrality); registry.fill(HIST("h2_jet_phi_centrality"), jet.phi(), centrality); if (fillGeneralSVQA) { - registry.fill(HIST("h2_3prong_nprongs_centrality"), jet.template secondaryVertices_as().size(), centrality); + registry.fill(HIST("h2_nprongs_centrality"), jet.template secondaryVertices_as().size(), centrality); for (const auto& prong : jet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_centrality"), jet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality); + registry.fill(HIST("hn_jet_Sxy_centrality"), jet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality); if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_centrality"), jet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality); + registry.fill(HIST("hn_jet_Sxyz_centrality"), jet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality); } } } @@ -394,9 +394,9 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); + registry.fill(HIST("hn_jet_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); if (jet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); + registry.fill(HIST("hn_taggedjet_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); } } if (fillSVxyz) { @@ -405,16 +405,16 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); + registry.fill(HIST("hn_jet_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); if (jet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); + registry.fill(HIST("hn_taggedjet_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); } } } } template - void fillHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float eventWeight = 1.0) + void fillHistogramSVMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float eventWeight = 1.0) { if (useEventWeight) { float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); @@ -429,11 +429,11 @@ struct BjetCentMultTask { registry.fill(HIST("h3_jet_eta_centrality_flavour"), mcdjet.eta(), centrality, origin, eventWeight); registry.fill(HIST("h3_jet_phi_centrality_flavour"), mcdjet.phi(), centrality, origin, eventWeight); if (fillGeneralSVQA) { - registry.fill(HIST("h3_3prong_nprongs_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); + registry.fill(HIST("h3_nprongs_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); for (const auto& prong : mcdjet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_centrality_flavour"), mcdjet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxy_centrality_flavour"), mcdjet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_centrality_flavour"), mcdjet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxyz_centrality_flavour"), mcdjet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); } } } @@ -442,9 +442,9 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_taggedjet_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); } } if (fillSVxyz) { @@ -452,16 +452,16 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_taggedjet_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); } } } } template - void fillRhoAreaSubtractedHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float rho, float eventWeight = 1.0) + void fillRhoAreaSubtractedHistogramSVMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float rho, float eventWeight = 1.0) { if (useEventWeight) { float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); @@ -476,11 +476,11 @@ struct BjetCentMultTask { registry.fill(HIST("h3_jet_eta_rhoareasubtracted_centrality_flavour"), mcdjet.eta(), centrality, origin, eventWeight); registry.fill(HIST("h3_jet_phi_rhoareasubtracted_centrality_flavour"), mcdjet.phi(), centrality, origin, eventWeight); if (fillGeneralSVQA) { - registry.fill(HIST("h3_3prong_nprongs_rhoareasubtracted_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); + registry.fill(HIST("h3_nprongs_rhoareasubtracted_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); for (const auto& prong : mcdjet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxy_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxyz_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); } } } @@ -489,9 +489,9 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); } } if (fillSVxyz) { @@ -499,9 +499,9 @@ struct BjetCentMultTask { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_jet_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); + registry.fill(HIST("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); } } } @@ -554,7 +554,7 @@ struct BjetCentMultTask { } PROCESS_SWITCH(BjetCentMultTask, processMCP, "Fill impact parameter imformation for mcp jets", false); - void processSV3ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) + void processSVData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -568,19 +568,19 @@ struct BjetCentMultTask { if (!isAcceptedJet(jet)) { continue; } - fillHistogramSV3ProngData(jet, prongs, centrality); + fillHistogramSVData(jet, prongs, centrality); } } - PROCESS_SWITCH(BjetCentMultTask, processSV3ProngData, "Fill 3prong imformation for data jets", false); + PROCESS_SWITCH(BjetCentMultTask, processSVData, "Fill n-prong imformation for data jets", false); - void processRhoAreaSubSV3ProngData(soa::Filtered>::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) + void processRhoAreaSubSVData(soa::Filtered>::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } float centrality = collision.centFT0M(); float rho = collision.rho(); - registry.fill(HIST("h_event_centrality"), centrality); + registry.fill(HIST("h_event_rhoareasubtracted_centrality"), collision.centFT0M()); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { continue; @@ -588,12 +588,12 @@ struct BjetCentMultTask { if (!isAcceptedJet(jet)) { continue; } - fillRhoAreaSubtractedHistogramSV3ProngData(jet, prongs, centrality, rho); + fillRhoAreaSubtractedHistogramSV(jet, prongs, centrality, rho); } } - PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSV3ProngData, "Fill 3prong imformation for data jets with background subtraction", false); + PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSVData, "Fill n-prong imformation for data jets with background subtraction", false); - void processSV3ProngMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -611,12 +611,12 @@ struct BjetCentMultTask { if (!isAcceptedJet(mcdjet)) { continue; } - fillHistogramSV3ProngMCD(mcdjet, prongs, centrality, weight); + fillHistogramSVMCD(mcdjet, prongs, centrality, weight); } } - PROCESS_SWITCH(BjetCentMultTask, processSV3ProngMCD, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(BjetCentMultTask, processSVMCD, "Fill n-prong imformation for mcd jets", false); - void processSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -637,12 +637,12 @@ struct BjetCentMultTask { if (!mcdjet.has_matchedJetGeo()) { continue; } - fillHistogramSV3ProngMCD(mcdjet, prongs, centrality, weight); + fillHistogramSVMCD(mcdjet, prongs, centrality, weight); } } - PROCESS_SWITCH(BjetCentMultTask, processSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets matched", false); + PROCESS_SWITCH(BjetCentMultTask, processSVMCPMCDMatched, "Fill n-prong imformation for mcd jets matched", false); - void processRhoAreaSubSV3ProngMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + void processRhoAreaSubSVMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -661,12 +661,12 @@ struct BjetCentMultTask { if (!isAcceptedJet(mcdjet)) { continue; } - fillRhoAreaSubtractedHistogramSV3ProngMCD(mcdjet, prongs, centrality, rho, weight); + fillRhoAreaSubtractedHistogramSVMCD(mcdjet, prongs, centrality, rho, weight); } } - PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSV3ProngMCD, "Fill 3prong imformation for mcd jets with background subraction", false); + PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSVMCD, "Fill n-prong imformation for mcd jets with background subraction", false); - void processRhoAreaSubSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + void processRhoAreaSubSVMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -688,10 +688,10 @@ struct BjetCentMultTask { if (!mcdjet.has_matchedJetGeo()) { continue; } - fillRhoAreaSubtractedHistogramSV3ProngMCD(mcdjet, prongs, centrality, rho, weight); + fillRhoAreaSubtractedHistogramSVMCD(mcdjet, prongs, centrality, rho, weight); } } - PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets matched with background subtraction", false); + PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSVMCPMCDMatched, "Fill n-prong imformation for mcd jets matched with background subtraction", false); }; using BjetCentMultChargedDataJets = soa::Join; diff --git a/PWGJE/Tasks/jetTaggerHFQA.cxx b/PWGJE/Tasks/jetTaggerHFQA.cxx index dac7777daf7..b7cbbe76f5d 100644 --- a/PWGJE/Tasks/jetTaggerHFQA.cxx +++ b/PWGJE/Tasks/jetTaggerHFQA.cxx @@ -76,8 +76,6 @@ struct JetTaggerHFQA { Configurable checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions (data and mcd jets), not mc collisions (mcp jets)"}; - Configurable meanFT0A{"meanFT0A", -1., "Mean value of FT0A signal"}; - Configurable meanFT0C{"meanFT0C", -1., "Mean value of FT0C signal"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; @@ -107,6 +105,7 @@ struct JetTaggerHFQA { ConfigurableAxis binMass{"binMass", {50, 0, 10.f}, ""}; ConfigurableAxis binSigmaLxy{"binSigmaLxy", {100, 0., 0.1}, ""}; ConfigurableAxis binSigmaLxyz{"binSigmaLxyz", {100, 0., 0.1}, ""}; + ConfigurableAxis binDispersion{"binDispersion", {200, 0., 1}, ""}; int numberOfJetFlavourSpecies = 6; std::vector eventSelectionBits; @@ -147,6 +146,7 @@ struct JetTaggerHFQA { AxisSpec axisMass = {binMass, "#it{m}_{SV}"}; AxisSpec axisSigmaLxy = {binSigmaLxy, "#sigma_{L_{XY}} [cm]"}; AxisSpec axisSigmaLxyz = {binSigmaLxyz, "#sigma_{L_{XYZ}} [cm]"}; + AxisSpec axisDispersion = {binDispersion, "#sigma_{SV}"}; AxisSpec axisFracSecPt = {100, 0, 1, "#frac{#Sigma#it{p}_{T}^{secondary track}}{#it{p}_{T, jet}}"}; registry.add("h_collision_events", "data;mcd;mcp evnets", {HistType::kTH1F, {{4, 0.0, 4.0}}}); @@ -316,7 +316,7 @@ struct JetTaggerHFQA { } if (doprocessJPData) { - if (!doprocessIPsData && !doprocessSV2ProngData && !doprocessSV3ProngData) { + if (!doprocessIPsData && !doprocessSVData) { registry.add("h_jet_pt", "", {HistType::kTH1F, {{axisJetPt}}}); registry.add("h_jet_eta", "", {HistType::kTH1F, {{axisEta}}}); registry.add("h_jet_phi", "", {HistType::kTH1F, {{axisPhi}}}); @@ -331,7 +331,7 @@ struct JetTaggerHFQA { registry.add("h2_taggedjet_pt_neg_log_JP_N3", "jet pt jet probabilityun N3", {HistType::kTH2F, {{axisJetPt}, {axisJetProbabilityLog}}}); } if (doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) { - if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted) && !(doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted)) { + if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessSVMCD || doprocessSVMCDWeighted || doprocessSVMCPMCDMatched || doprocessSVMCPMCDMatchedWeighted)) { registry.add("h2_jet_pt_flavour", "", {HistType::kTH2F, {{axisJetPt}, {axisJetFlavour}}}); registry.add("h2_jet_eta_flavour", "", {HistType::kTH2F, {{axisEta}, {axisJetFlavour}}}); registry.add("h2_jet_phi_flavour", "", {HistType::kTH2F, {{axisPhi}, {axisJetFlavour}}}); @@ -345,101 +345,55 @@ struct JetTaggerHFQA { registry.add("h3_taggedjet_pt_JP_N3_flavour", "jet pt jet probability flavour N3", {HistType::kTH3F, {{axisJetPt}, {axisJetProbability}, {axisJetFlavour}}}); registry.add("h3_taggedjet_pt_neg_log_JP_N3_flavour", "jet pt log jet probability flavour N3", {HistType::kTH3F, {{axisJetPt}, {axisJetProbabilityLog}, {axisJetFlavour}}}); } - if (doprocessSV2ProngData) { - if (!doprocessIPsData && !doprocessJPData && !doprocessSV3ProngData) { + if (doprocessSVData) { + if (!doprocessIPsData && !doprocessJPData) { registry.add("h_jet_pt", "", {HistType::kTH1F, {{axisJetPt}}}); registry.add("h_jet_eta", "", {HistType::kTH1F, {{axisEta}}}); registry.add("h_jet_phi", "", {HistType::kTH1F, {{axisPhi}}}); } if (fillGeneralSVQA) { - registry.add("h_2prong_nprongs", "", {HistType::kTH1F, {{axisNprongs}}}); - registry.add("h2_jet_pt_2prong_Lxy", "", {HistType::kTH2F, {{axisJetPt}, {axisLxy}}}); - registry.add("h2_jet_pt_2prong_sigmaLxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxy}}}); - registry.add("h2_jet_pt_2prong_Sxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_jet_pt_2prong_Lxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisLxyz}}}); - registry.add("h2_jet_pt_2prong_sigmaLxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxyz}}}); - registry.add("h2_jet_pt_2prong_Sxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - } - registry.add("h2_jet_pt_2prong_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_jet_pt_2prong_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - registry.add("h2_jet_pt_2prong_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_jet_pt_2prong_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_taggedjet_pt_2prong_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_taggedjet_pt_2prong_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - registry.add("h2_taggedjet_pt_2prong_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_taggedjet_pt_2prong_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - } - if (doprocessSV3ProngData) { - if (!doprocessIPsData && !doprocessJPData && !doprocessSV2ProngData) { - registry.add("h_jet_pt", "", {HistType::kTH1F, {{axisJetPt}}}); - registry.add("h_jet_eta", "", {HistType::kTH1F, {{axisEta}}}); - registry.add("h_jet_phi", "", {HistType::kTH1F, {{axisPhi}}}); - } - if (fillGeneralSVQA) { - registry.add("h_3prong_nprongs", "", {HistType::kTH1F, {{axisNprongs}}}); - registry.add("h2_jet_pt_3prong_Lxy", "", {HistType::kTH2F, {{axisJetPt}, {axisLxy}}}); - registry.add("h2_jet_pt_3prong_sigmaLxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxy}}}); - registry.add("h2_jet_pt_3prong_Sxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_jet_pt_3prong_Lxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisLxyz}}}); - registry.add("h2_jet_pt_3prong_sigmaLxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxyz}}}); - registry.add("h2_jet_pt_3prong_Sxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - } - registry.add("h2_jet_pt_3prong_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_jet_pt_3prong_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - registry.add("h2_jet_pt_3prong_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_jet_pt_3prong_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_taggedjet_pt_3prong_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); - registry.add("h2_taggedjet_pt_3prong_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); - registry.add("h2_taggedjet_pt_3prong_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - registry.add("h2_taggedjet_pt_3prong_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); - } - if (doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted) { - if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) && !(doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted)) { + registry.add("h_nprongs", "", {HistType::kTH1F, {{axisNprongs}}}); + registry.add("h2_jet_pt_Lxy", "", {HistType::kTH2F, {{axisJetPt}, {axisLxy}}}); + registry.add("h2_jet_pt_sigmaLxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxy}}}); + registry.add("h2_jet_pt_Sxy", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); + registry.add("h2_jet_pt_Lxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisLxyz}}}); + registry.add("h2_jet_pt_sigmaLxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSigmaLxyz}}}); + registry.add("h2_jet_pt_Sxyz", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); + registry.add("hn_jet_pt_Lxy_sigmaLxy_Sxy_dispersion", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisDispersion}}}); + } + registry.add("h2_jet_pt_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); + registry.add("h2_jet_pt_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); + registry.add("h2_jet_pt_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); + registry.add("h2_jet_pt_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); + registry.add("h2_taggedjet_pt_Sxy_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxy}}}); + registry.add("h2_taggedjet_pt_Sxyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisSxyz}}}); + registry.add("h2_taggedjet_pt_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); + registry.add("h2_taggedjet_pt_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); + } + if (doprocessSVMCD || doprocessSVMCDWeighted || doprocessSVMCPMCDMatched || doprocessSVMCPMCDMatchedWeighted) { + if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted)) { registry.add("h2_jet_pt_flavour", "", {HistType::kTH2F, {{axisJetPt}, {axisJetFlavour}}}); registry.add("h2_jet_eta_flavour", "", {HistType::kTH2F, {{axisEta}, {axisJetFlavour}}}); registry.add("h2_jet_phi_flavour", "", {HistType::kTH2F, {{axisPhi}, {axisJetFlavour}}}); } if (fillGeneralSVQA) { - registry.add("h2_2prong_nprongs_flavour", "", {HistType::kTH2F, {{axisNprongs}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_Lxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_Sxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_Lxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_Sxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - } - registry.add("h3_jet_pt_2prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_2prong_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_2prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_2prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_2prong_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_2prong_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - } - if (doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted) { - if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) && !(doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted)) { - registry.add("h2_jet_pt_flavour", "", {HistType::kTH2F, {{axisJetPt}, {axisJetFlavour}}}); - registry.add("h2_jet_eta_flavour", "", {HistType::kTH2F, {{axisEta}, {axisJetFlavour}}}); - registry.add("h2_jet_phi_flavour", "", {HistType::kTH2F, {{axisPhi}, {axisJetFlavour}}}); - } - if (fillGeneralSVQA) { - registry.add("h2_3prong_nprongs_flavour", "", {HistType::kTH2F, {{axisNprongs}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_Lxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_sigmaLxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_Sxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_Lxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_sigmaLxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_Sxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - } - registry.add("h3_jet_pt_3prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_jet_pt_3prong_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_3prong_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_3prong_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_3prong_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); - registry.add("h3_taggedjet_pt_3prong_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); + registry.add("h2_nprongs_flavour", "", {HistType::kTH2F, {{axisNprongs}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_Lxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxy}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_sigmaLxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxy}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_Sxy_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_Lxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisLxyz}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_sigmaLxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSigmaLxyz}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_Sxyz_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); + registry.add("hn_jet_pt_Lxy_sigmaLxy_Sxy_dispersion_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisDispersion}, {axisJetFlavour}}}); + } + registry.add("h3_jet_pt_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); + registry.add("h3_taggedjet_pt_Sxy_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxy}, {axisJetFlavour}}}); + registry.add("h3_taggedjet_pt_Sxyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisSxyz}, {axisJetFlavour}}}); + registry.add("h3_taggedjet_pt_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); + registry.add("h3_taggedjet_pt_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); } } @@ -848,7 +802,7 @@ struct JetTaggerHFQA { if (jet.pt() > pTHatMaxMCD * pTHat) { return; } - if (!doprocessIPsData && !doprocessSV2ProngData && !doprocessSV3ProngData) { + if (!doprocessIPsData && !doprocessSVData) { registry.fill(HIST("h_jet_pt"), jet.pt()); registry.fill(HIST("h_jet_eta"), jet.eta()); registry.fill(HIST("h_jet_phi"), jet.phi()); @@ -870,7 +824,7 @@ struct JetTaggerHFQA { if (mcdjet.pt() > pTHatMaxMCD * pTHat) { return; } - if (!((doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && (doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted) && (doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted))) { + if (!((doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && (doprocessSVMCD || doprocessSVMCDWeighted || doprocessSVMCPMCDMatched || doprocessSVMCPMCDMatchedWeighted))) { registry.fill(HIST("h2_jet_pt_flavour"), mcdjet.pt(), mcdjet.origin(), eventWeight); registry.fill(HIST("h2_jet_eta_flavour"), mcdjet.eta(), mcdjet.origin(), eventWeight); registry.fill(HIST("h2_jet_phi_flavour"), mcdjet.phi(), mcdjet.origin(), eventWeight); @@ -886,14 +840,14 @@ struct JetTaggerHFQA { } template - void fillHistogramSV2ProngData(T const& jet, U const& /*prongs*/) + void fillHistogramSVData(T const& jet, U const& /*prongs*/) { float eventWeight = 1.0; float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat) { return; } - if (!doprocessIPsData && !doprocessJPData && !doprocessSV3ProngData) { + if (!doprocessIPsData && !doprocessJPData) { registry.fill(HIST("h_jet_pt"), jet.pt(), eventWeight); registry.fill(HIST("h_jet_eta"), jet.eta(), eventWeight); registry.fill(HIST("h_jet_phi"), jet.phi(), eventWeight); @@ -901,15 +855,16 @@ struct JetTaggerHFQA { if (jet.template secondaryVertices_as().size() < 1) return; if (fillGeneralSVQA) { - registry.fill(HIST("h_2prong_nprongs"), jet.template secondaryVertices_as().size()); + registry.fill(HIST("h_nprongs"), jet.template secondaryVertices_as().size()); for (const auto& prong : jet.template secondaryVertices_as()) { - registry.fill(HIST("h2_jet_pt_2prong_Lxy"), jet.pt(), prong.decayLengthXY()); - registry.fill(HIST("h2_jet_pt_2prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); - registry.fill(HIST("h2_jet_pt_2prong_Sxy"), jet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY()); + registry.fill(HIST("h2_jet_pt_Lxy"), jet.pt(), prong.decayLengthXY()); + registry.fill(HIST("h2_jet_pt_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); + registry.fill(HIST("h2_jet_pt_Sxy"), jet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY()); + registry.fill(HIST("hn_jet_pt_Lxy_sigmaLxy_Sxy_dispersion"), jet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), prong.dispersion()); if (fillSVxyz) { - registry.fill(HIST("h2_jet_pt_2prong_Lxyz"), jet.pt(), prong.decayLength()); - registry.fill(HIST("h2_jet_pt_2prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); - registry.fill(HIST("h2_jet_pt_2prong_Sxyz"), jet.pt(), prong.decayLength() / prong.errorDecayLength()); + registry.fill(HIST("h2_jet_pt_Lxyz"), jet.pt(), prong.decayLength()); + registry.fill(HIST("h2_jet_pt_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); + registry.fill(HIST("h2_jet_pt_Sxyz"), jet.pt(), prong.decayLength() / prong.errorDecayLength()); } } } @@ -918,11 +873,11 @@ struct JetTaggerHFQA { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("h2_jet_pt_2prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_jet_pt_2prong_mass_N1"), jet.pt(), massSV); + registry.fill(HIST("h2_jet_pt_Sxy_N1"), jet.pt(), maxSxy); + registry.fill(HIST("h2_jet_pt_mass_N1"), jet.pt(), massSV); if (jet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("h2_taggedjet_pt_2prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_taggedjet_pt_2prong_mass_N1"), jet.pt(), massSV); + registry.fill(HIST("h2_taggedjet_pt_Sxy_N1"), jet.pt(), maxSxy); + registry.fill(HIST("h2_taggedjet_pt_mass_N1"), jet.pt(), massSV); } } if (fillSVxyz) { @@ -930,136 +885,25 @@ struct JetTaggerHFQA { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("h2_jet_pt_2prong_Sxyz_N1"), jet.pt(), maxSxyz); - registry.fill(HIST("h2_jet_pt_2prong_mass_xyz_N1"), jet.pt(), massSV); + registry.fill(HIST("h2_jet_pt_Sxyz_N1"), jet.pt(), maxSxyz); + registry.fill(HIST("h2_jet_pt_mass_xyz_N1"), jet.pt(), massSV); if (jet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("h2_taggedjet_pt_2prong_Sxyz_N1"), jet.pt(), maxSxyz); - registry.fill(HIST("h2_taggedjet_pt_2prong_mass_xyz_N1"), jet.pt(), massSV); - } - } - } - } - - template - void fillHistogramSV3ProngData(T const& jet, U const& /*prongs*/) - { - float eventWeight = 1.0; - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCD * pTHat) { - return; - } - if (!doprocessIPsData && !doprocessJPData && !doprocessSV2ProngData) { - registry.fill(HIST("h_jet_pt"), jet.pt(), eventWeight); - registry.fill(HIST("h_jet_eta"), jet.eta(), eventWeight); - registry.fill(HIST("h_jet_phi"), jet.phi(), eventWeight); - } - if (jet.template secondaryVertices_as().size() < 1) - return; - if (fillGeneralSVQA) { - registry.fill(HIST("h_3prong_nprongs"), jet.template secondaryVertices_as().size()); - for (const auto& prong : jet.template secondaryVertices_as()) { - registry.fill(HIST("h2_jet_pt_3prong_Lxy"), jet.pt(), prong.decayLengthXY()); - registry.fill(HIST("h2_jet_pt_3prong_sigmaLxy"), jet.pt(), prong.errorDecayLengthXY()); - registry.fill(HIST("h2_jet_pt_3prong_Sxy"), jet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY()); - if (fillSVxyz) { - registry.fill(HIST("h2_jet_pt_3prong_Lxyz"), jet.pt(), prong.decayLength()); - registry.fill(HIST("h2_jet_pt_3prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); - registry.fill(HIST("h2_jet_pt_3prong_Sxyz"), jet.pt(), prong.decayLength() / prong.errorDecayLength()); - } - } - } - bool checkSv = false; - auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { - auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); - auto massSV = bjetCand.m(); - registry.fill(HIST("h2_jet_pt_3prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_jet_pt_3prong_mass_N1"), jet.pt(), massSV); - if (jet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("h2_taggedjet_pt_3prong_Sxy_N1"), jet.pt(), maxSxy); - registry.fill(HIST("h2_taggedjet_pt_3prong_mass_N1"), jet.pt(), massSV); - } - } - if (fillSVxyz) { - auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { - auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); - auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("h2_jet_pt_3prong_Sxyz_N1"), jet.pt(), maxSxyz); - registry.fill(HIST("h2_jet_pt_3prong_mass_xyz_N1"), jet.pt(), massSV); - if (jet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("h2_taggedjet_pt_3prong_Sxyz_N1"), jet.pt(), maxSxyz); - registry.fill(HIST("h2_taggedjet_pt_3prong_mass_xyz_N1"), jet.pt(), massSV); - } - } - } - } - - template - void fillHistogramSV2ProngMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) - { - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - if (mcdjet.pt() > pTHatMaxMCD * pTHat) { - return; - } - auto origin = mcdjet.origin(); - if (!((doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && (doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) && (doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted))) { - registry.fill(HIST("h2_jet_pt_flavour"), mcdjet.pt(), origin, eventWeight); - registry.fill(HIST("h2_jet_eta_flavour"), mcdjet.eta(), origin, eventWeight); - registry.fill(HIST("h2_jet_phi_flavour"), mcdjet.phi(), origin, eventWeight); - } - if (mcdjet.template secondaryVertices_as().size() < 1) - return; - if (fillGeneralSVQA) { - registry.fill(HIST("h2_2prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin, eventWeight); - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - registry.fill(HIST("h3_jet_pt_2prong_Lxy_flavour"), mcdjet.pt(), prong.decayLengthXY(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_Sxy_flavour"), mcdjet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY(), origin, eventWeight); - if (fillSVxyz) { - registry.fill(HIST("h3_jet_pt_2prong_Lxyz_flavour"), mcdjet.pt(), prong.decayLength(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_Sxyz_flavour"), mcdjet.pt(), prong.decayLength() / prong.errorDecayLength(), origin, eventWeight); - } - } - } - bool checkSv = false; - auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { - auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); - auto massSV = bjetCand.m(); - registry.fill(HIST("h3_jet_pt_2prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); - if (mcdjet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("h3_taggedjet_pt_2prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); - registry.fill(HIST("h3_taggedjet_pt_2prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); - } - } - if (fillSVxyz) { - checkSv = false; - auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { - auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); - auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("h3_jet_pt_2prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); - registry.fill(HIST("h3_jet_pt_2prong_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); - if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("h3_taggedjet_pt_2prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); - registry.fill(HIST("h3_taggedjet_pt_2prong_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + registry.fill(HIST("h2_taggedjet_pt_Sxyz_N1"), jet.pt(), maxSxyz); + registry.fill(HIST("h2_taggedjet_pt_mass_xyz_N1"), jet.pt(), massSV); } } } } template - void fillHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) + void fillHistogramSVMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) { float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (mcdjet.pt() > pTHatMaxMCD * pTHat) { return; } auto origin = mcdjet.origin(); - if (!((doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && (doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) && (doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted))) { + if (!((doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && (doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted))) { registry.fill(HIST("h2_jet_pt_flavour"), mcdjet.pt(), origin, eventWeight); registry.fill(HIST("h2_jet_eta_flavour"), mcdjet.eta(), origin, eventWeight); registry.fill(HIST("h2_jet_phi_flavour"), mcdjet.phi(), origin, eventWeight); @@ -1067,15 +911,16 @@ struct JetTaggerHFQA { if (mcdjet.template secondaryVertices_as().size() < 1) return; if (fillGeneralSVQA) { - registry.fill(HIST("h2_3prong_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin); + registry.fill(HIST("h2_nprongs_flavour"), mcdjet.template secondaryVertices_as().size(), origin); for (const auto& prong : mcdjet.template secondaryVertices_as()) { - registry.fill(HIST("h3_jet_pt_3prong_Lxy_flavour"), mcdjet.pt(), prong.decayLengthXY(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_Sxy_flavour"), mcdjet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Lxy_flavour"), mcdjet.pt(), prong.decayLengthXY(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_sigmaLxy_flavour"), mcdjet.pt(), prong.errorDecayLengthXY(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Sxy_flavour"), mcdjet.pt(), prong.decayLengthXY() / prong.errorDecayLengthXY(), origin, eventWeight); + registry.fill(HIST("hn_jet_pt_Lxy_sigmaLxy_Sxy_dispersion"), mcdjet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), prong.dispersion(), origin, eventWeight); if (fillSVxyz) { - registry.fill(HIST("h3_jet_pt_3prong_Lxyz_flavour"), mcdjet.pt(), prong.decayLength(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_Sxyz_flavour"), mcdjet.pt(), prong.decayLength() / prong.errorDecayLength(), origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Lxyz_flavour"), mcdjet.pt(), prong.decayLength(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Sxyz_flavour"), mcdjet.pt(), prong.decayLength() / prong.errorDecayLength(), origin, eventWeight); + registry.fill(HIST("h3_jet_pt_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); } } } @@ -1084,11 +929,11 @@ struct JetTaggerHFQA { if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); - registry.fill(HIST("h3_jet_pt_3prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("h3_taggedjet_pt_3prong_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); - registry.fill(HIST("h3_taggedjet_pt_3prong_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_Sxy_N1_flavour"), mcdjet.pt(), maxSxy, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_mass_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); } } if (fillSVxyz) { @@ -1097,11 +942,11 @@ struct JetTaggerHFQA { if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("h3_jet_pt_3prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); - registry.fill(HIST("h3_jet_pt_3prong_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_jet_pt_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("h3_taggedjet_pt_3prong_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); - registry.fill(HIST("h3_taggedjet_pt_3prong_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_Sxyz_N1_flavour"), mcdjet.pt(), maxSxyz, origin, eventWeight); + registry.fill(HIST("h3_taggedjet_pt_mass_xyz_N1_flavour"), mcdjet.pt(), massSV, origin, eventWeight); } } } @@ -1563,7 +1408,7 @@ struct JetTaggerHFQA { } PROCESS_SWITCH(JetTaggerHFQA, processJPMCPMCDMatchedWeighted, "Fill jet probability imformation for mcd jets", false); - void processSV2ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex2Prongs const& prongs) + void processSVData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -1576,116 +1421,12 @@ struct JetTaggerHFQA { if (!isAcceptedJet(jet)) { continue; } - fillHistogramSV2ProngData(jet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngData, "Fill 2prong imformation for data jets", false); - - void processSV3ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - registry.fill(HIST("h_collision_events"), 0.5); // mcd events - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; - } - fillHistogramSV3ProngData(jet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngData, "Fill 3prong imformation for data jets", false); - - void processSV2ProngMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - registry.fill(HIST("h_collision_events"), 1.5); // mcd events - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - fillHistogramSV2ProngMCD(mcdjet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCD, "Fill 2prong imformation for mcd jets", false); - - void processSV2ProngMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - if (collision.isOutlier()) { - return; - } - registry.fill(HIST("h_collision_events"), 1.5, collision.weight()); // mcd events - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - fillHistogramSV2ProngMCD(mcdjet, prongs, collision.weight()); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCDWeighted, "Fill 2prong imformation for mcd jets", false); - - void processSV2ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex2Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - registry.fill(HIST("h_collision_events"), 1.5); // mcd events - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - if (!mcdjet.has_matchedJetGeo()) { - continue; - } - if (!doprocessSV2ProngMCD) - fillHistogramSV2ProngMCD(mcdjet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCPMCDMatched, "Fill 2prong imformation for mcd jets", false); - - void processSV2ProngMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex2Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - if (collision.isOutlier()) { - return; - } - registry.fill(HIST("h_collision_events"), 1.5, collision.weight()); // mcd events - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - if (!mcdjet.has_matchedJetGeo()) { - continue; - } - if (!doprocessSV2ProngMCDWeighted) - fillHistogramSV2ProngMCD(mcdjet, prongs, collision.weight()); + fillHistogramSVData(jet, prongs); } } - PROCESS_SWITCH(JetTaggerHFQA, processSV2ProngMCPMCDMatchedWeighted, "Fill 2prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSVData, "Fill n-prong imformation for data jets", false); - void processSV3ProngMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -1698,12 +1439,12 @@ struct JetTaggerHFQA { if (!isAcceptedJet(mcdjet)) { continue; } - fillHistogramSV3ProngMCD(mcdjet, prongs); + fillHistogramSVMCD(mcdjet, prongs); } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCD, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSVMCD, "Fill n-prong imformation for mcd jets", false); - void processSV3ProngMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -1719,12 +1460,12 @@ struct JetTaggerHFQA { if (!isAcceptedJet(mcdjet)) { continue; } - fillHistogramSV3ProngMCD(mcdjet, prongs, collision.weight()); + fillHistogramSVMCD(mcdjet, prongs, collision.weight()); } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCDWeighted, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSVMCDWeighted, "Fill n-prong imformation for mcd jets", false); - void processSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -1740,13 +1481,13 @@ struct JetTaggerHFQA { if (!mcdjet.has_matchedJetGeo()) { continue; } - if (!doprocessSV3ProngMCD) - fillHistogramSV3ProngMCD(mcdjet, prongs); + if (!doprocessSVMCD) + fillHistogramSVMCD(mcdjet, prongs); } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSVMCPMCDMatched, "Fill n-prong imformation for mcd jets", false); - void processSV3ProngMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + void processSVMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertexNProngs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; @@ -1765,11 +1506,11 @@ struct JetTaggerHFQA { if (!mcdjet.has_matchedJetGeo()) { continue; } - if (!doprocessSV3ProngMCDWeighted) - fillHistogramSV3ProngMCD(mcdjet, prongs, collision.weight()); + if (!doprocessSVMCDWeighted) + fillHistogramSVMCD(mcdjet, prongs, collision.weight()); } } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatchedWeighted, "Fill 3prong imformation for mcd jets", false); + PROCESS_SWITCH(JetTaggerHFQA, processSVMCPMCDMatchedWeighted, "Fill n-prong imformation for mcd jets", false); }; using JetTaggerQAChargedDataJets = soa::Join; From 054b21ef2ddc547fd20375097995e83062e00f4e Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sun, 3 May 2026 12:13:09 +0200 Subject: [PATCH 013/449] [PWGLF] Add process function to produce MC table for spincorr analysis (#16069) --- .../Strangeness/lambdaspincorrelation.cxx | 203 +++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx index bb35e81c1f9..f20460f7171 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -75,6 +75,7 @@ struct lambdaspincorrelation { // events Configurable cfgEventTypepp{"cfgEventTypepp", false, "Type of collisions"}; + Configurable cfgCentTypepp{"cfgCentTypepp", true, "Type of centrality"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 80.0f, "Accepted maximum Centrality"}; Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 0.0f, "Accepted minimum Centrality"}; @@ -242,7 +243,8 @@ struct lambdaspincorrelation { using EventCandidates = soa::Filtered>; using AllTrackCandidates = soa::Join; using ResoV0s = aod::V0Datas; - + using EventCandidatesMC = soa::Join; + using AllTrackCandidatesMC = soa::Join; void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) { std::vector lambdaMother, protonDaughter, pionDaughter; @@ -258,7 +260,7 @@ struct lambdaspincorrelation { int numbV0 = 0; // LOGF(info, "event collisions: (%d)", collision.index()); auto centrality = collision.centFT0C(); - if (cfgEventTypepp) + if (cfgCentTypepp) centrality = collision.centFT0M(); auto vz = collision.posZ(); int occupancy = collision.trackOccupancyInTimeRange(); @@ -370,7 +372,7 @@ struct lambdaspincorrelation { int numbV0 = 0; // LOGF(info, "event collisions: (%d)", collision.index()); auto centrality = collision.centFT0C(); - if (cfgEventTypepp) + if (cfgCentTypepp) centrality = collision.centFT0M(); auto vz = collision.posZ(); int occupancy = collision.trackOccupancyInTimeRange(); @@ -465,6 +467,201 @@ struct lambdaspincorrelation { } } PROCESS_SWITCH(lambdaspincorrelation, processMc, "Process montecarlo", true); + + void processMc2(aod::McCollision const&, + soa::SmallGroups const& collisions, + AllTrackCandidatesMC const&, + ResoV0s const& V0s, + aod::McParticles const&) + { + if (collisions.size() == 1) { + + for (const auto& collision : collisions) { + + std::vector lambdaMother, protonDaughter, pionDaughter; + std::vector v0Status = {}; + std::vector doubleStatus = {}; + std::vector v0Cospa = {}; + std::vector v0Radius = {}; + std::vector dcaPositive = {}; + std::vector dcaNegative = {}; + std::vector positiveIndex = {}; + std::vector negativeIndex = {}; + std::vector dcaBetweenDaughter = {}; + int numbV0 = 0; + + auto centrality = collision.centFT0C(); + if (cfgCentTypepp) { + centrality = collision.centFT0M(); + } + + auto vz = collision.posZ(); + int occupancy = collision.trackOccupancyInTimeRange(); + + histos.fill(HIST("hEvtSelInfo"), 0.5); + + if (std::abs(collision.posZ()) < cfgCutVertex && + (!rctCut.requireRCTFlagChecker || rctChecker(collision)) && + + (!cfgEventTypepp || (collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && + collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) && + + (!useNoCollInTimeRangeStandard || collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) && + collision.sel8() && + (!useGoodITSLayersAll || collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) && + occupancy < cfgCutOccupancy) { + + histos.fill(HIST("hEvtSelInfo"), 1.5); + + for (const auto& v0 : V0s) { + + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); + + if (isValid) { + + auto postrack1 = v0.template posTrack_as(); + auto negtrack1 = v0.template negTrack_as(); + + // Reject candidates whose reconstructed daughters are not MC-labelled. + if (!postrack1.has_mcParticle() || !negtrack1.has_mcParticle()) { + continue; + } + + auto mcPos = postrack1.mcParticle(); + auto mcNeg = negtrack1.mcParticle(); + + // Reject gap/background-event daughters. + if (mcPos.fromBackgroundEvent() || mcNeg.fromBackgroundEvent()) { + continue; + } + + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 0.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 1.5); + } + + if (lambdaTag && aLambdaTag) { + doubleStatus.push_back(true); + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda) < + std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda)) { + lambdaTag = true; + aLambdaTag = false; + } else { + lambdaTag = false; + aLambdaTag = true; + } + } else { + doubleStatus.push_back(false); + } + + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 2.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 3.5); + } + + positiveIndex.push_back(postrack1.globalIndex()); + negativeIndex.push_back(negtrack1.globalIndex()); + + v0Cospa.push_back(v0.v0cosPA()); + v0Radius.push_back(v0.v0radius()); + dcaPositive.push_back(std::abs(v0.dcapostopv())); + dcaNegative.push_back(std::abs(v0.dcanegtopv())); + dcaBetweenDaughter.push_back(std::abs(v0.dcaV0daughters())); + + if (lambdaTag) { + v0Status.push_back(0); + + proton = ROOT::Math::PxPyPzMVector( + v0.pxpos(), + v0.pypos(), + v0.pzpos(), + o2::constants::physics::MassProton); + + antiPion = ROOT::Math::PxPyPzMVector( + v0.pxneg(), + v0.pyneg(), + v0.pzneg(), + o2::constants::physics::MassPionCharged); + + lambda = proton + antiPion; + + lambdaMother.push_back(lambda); + protonDaughter.push_back(proton); + pionDaughter.push_back(antiPion); + + histos.fill(HIST("hLambdaMass"), lambda.M()); + + } else if (aLambdaTag) { + v0Status.push_back(1); + + antiProton = ROOT::Math::PxPyPzMVector( + v0.pxneg(), + v0.pyneg(), + v0.pzneg(), + o2::constants::physics::MassProton); + + pion = ROOT::Math::PxPyPzMVector( + v0.pxpos(), + v0.pypos(), + v0.pzpos(), + o2::constants::physics::MassPionCharged); + + antiLambda = antiProton + pion; + + lambdaMother.push_back(antiLambda); + protonDaughter.push_back(antiProton); + pionDaughter.push_back(pion); + + histos.fill(HIST("hLambdaMass"), antiLambda.M()); + } + + numbV0 = numbV0 + 1; + } + } + + if (numbV0 > 1 && v0Cospa.size() > 1) { + histos.fill(HIST("hEvtSelInfo"), 2.5); + + lambdaEventmc(centrality, vz); + auto indexEvent = lambdaEventmc.lastIndex(); + + for (auto if1 = lambdaMother.begin(); if1 != lambdaMother.end(); ++if1) { + auto i5 = std::distance(lambdaMother.begin(), if1); + + lambdaDummy = lambdaMother.at(i5); + protonDummy = protonDaughter.at(i5); + pionDummy = pionDaughter.at(i5); + + lambdaPairmc(indexEvent, + v0Status.at(i5), + doubleStatus.at(i5), + v0Cospa.at(i5), + v0Radius.at(i5), + dcaPositive.at(i5), + dcaNegative.at(i5), + dcaBetweenDaughter.at(i5), + lambdaDummy.Pt(), + lambdaDummy.Eta(), + lambdaDummy.Phi(), + lambdaDummy.M(), + protonDummy.Pt(), + protonDummy.Eta(), + protonDummy.Phi(), + positiveIndex.at(i5), + negativeIndex.at(i5)); + } + } + } + } + } + } + PROCESS_SWITCH(lambdaspincorrelation, processMc2, "Process montecarlo2", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From 2e2cf71104705e82e0b16bfd5030b0d86561d913 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 3 May 2026 16:20:35 +0200 Subject: [PATCH 014/449] [PWGEM/Dilepton] add XOR for matching in MC (#16071) --- PWGEM/Dilepton/Core/DileptonMC.h | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 10a069da32d..b7f34d5b398 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -311,8 +311,9 @@ struct DileptonMC { o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; - o2::framework::Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. - o2::framework::Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable acceptOnlyXORMatching{"acceptOnlyXORMatching", false, "flag to accept only correct-wrong XOR pairs between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -1436,22 +1437,33 @@ struct DileptonMC { // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { // return false; // } + + bool isCorrectMatch1 = t1.emmcparticleId() == t1.emmftmcparticleId(); + bool isCorrectMatch2 = t2.emmcparticleId() == t2.emmftmcparticleId(); + if (dimuoncuts.acceptOnlyCorrectMatch) { - if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() != t1.emmftmcparticleId()) { + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !isCorrectMatch1) { return false; } - if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.emmcparticleId() != t2.emmftmcparticleId()) { + if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !isCorrectMatch2) { return false; } } - if (dimuoncuts.acceptOnlyWrongMatch) { // reject correctly matched MFT-MCH-MID for bkg estimation - if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() == t1.emmftmcparticleId()) { + if (dimuoncuts.acceptOnlyWrongMatch) { + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && isCorrectMatch1) { return false; } - if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.emmcparticleId() == t2.emmftmcparticleId()) { + if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && isCorrectMatch2) { return false; } } + if (dimuoncuts.acceptOnlyXORMatching) { // this is dummy comment. + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (!(isCorrectMatch1 ^ isCorrectMatch2)) { + return false; + } + } + } if (!cut.IsSelectedPair(t1, t2)) { return false; From 9645038f768686affae08941ae82d7e047540df4 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Sun, 3 May 2026 19:38:13 +0200 Subject: [PATCH 015/449] [PWGLF,PWGMM] Fix reassociation checks (#16073) --- PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx | 570 ++++++++++++++++------------- 1 file changed, 322 insertions(+), 248 deletions(-) diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index 4edb4bfff6e..8ecdaafd555 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -72,6 +72,7 @@ #include #include #include +#include #include using SMatrix55 = ROOT::Math::SMatrix>; @@ -101,11 +102,11 @@ constexpr int CevtSel = 15; constexpr int CtrkSel = 7; constexpr int CtrkTrkBestSel = 6; constexpr int CambTrkType = 7; -constexpr int CselAmbTrkTypeAssocFlag = 16; +constexpr int CselAmbTrkTypeAssocFlag = 23; constexpr int CtrackToCollEvtType = 5; constexpr int CreassocVtxType = 18; constexpr int CevtReAsReAssocMCEventStatus = 5; -constexpr int CreAssocMCTrackStatus = 29; +constexpr int CreAssocMCTrackStatus = 33; enum class EvtSel { evtAll = 0, @@ -159,21 +160,28 @@ enum class AmbTrkType { }; enum AmbTrkTypeAssocFlag { - kSel = 0, + kSelAll = 0, + kSelGoodVtx, kSelGoodVtxTrue, - kSelGoodVtxBad, - kSelNonAmbAll, + kSelBadVtx, + kSelBadVtxTrue, + kSelNonAmb, + kSelNonAmbGoodVtx, kSelNonAmbGoodVtxTrue, - kSelNonAmbGoodVtxBad, - kSelNonAmbSameAll, - kSelNonAmbSameGoodVtxTrue, - kSelNonAmbSameGoodVtxBad, - kSelAmbAll, + kSelNonAmbBadVtx, + kSelNonAmbBadVtxTrue, + kSelNonAmbID, + kSelNonAmbIDGoodVtxTrue, + kSelNonAmbIDBadVtxTrue, + kSelAmbID, + kSelAmbIDGoodVtxTrue, + kSelAmbIDBadVtxTrue, + kSelNonAmbIDExtra, + kSelNonAmbIDExtraGoodVtxTrue, + kSelNonAmbIDExtraBadVtxTrue, + kSelAmb, kSelAmbGoodVtxTrue, - kSelAmbGoodVtxBad, - kSelAmbGt1All, - kSelAmbGt1GoodVtxTrue, - kSelAmbGt1GoodVtxBad, + kSelAmbBadVtxTrue, kSelOrphanNull, nSelAmbTrkTypeAssocFlag }; @@ -193,6 +201,18 @@ enum class VertexStatusMC { kBad }; +enum class AssocCheckVtxType { + kAllVtxTrue = 0, + kAllVtxFalse, + kAllGoodVtx, + kAllGoodVtxTrue, + kAllGoodVtxFalse, + kAllBadVtx, + kAllBadVtxTrue, + kAllBadVtxFalse, + nAssocVtxType +}; + enum class ReassocCheckVtxType { kIsTrueVtxAllTrue = 0, kIsTrueVtxAllFalse, @@ -231,22 +251,19 @@ enum class ReAssocMCTrackStatus { kTrkHasColl, kTrkReassignedRemoved, kTrkHasMcPart, - kTrkNonAmbAll, + kTrkIdGt0, + kTrkNonAmb, kTrkNonAmbGood, kTrkNonAmbBad, - kTrkAmbAll, - kTrkAmbGood, - kTrkAmbBad, - kTrkNonAmbAllE, - kTrkNonAmbGoodE, - kTrkNonAmbBadE, - kAssoc, - kAssocGood, - kAssocGoodIsCompTrue, - kAssocGoodIsCompFalse, - kAssocBad, - kAssocBadIsCompTrue, - kAssocBadIsCompFalse, + kTrkNonAmbID, + kTrkNonAmbIDGood, + kTrkNonAmbIDBad, + kTrkAmbID, + kTrkAmbIDGood, + kTrkAmbIDBad, + kTrkNonAmbIDExtra, + kTrkNonAmbIDExtraGood, + kTrkNonAmbIDExtraBad, kReAssoc, kReAssocGood, kReAssocGoodIsCompTrue, @@ -254,19 +271,6 @@ enum class ReAssocMCTrackStatus { kReAssocBad, kReAssocBadIsCompTrue, kReAssocBadIsCompFalse, - nReAssocMCTrackStatus -}; - -enum class HistStatusReAssocVtx { - kTrkNonAmbAll = 0, - kTrkNonAmbGood, - kTrkNonAmbBad, - kTrkAmbAll, - kTrkAmbGood, - kTrkAmbBad, - kTrkNonAmbAllE, - kTrkNonAmbGoodE, - kTrkNonAmbBadE, kAssoc, kAssocGood, kAssocGoodIsCompTrue, @@ -274,6 +278,23 @@ enum class HistStatusReAssocVtx { kAssocBad, kAssocBadIsCompTrue, kAssocBadIsCompFalse, + nReAssocMCTrackStatusCheck +}; + +enum class HistStatusReAssocVtx { + kTrkIdGt0 = 0, + kTrkNonAmb, + kTrkNonAmbGood, + kTrkNonAmbBad, + kTrkNonAmbID, + kTrkNonAmbIDGood, + kTrkNonAmbIDBad, + kTrkAmbID, + kTrkAmbIDGood, + kTrkAmbIDBad, + kTrkNonAmbIDExtra, + kTrkNonAmbIDExtraGood, + kTrkNonAmbIDExtraBad, kReAssoc, kReAssocGood, kReAssocGoodIsCompTrue, @@ -281,6 +302,13 @@ enum class HistStatusReAssocVtx { kReAssocBad, kReAssocBadIsCompTrue, kReAssocBadIsCompFalse, + kAssoc, + kAssocGood, + kAssocGoodIsCompTrue, + kAssocGoodIsCompFalse, + kAssocBad, + kAssocBadIsCompTrue, + kAssocBadIsCompFalse, nHistStatusReAssocVtx }; @@ -296,8 +324,8 @@ struct DndetaMFTPbPb { SliceCache cache; std::array, 4> hCollAssoc; - std::array, 23> hReAssocVtxRes; - std::array, 23> hReAssocDCA; + std::array, 27> hReAssocVtxRes; + std::array, 27> hReAssocDCA; // std::array, 23> hReAssocDCAPrim; std::array, 21> hTimeAssocWithReassocMC; @@ -1170,7 +1198,7 @@ struct DndetaMFTPbPb { registry.get(HIST("ReAssocMC/hReAssocMCEventStatus"))->GetXaxis()->SetBinLabel(iBin + 1, labelReAssocMCEventStatus[iBin].data()); } - registry.add("ReAssocMC/hReAssocMCTrackStatus", ";status", {HistType::kTH1F, {{static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatus), -0.5, +static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatus) - 0.5}}}); + registry.add("ReAssocMC/hReAssocMCTrackStatus", ";status", {HistType::kTH1F, {{static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatusCheck), -0.5, +static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatusCheck) - 0.5}}}); std::string labelReAssocMCTrackStatus[CreAssocMCTrackStatus]; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkReAssocAll)] = "All"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkBestSel)] = "Best sel"; @@ -1178,22 +1206,19 @@ struct DndetaMFTPbPb { labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkHasColl)] = "Has coll"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkReassignedRemoved)] = "Reas rm"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkHasMcPart)] = "Has part"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbAll)] = "Non-amb"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkIdGt0)] = "Trk idGt0"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmb)] = "Non-amb"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbGood)] = "Non-amb good coll."; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbBad)] = "Non-amb bad coll."; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbAll)] = "Amb"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbGood)] = "Amb good coll."; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbBad)] = "Amb bad coll."; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbAllE)] = "Non-amb (ex)"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbGoodE)] = "Non-amb good coll. (ex)"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbBadE)] = "Non-amb bad coll. (ex)"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssoc)] = "Assoc (gt1 amb)"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGood)] = "Assoc good"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGoodIsCompTrue)] = "Assoc good Comp True"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGoodIsCompFalse)] = "Assoc good Comp False"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBad)] = "Assoc bad"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBadIsCompTrue)] = "Assoc bad Comp True"; - labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBadIsCompFalse)] = "Assoc bad Comp False"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbID)] = "Non-amb id"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDGood)] = "Non-amb id good"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDBad)] = "Non-amb id bad"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbID)] = "Amb id"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbIDGood)] = "Amb id good"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkAmbIDBad)] = "Amb id bad"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtra)] = "Non-amb id ex"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtraGood)] = "Non-amb id ex good"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtraBad)] = "Non-amb id ex bad"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssoc)] = "ReAssoc"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssocGood)] = "ReAssoc good"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssocGoodIsCompTrue)] = "ReAssoc good Comp True"; @@ -1201,28 +1226,32 @@ struct DndetaMFTPbPb { labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssocBad)] = "ReAssoc bad"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssocBadIsCompTrue)] = "ReAssoc bad Comp True"; labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kReAssocBadIsCompFalse)] = "ReAssoc bad Comp False"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssoc)] = "Assoc (gt1 amb)"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGood)] = "Assoc good"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGoodIsCompTrue)] = "Assoc good Comp True"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocGoodIsCompFalse)] = "Assoc good Comp False"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBad)] = "Assoc bad"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBadIsCompTrue)] = "Assoc bad Comp True"; + labelReAssocMCTrackStatus[static_cast(ReAssocMCTrackStatus::kAssocBadIsCompFalse)] = "Assoc bad Comp False"; registry.get(HIST("ReAssocMC/hReAssocMCTrackStatus"))->SetMinimum(0.1); - for (int iBin = 0; iBin < static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatus); iBin++) { + for (int iBin = 0; iBin < static_cast(ReAssocMCTrackStatus::nReAssocMCTrackStatusCheck); iBin++) { registry.get(HIST("ReAssocMC/hReAssocMCTrackStatus"))->GetXaxis()->SetBinLabel(iBin + 1, labelReAssocMCTrackStatus[iBin].data()); } // Vertex resolution - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbAll)] = registry.add("ReAssocMC/hVtxResNonAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkIdGt0)] = registry.add("ReAssocMC/hVtxResIdGt0", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmb)] = registry.add("ReAssocMC/hVtxResNonAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)] = registry.add("ReAssocMC/hVtxResNonAmbGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)] = registry.add("ReAssocMC/hVtxResNonAmbBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbAll)] = registry.add("ReAssocMC/hVtxResAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbGood)] = registry.add("ReAssocMC/hVtxResAmbGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbBad)] = registry.add("ReAssocMC/hVtxResAmbBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbAllE)] = registry.add("ReAssocMC/hVtxResNonAmbAllE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbGoodE)] = registry.add("ReAssocMC/hVtxResNonAmbGoodE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbBadE)] = registry.add("ReAssocMC/hVtxResNonAmbBadE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssoc)] = registry.add("ReAssocMC/hVtxResAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGood)] = registry.add("ReAssocMC/hVtxResAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hVtxResAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompFalse)] = registry.add("ReAssocMC/hVtxResAssocGoodIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBad)] = registry.add("ReAssocMC/hVtxResAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBadIsCompTrue)] = registry.add("ReAssocMC/hVtxResAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBadIsCompFalse)] = registry.add("ReAssocMC/hVtxResAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbID)] = registry.add("ReAssocMC/hVtxResNonAmbID", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDGood)] = registry.add("ReAssocMC/hVtxResNonAmbIDGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDBad)] = registry.add("ReAssocMC/hVtxResNonAmbIDBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbID)] = registry.add("ReAssocMC/hVtxResAmbID", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbIDGood)] = registry.add("ReAssocMC/hVtxResAmbIDGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbIDBad)] = registry.add("ReAssocMC/hVtxResAmbIDBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtra)] = registry.add("ReAssocMC/hVtxResNonAmbIDExtra", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraGood)] = registry.add("ReAssocMC/hVtxResNonAmbIDExtraGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraBad)] = registry.add("ReAssocMC/hVtxResNonAmbIDExtraBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssoc)] = registry.add("ReAssocMC/hVtxResReAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocGood)] = registry.add("ReAssocMC/hVtxResReAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hVtxResReAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); @@ -1230,24 +1259,28 @@ struct DndetaMFTPbPb { hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocBad)] = registry.add("ReAssocMC/hVtxResReAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocBadIsCompTrue)] = registry.add("ReAssocMC/hVtxResReAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocBadIsCompFalse)] = registry.add("ReAssocMC/hVtxResReAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssoc)] = registry.add("ReAssocMC/hVtxResAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGood)] = registry.add("ReAssocMC/hVtxResAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hVtxResAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompFalse)] = registry.add("ReAssocMC/hVtxResAssocGoodIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBad)] = registry.add("ReAssocMC/hVtxResAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBadIsCompTrue)] = registry.add("ReAssocMC/hVtxResAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBadIsCompFalse)] = registry.add("ReAssocMC/hVtxResAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // DCA - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbAll)] = registry.add("ReAssocMC/hDCANonAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkIdGt0)] = registry.add("ReAssocMC/hDCAIdGt0", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmb)] = registry.add("ReAssocMC/hDCANonAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)] = registry.add("ReAssocMC/hDCANonAmbGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)] = registry.add("ReAssocMC/hDCANonAmbBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbAll)] = registry.add("ReAssocMC/hDCAAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbGood)] = registry.add("ReAssocMC/hDCAAmbGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbBad)] = registry.add("ReAssocMC/hDCAAmbBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbAllE)] = registry.add("ReAssocMC/hDCANonAmbAllE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbGoodE)] = registry.add("ReAssocMC/hDCANonAmbGoodE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbBadE)] = registry.add("ReAssocMC/hDCANonAmbBadE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssoc)] = registry.add("ReAssocMC/hDCAAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGood)] = registry.add("ReAssocMC/hDCAAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hDCAAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompFalse)] = registry.add("ReAssocMC/hDCAAssocGoodIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBad)] = registry.add("ReAssocMC/hDCAAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBadIsCompTrue)] = registry.add("ReAssocMC/hDCAAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBadIsCompFalse)] = registry.add("ReAssocMC/hDCAAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbID)] = registry.add("ReAssocMC/hDCAAmbAll", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDGood)] = registry.add("ReAssocMC/hDCAAmbGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDBad)] = registry.add("ReAssocMC/hDCAAmbBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbID)] = registry.add("ReAssocMC/hDCANonAmbAllE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbIDGood)] = registry.add("ReAssocMC/hDCANonAmbGoodE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbIDBad)] = registry.add("ReAssocMC/hDCANonAmbBadE", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtra)] = registry.add("ReAssocMC/hDCANonAmbIDExtra", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraGood)] = registry.add("ReAssocMC/hDCANonAmbIDExtraGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraBad)] = registry.add("ReAssocMC/hDCANonAmbIDExtraBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssoc)] = registry.add("ReAssocMC/hDCAReAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocGood)] = registry.add("ReAssocMC/hDCAReAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hDCAReAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); @@ -1255,6 +1288,13 @@ struct DndetaMFTPbPb { hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocBad)] = registry.add("ReAssocMC/hDCAReAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocBadIsCompTrue)] = registry.add("ReAssocMC/hDCAReAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocBadIsCompFalse)] = registry.add("ReAssocMC/hDCAReAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssoc)] = registry.add("ReAssocMC/hDCAAssoc", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGood)] = registry.add("ReAssocMC/hDCAAssocGood", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompTrue)] = registry.add("ReAssocMC/hDCAAssocGoodIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompFalse)] = registry.add("ReAssocMC/hDCAAssocGoodIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBad)] = registry.add("ReAssocMC/hDCAAssocBad", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBadIsCompTrue)] = registry.add("ReAssocMC/hDCAAssocBadIsCompTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBadIsCompFalse)] = registry.add("ReAssocMC/hDCAAssocBadIsCompFalse", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); } if (doprocessEfficiencyInclusive) { @@ -1304,12 +1344,6 @@ struct DndetaMFTPbPb { for (int iBin = 0; iBin < static_cast(TrackToCollEvtType::nTrackToCollEvtType); iBin++) { qaregistry.get(HIST("Events/hTrackToCollEvtType"))->GetXaxis()->SetBinLabel(iBin + 1, labelTrkToCollEvt[iBin].data()); } - // registry.add({"Events/EvtGenRec", ";status", {HistType::kTH1F, {{3, 0.5, 3.5}}}}); - // auto heff = registry.get(HIST("Events/EvtGenRec")); - // auto* h = heff->GetXaxis(); - // h->SetBinLabel(1, "All generated"); - // h->SetBinLabel(2, "All reconstructed"); - // h->SetBinLabel(3, "Selected reconstructed"); qaregistry.add("TrkCompColls/hAmbTrackType", ";status", {HistType::kTH1F, {{static_cast(AmbTrkType::nAmbTrkType), -0.5, +static_cast(AmbTrkType::nAmbTrkType) - 0.5}}}); std::string labelAmbiguity[CambTrkType]; @@ -1350,12 +1384,6 @@ struct DndetaMFTPbPb { for (int iBin = 0; iBin < static_cast(TrackToCollEvtType::nTrackToCollEvtType); iBin++) { qaregistry.get(HIST("Events/Centrality/hTrackToCollEvtType"))->GetXaxis()->SetBinLabel(iBin + 1, labelTrkToCollEvt[iBin].data()); } - // registry.add({"Events/Centrality/EvtGenRec", ";status;centrality", {HistType::kTH2F, {{3, 0.5, 3.5}, centralityAxis}}}); - // auto heff = registry.get(HIST("Events/Centrality/EvtGenRec")); - // auto* h = heff->GetXaxis(); - // h->SetBinLabel(1, "All generated"); - // h->SetBinLabel(2, "All reconstructed"); - // h->SetBinLabel(3, "Selected reconstructed"); qaregistry.add("TrkCompColls/Centrality/hAmbTrackType", ";status;centrality", {HistType::kTH2F, {{static_cast(AmbTrkType::nAmbTrkType), -0.5, +static_cast(AmbTrkType::nAmbTrkType) - 0.5}, centralityAxis}}); std::string labelAmbiguity[CambTrkType]; @@ -1487,33 +1515,38 @@ struct DndetaMFTPbPb { registry.add({"TimeAssocMC/hVertexResV1", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); registry.add({"TimeAssocMC/hVertexResV2", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelGoodVtxBad", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelNonAmbAll", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmb", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbGoodVtx", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); registry.add({"TimeAssocMC/hVTXkSelNonAmbGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelNonAmbGoodVtxBad", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelNonAmbSameAll", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelNonAmbSameGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelNonAmbSameGoodVtxBad", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelAmbAll", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbID", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbIDGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbIDBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelAmbID", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelAmbIDGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelAmbIDBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbIDExtra", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbIDExtraGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelNonAmbIDExtraBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + registry.add({"TimeAssocMC/hVTXkSelAmb", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); registry.add({"TimeAssocMC/hVTXkSelAmbGoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelAmbGoodVtxBad", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelAmbGt1All", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelAmbGt1GoodVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - registry.add({"TimeAssocMC/hVTXkSelAmbGt1GoodVtxBad", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); - - registry.add("TimeAssocMC/hTimeAssocCheckVtxType", ";status", {HistType::kTH1F, {{static_cast(ReassocCheckVtxType::nReassocVtxType), -0.5, +static_cast(ReassocCheckVtxType::nReassocVtxType) - 0.5}}}); - std::string labelReAssocVtxType[CreassocVtxType]; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxAllTrue)] = "kIsTrueVtxAll=True"; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxAllFalse)] = "kIsTrueVtxAll=False"; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxVsGoodVtxTrue)] = "kIsTrueVtxVsGoodVtx=True"; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxVsGoodVtxFalse)] = "kIsTrueVtxVsGoodVtx=False"; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxVsBadVtxTrue)] = "kIsTrueVtxVsBadVtx=True"; - labelReAssocVtxType[static_cast(ReassocCheckVtxType::kIsTrueVtxVsBadVtxFalse)] = "kIsTrueVtxVsBadVtx=False"; + registry.add({"TimeAssocMC/hVTXkSelAmbBadVtxTrue", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis}}}); + + registry.add("TimeAssocMC/hTimeAssocCheckVtxType", ";status", {HistType::kTH1F, {{static_cast(AssocCheckVtxType::nAssocVtxType), -0.5, +static_cast(AssocCheckVtxType::nAssocVtxType) - 0.5}}}); + std::string labelAssocVtxType[CreassocVtxType]; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllVtxTrue)] = "kAllVtx=True"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllVtxFalse)] = "kAllVtx=False"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllGoodVtx)] = "kAllGoodVtx"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllGoodVtxTrue)] = "kAllGoodVtx=True"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllGoodVtxFalse)] = "kAllGoodVtx=False"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllBadVtx)] = "kAllBadVtx"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllBadVtxTrue)] = "kAllBadVtx=True"; + labelAssocVtxType[static_cast(AssocCheckVtxType::kAllBadVtxFalse)] = "kAllBadVtx=False"; registry.get(HIST("TimeAssocMC/hTimeAssocCheckVtxType"))->SetMinimum(0.1); - for (int iBin = 0; iBin < static_cast(ReassocCheckVtxType::nReassocVtxType); iBin++) { - registry.get(HIST("TimeAssocMC/hTimeAssocCheckVtxType"))->GetXaxis()->SetBinLabel(iBin + 1, labelReAssocVtxType[iBin].data()); + for (int iBin = 0; iBin < static_cast(AssocCheckVtxType::nAssocVtxType); iBin++) { + registry.get(HIST("TimeAssocMC/hTimeAssocCheckVtxType"))->GetXaxis()->SetBinLabel(iBin + 1, labelAssocVtxType[iBin].data()); } registry.add("TimeAssocMC/hAmbTrackType", ";status", {HistType::kTH1F, {{static_cast(AmbTrkType::nAmbTrkType), -0.5, +static_cast(AmbTrkType::nAmbTrkType) - 0.5}}}); @@ -1532,21 +1565,28 @@ struct DndetaMFTPbPb { registry.add("TimeAssocMC/hAmbTrkTypeAssocFlag", ";status", {HistType::kTH1F, {{static_cast(AmbTrkTypeAssocFlag::nSelAmbTrkTypeAssocFlag), -0.5, +static_cast(AmbTrkTypeAssocFlag::nSelAmbTrkTypeAssocFlag) - 0.5}}}); std::string lAmbTrackType[CselAmbTrkTypeAssocFlag]; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSel)] = "all sel"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxTrue)] = "all good vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxBad)] = "all bad vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbAll)] = "non-amb"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtxTrue)] = "non-amb good vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtxBad)] = "non-amb bad vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameAll)] = "non-amb (same)"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameGoodVtxTrue)] = "non-amb (same) good vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameGoodVtxBad)] = "non-amb (same) bad vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbAll)] = "amb"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxTrue)] = "amb good vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxBad)] = "amb bad vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1All)] = "ambGt1"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1GoodVtxTrue)] = "ambGt1 good vtx"; - lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1GoodVtxBad)] = "ambGt1 bad vtx"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAll)] = "all sel"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelGoodVtx)] = "all sel good vtx"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxTrue)] = "all sel good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelBadVtx)] = "all sel bad vtx"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelBadVtxTrue)] = "all sel bad vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmb)] = "all non-amb"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtx)] = "non-amb good vtx"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtxTrue)] = "non-amb good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbBadVtx)] = "non-amb bad vtx"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbBadVtxTrue)] = "non-amb bad vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbID)] = "non-amb id"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDGoodVtxTrue)] = "non-amb id good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDBadVtxTrue)] = "non-amb bad vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbID)] = "amb id"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbIDGoodVtxTrue)] = "amb id good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbIDBadVtxTrue)] = "amb id bad vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtra)] = "non-amb id ext"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtraGoodVtxTrue)] = "non-amb id ext good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtraBadVtxTrue)] = "non-amb id ext bad vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmb)] = "amb all"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxTrue)] = "amb good vtx true"; + lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelAmbBadVtxTrue)] = "amb bad vtx true"; lAmbTrackType[static_cast(AmbTrkTypeAssocFlag::kSelOrphanNull)] = "orhpan null"; registry.get(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"))->SetMinimum(0.1); for (int iBin = 0; iBin < static_cast(AmbTrkTypeAssocFlag::nSelAmbTrkTypeAssocFlag); iBin++) { @@ -3712,7 +3752,6 @@ struct DndetaMFTPbPb { PROCESS_SWITCH(DndetaMFTPbPb, processCheckAmbiguousMftTracks, "Process checks for Ambiguous MFT tracks (inclusive)", false); - // Preslice perColMc = aod::mcparticle::mcCollisionId; void processTimeAssocMC(CollsMCExtra const& mcCollisions, CollisionsWithMCLabels const& collisions, MftTracksWCollsMC const& tracks, @@ -3726,9 +3765,14 @@ struct DndetaMFTPbPb { const auto& nLabels = labels.size(); LOG(info) << "collision labels: " << nLabels; + std::unordered_set setRecCollSel; + setRecCollSel.reserve(nRecoColls); std::unordered_map mapRecToMc; mapRecToMc.clear(); mapRecToMc.reserve(nRecoColls); + std::unordered_map mapMcToRec; + mapMcToRec.clear(); + mapMcToRec.reserve(nRecoColls); // std::unordered_map mapVtxXrec; mapVtxXrec.clear(); @@ -3750,11 +3794,13 @@ struct DndetaMFTPbPb { if (maxNcontributors < collision.numContrib()) { maxNcontributors = collision.numContrib(); bestCollIndex = collision.globalIndex(); - mapVtxXrec.emplace(collision.globalIndex(), collision.posX()); - mapVtxYrec.emplace(collision.globalIndex(), collision.posY()); - mapVtxZrec.emplace(collision.globalIndex(), collision.posZ()); - mapRecToMc.emplace(collision.globalIndex(), collision.mcCollisionId()); } + mapVtxXrec.emplace(collision.globalIndex(), collision.posX()); + mapVtxYrec.emplace(collision.globalIndex(), collision.posY()); + mapVtxZrec.emplace(collision.globalIndex(), collision.posZ()); + mapRecToMc.emplace(collision.globalIndex(), collision.mcCollisionId()); + mapMcToRec.emplace(collision.mcCollisionId(), collision.globalIndex()); + setRecCollSel.insert(collision.globalIndex()); } LOG(info) << "mapRecToMc size: " << mapRecToMc.size(); LOG(info) << "mapVtxXrec size: " << mapVtxXrec.size(); @@ -3812,7 +3858,11 @@ struct DndetaMFTPbPb { } auto trkCollId = track.has_collision() ? track.collisionId() : -1; auto ids = track.compatibleCollIds(); - if (trkCollId != recCollId) { // check if track is associated to rec coll + // check if track is associated to rec coll + // if (trkCollId != recCollId) { + // continue; + // } + if (setRecCollSel.find(trkCollId) == setRecCollSel.end()) { continue; } registry.fill(HIST("TimeAssocMC/hAmbTrackType"), static_cast(AmbTrkType::kAll)); @@ -3830,6 +3880,7 @@ struct DndetaMFTPbPb { if (gConf.cfgRemoveAmbiguousTracks && (track.compatibleCollIds().size() != 1)) { continue; } + if (ids.size() > 0) { if (ids.size() == 1) { if (trkCollId == ids[0]) { @@ -3863,7 +3914,6 @@ struct DndetaMFTPbPb { float deltaZv2 = -1.; if (track.collisionId() >= 0 && track.has_mcParticle() && track.mcMask() == 0) { - auto itMCTrk = mapRecToMc.find(trkCollId); const auto& mcPart = track.mcParticle(); if (!isChrgParticle(mcPart.pdgCode())) { continue; @@ -3872,16 +3922,15 @@ struct DndetaMFTPbPb { continue; } int64_t mcPartId = mcPart.mcCollisionId(); - // check if rec vertex is available in MC collisions - for (const auto& mcTrkId : mapRecToMc) { + for (const auto& mcTrkId : mapMcToRec) { if (mcTrkId.second == mcPartId) { isTrueVtx = true; break; } } - // check if there is good or bad collision + auto itMCTrk = mapRecToMc.find(trkCollId); if (itMCTrk != mapRecToMc.end()) { int mcTrkCollId = itMCTrk->second; if (mcPartId == mcTrkCollId) { // particle.mcCollisionId == collision.mcCollisionId -> good vtx @@ -3890,7 +3939,6 @@ struct DndetaMFTPbPb { vtxFlag = static_cast(VertexStatusMC::kBad); } } - if (mapVtxXrec.find(trkCollId) == mapVtxXrec.end()) { continue; } @@ -3929,99 +3977,118 @@ struct DndetaMFTPbPb { deltaXv2 = vtxX - mapVtxXgen.find(mcCollIdRec)->second; deltaYv2 = vtxY - mapVtxYgen.find(mcCollIdRec)->second; deltaZv2 = vtxZ - mapVtxZgen.find(mcCollIdRec)->second; - } - - registry.fill(HIST("TimeAssocMC/VtxStatus"), vtxFlag); - registry.fill(HIST("TimeAssocMC/hVertexResV1"), deltaXv1, deltaYv1, deltaZv1); - registry.fill(HIST("TimeAssocMC/hVertexResV2"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSel)); + registry.fill(HIST("TimeAssocMC/VtxStatus"), vtxFlag); + registry.fill(HIST("TimeAssocMC/hVertexResV1"), deltaXv1, deltaYv1, deltaZv1); + registry.fill(HIST("TimeAssocMC/hVertexResV2"), deltaXv2, deltaYv2, deltaZv2); - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxAllTrue)); - } else { - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxAllFalse)); - } - if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAll)); if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxTrue)); - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxVsGoodVtxTrue)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllVtxTrue)); } else { - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxVsGoodVtxFalse)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllVtxFalse)); } - } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelGoodVtxBad"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxBad)); - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxVsBadVtxTrue)); - } else { - registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(ReassocCheckVtxType::kIsTrueVtxVsBadVtxFalse)); + if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelGoodVtx)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllGoodVtx)); + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelGoodVtxTrue)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllGoodVtxTrue)); + } else { + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllGoodVtxFalse)); + } + } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelBadVtx)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllBadVtx)); + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelBadVtxTrue)); + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllBadVtxTrue)); + } else { + registry.fill(HIST("TimeAssocMC/hTimeAssocCheckVtxType"), static_cast(AssocCheckVtxType::kAllBadVtxFalse)); + } } - } - if (ids.size() > 0) { - if (ids.size() == 1) { - if (trkCollId == ids[0]) { // non ambiguous - registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbAll"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbAll)); + if (ids.size() > 0) { + if (ids.size() == 1) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmb"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmb)); if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbGoodVtx"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtx)); if (isTrueVtx) { registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtxTrue)); } } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbBadVtx)); if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbGoodVtxBad"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbGoodVtxBad)); + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbBadVtxTrue)); } } - } else if (trkCollId != ids[0]) { - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbAll"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbAll)); - if (vtxFlag == static_cast(VertexStatusMC::kGood)) { - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxTrue)); + if (trkCollId == ids[0]) { // non ambiguous + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbID"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbID)); + if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbIDGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDGoodVtxTrue)); + } + } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbIDBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDBadVtxTrue)); + } } - } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGoodVtxBad"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxBad)); + } else if (trkCollId != ids[0]) { + registry.fill(HIST("TimeAssocMC/hVTXkSelAmbID"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbID)); + if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelAmbIDGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbIDGoodVtxTrue)); + } + } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelAmbIDBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbIDBadVtxTrue)); + } + } + } else { // non ambiguous (extra) + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbIDExtra"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtra)); + if (vtxFlag == static_cast(VertexStatusMC::kGood)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbIDExtraGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtraGoodVtxTrue)); + } + } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { + if (isTrueVtx) { + registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbIDExtraBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbIDExtraBadVtxTrue)); + } } } - } else { // non ambiguous (extra) - registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbSameAll"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameAll)); + } else { // ambiguous + registry.fill(HIST("TimeAssocMC/hVTXkSelAmb"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmb)); if (vtxFlag == static_cast(VertexStatusMC::kGood)) { if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbSameGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameGoodVtxTrue)); + registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGoodVtxTrue)); } } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelNonAmbSameGoodVtxBad"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelNonAmbSameGoodVtxBad)); + registry.fill(HIST("TimeAssocMC/hVTXkSelAmbBadVtxTrue"), deltaXv2, deltaYv2, deltaZv2); + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbBadVtxTrue)); } } } - } else { // ambiguous - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGt1All"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1All)); - if (vtxFlag == static_cast(VertexStatusMC::kGood)) { - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGt1GoodVtxTrue"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1GoodVtxTrue)); - } - } else if (vtxFlag == static_cast(VertexStatusMC::kBad)) { - if (isTrueVtx) { - registry.fill(HIST("TimeAssocMC/hVTXkSelAmbGt1GoodVtxBad"), deltaXv2, deltaYv2, deltaZv2); - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelAmbGt1GoodVtxBad)); - } - } + } else { + registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelOrphanNull)); } - } else { - registry.fill(HIST("TimeAssocMC/hAmbTrkTypeAssocFlag"), static_cast(AmbTrkTypeAssocFlag::kSelOrphanNull)); } } } @@ -4614,47 +4681,60 @@ struct DndetaMFTPbPb { registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkHasMcPart)); if (ids.size() > 0) { + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkIdGt0)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkIdGt0)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkIdGt0)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); if (ids.size() == 1) { + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmb)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmb)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmb)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbGood)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbBad)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + } if (itrack.collisionId() == ids[0]) { // non ambiguous - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbAll)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbAll)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbAll)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbID)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbID)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbID)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbGood)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbGood)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDGood)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDGood)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); } else { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbBad)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbBad)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDBad)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDBad)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); } } else if (itrack.collisionId() != ids[0]) { // ambiguous extra - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbAll)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbAll)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbAll)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbID)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbID)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbID)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbGood)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbGood)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbIDGood)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbIDGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbIDGood)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); } else { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbBad)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbBad)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkAmbIDBad)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkAmbIDBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkAmbIDBad)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); } } else { // non ambiguous (extra) - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbAllE)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbAllE)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbAllE)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); - + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtra)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtra)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtra)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbGoodE)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbGoodE)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbGoodE)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtraGood)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraGood)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); } else { - registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbBadE)); - hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbBadE)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbBadE)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); + registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kTrkNonAmbIDExtraBad)); + hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + hReAssocDCA[static_cast(HistStatusReAssocVtx::kTrkNonAmbIDExtraBad)]->Fill(itrack.pt(), itrack.eta(), 0., 0., dcaXYtruth, dcaZtruth); } } } else { // ambiguous @@ -4664,12 +4744,10 @@ struct DndetaMFTPbPb { registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kReAssoc)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssoc)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssoc)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { // good coll registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kReAssocGood)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocGood)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (isInCoColl) { // coll vertex is among compatible colls registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kReAssocGoodIsCompTrue)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocGoodIsCompTrue)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); @@ -4683,7 +4761,6 @@ struct DndetaMFTPbPb { registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kReAssocBad)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kReAssocBad)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (isInCoColl) { // coll vertex is among compatible colls registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kReAssocBadIsCompTrue)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kReAssocBadIsCompTrue)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); @@ -4698,12 +4775,10 @@ struct DndetaMFTPbPb { registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kAssoc)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssoc)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssoc)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { // good coll registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kAssocGood)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGood)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocGood)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (isInCoColl) { // coll vertex is among compatible colls registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kAssocGoodIsCompTrue)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocGoodIsCompTrue)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); @@ -4717,7 +4792,6 @@ struct DndetaMFTPbPb { registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kAssocBad)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBad)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); hReAssocDCA[static_cast(HistStatusReAssocVtx::kAssocBad)]->Fill(itrack.pt(), itrack.eta(), atrack.bestDCAXY(), bestDcaZ, dcaXYtruth, dcaZtruth); - if (isInCoColl) { // coll vertex is among compatible colls registry.fill(HIST("ReAssocMC/hReAssocMCTrackStatus"), static_cast(ReAssocMCTrackStatus::kAssocBadIsCompTrue)); hReAssocVtxRes[static_cast(HistStatusReAssocVtx::kAssocBadIsCompTrue)]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); From 5dd7ec290cee80803666c383cbab6411ee33a002 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Sun, 3 May 2026 23:41:44 +0530 Subject: [PATCH 016/449] [PWGCF] Added process MC generated (#16074) --- .../Tasks/v0ptHadPiKaProt.cxx | 137 ++++++++++++++++-- 1 file changed, 127 insertions(+), 10 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index eff32e7dd98..5e3bf2b9d14 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -166,6 +166,7 @@ struct V0ptHadPiKaProt { TF1* fPtDepDCAz = nullptr; O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCut, bool, true, "Use additional event cut on mult correlations for small ions") + O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCutInMC, bool, false, "Use additional event cut on mult correlations for small ions while using MC generated") O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") struct : ConfigurableGroup { @@ -229,6 +230,9 @@ struct V0ptHadPiKaProt { using MyMCRecCollisions = soa::Filtered>; using MyMCTracks = soa::Filtered>; + using EventCandidatesMC = soa::Join; + + Preslice perCollision = aod::track::collisionId; Preslice perMcCollision = aod::mcparticle::mcCollisionId; std::array tofNsigmaCut; @@ -357,9 +361,9 @@ struct V0ptHadPiKaProt { histos.add("h2DnsigmaPionTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); histos.add("h2DnsigmaKaonTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); histos.add("h2DnsigmaProtonTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); - histos.add("h2DnsigmaPionTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH2F, {nSigmaAxis, nSigmaAxis}); - histos.add("h2DnsigmaKaonTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH2F, {nSigmaAxis, nSigmaAxis}); - histos.add("h2DnsigmaProtonTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); // Analysis profiles @@ -403,6 +407,12 @@ struct V0ptHadPiKaProt { histos.add("Prof_XY_weighted", "", {HistType::kTProfile2D, {centAxis, noAxis}}); histos.add("Prof_XYZ_weighted_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); histos.add("Prof_Z_weighted_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weighted_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weighted_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weighted_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weighted_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weighted_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weighted_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); } // initial array @@ -503,6 +513,10 @@ struct V0ptHadPiKaProt { histos.add("MCGenerated/hPtEtaPhiPion", "MC charged pions' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCGenerated/hPtEtaPhiKaon", "MC charged kaons' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCGenerated/hPtEtaPhiProton", "MC charged protons' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); + histos.add("MCGenerated/hPtEtaPhiCharged_gen", "MC charged particles' pt, eta, phi in the generated process", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); + histos.add("MCGenerated/hPtEtaPhiPion_gen", "MC charged pions' pt, eta, phi in the generated process", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); + histos.add("MCGenerated/hPtEtaPhiKaon_gen", "MC charged kaons' pt, eta, phi in the generated process", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); + histos.add("MCGenerated/hPtEtaPhiProton_gen", "MC charged protons' pt, eta, phi in the generated process", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCReconstructed/hPtEtaPhiChargedParticle", "MC reconstructed charged particles' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCReconstructed/hPtEtaPhiChargedTrack", "MC reconstructed charged tracks' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); @@ -927,6 +941,109 @@ struct V0ptHadPiKaProt { return ptweight; } + void processMCGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions, MyMCTracks const& tracks) + { + histos.fill(HIST("MCGenerated/hMC"), 0.5); + if (std::abs(mcCollision.posZ()) < cfgCutVertex) { + histos.fill(HIST("MCGenerated/hMC"), 1.5); + } + auto cent = 0; + + int nchInel = 0; + for (const auto& mcParticle : mcParticles) { + auto pdgcode = std::abs(mcParticle.pdgCode()); + if (mcParticle.isPhysicalPrimary() && (pdgcode == PDG_t::kPiPlus || pdgcode == PDG_t::kKPlus || pdgcode == PDG_t::kProton || pdgcode == PDG_t::kElectron || pdgcode == PDG_t::kMuonMinus)) { + if (std::abs(mcParticle.eta()) < 1.0) { + nchInel = nchInel + 1; + } + } + } + if (nchInel > 0 && std::abs(mcCollision.posZ()) < cfgCutVertex) + histos.fill(HIST("MCGenerated/hMC"), 2.5); + std::vector selectedEvents(collisions.size()); + int nevts = 0; + + for (const auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { + continue; + } + if (cfgUseGoodITSLayerAllCut && !(collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (cfgEvSelkNoSameBunchPileup && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (cfgEvSelkNoITSROFrameBorder && !(collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (cfgEvSelkNoTimeFrameBorder && !(collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (cfgEvSelUseGoodZvtxFT0vsPV && !(collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + + // events with selection bits based on occupancy time pattern + if (cfgEvSelUseOcuppancyTimeCut && !(collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + + int occupancy = collision.trackOccupancyInTimeRange(); + if (cfgEvSelSetOcuppancyRange && (occupancy < cfgMinOccupancy || occupancy > cfgMaxOccupancy)) { + continue; + } + + auto rectrackspart = tracks.sliceBy(perCollision, collision.globalIndex()); + cent = collision.centFT0C(); + if (cfgUseSmallIonAdditionalEventCutInMC && !eventSelectedSmallion(collision, rectrackspart.size(), cent)) { + continue; + } + + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + } + selectedEvents.resize(nevts); + const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); + histos.fill(HIST("MCGenerated/hMC"), 3.5); + if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + return; + } + histos.fill(HIST("MCGenerated/hMC"), 4.5); + histos.fill(HIST("MCGenerated/hCentgen"), cent); + + // creating phi, pt, eta dstribution of generted MC particles + + // Generated track variables + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.has_mcCollision()) + continue; + + // charged check + auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (!pdgEntry) + continue; + if (pdgEntry->Charge() == 0) + continue; + + if (mcParticle.isPhysicalPrimary()) { + if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPtUpper) && (std::abs(mcParticle.eta()) < cfgCutEta)) { + histos.fill(HIST("MCGenerated/hPtEtaPhiCharged_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); + + auto pdgcode = std::abs(mcParticle.pdgCode()); + + if (pdgcode == PDG_t::kPiPlus) + histos.fill(HIST("MCGenerated/hPtEtaPhiPion_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); + + if (pdgcode == PDG_t::kKPlus) + histos.fill(HIST("MCGenerated/hPtEtaPhiKaon_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); + + if (pdgcode == PDG_t::kProton) + histos.fill(HIST("MCGenerated/hPtEtaPhiProton_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); + } + } + } //! end particle loop + } + PROCESS_SWITCH(V0ptHadPiKaProt, processMCGen, "Process Monte-carlo generated data", false); + // process MC recosnstructed data void processMCRec(MyMCRecCollisions::iterator const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const& mcParticles) { @@ -1082,17 +1199,17 @@ struct V0ptHadPiKaProt { if (isPion) { histos.fill(HIST("h2DnsigmaPionTpcVsPtAfterCut"), track.pt(), nSigmaTpcPi); histos.fill(HIST("h2DnsigmaPionTofVsPtAfterCut"), track.pt(), nSigmaTofPi); - histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), nSigmaTpcPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), track.pt(), nSigmaTpcPi, nSigmaTofPi); } if (isKaon) { histos.fill(HIST("h2DnsigmaKaonTpcVsPtAfterCut"), track.pt(), nSigmaTpcKa); histos.fill(HIST("h2DnsigmaKaonTofVsPtAfterCut"), track.pt(), nSigmaTofKa); - histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), nSigmaTpcKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), track.pt(), nSigmaTpcKa, nSigmaTofKa); } if (isProton) { histos.fill(HIST("h2DnsigmaProtonTpcVsPtAfterCut"), track.pt(), nSigmaTpcProt); histos.fill(HIST("h2DnsigmaProtonTofVsPtAfterCut"), track.pt(), nSigmaTofProt); - histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), track.pt(), nSigmaTpcProt, nSigmaTofProt); } auto pdgcodeRec = std::abs(particle.pdgCode()); @@ -1121,7 +1238,7 @@ struct V0ptHadPiKaProt { } } // end track loop } - PROCESS_SWITCH(V0ptHadPiKaProt, processMCRec, "Process Monte-carlo data", false); + PROCESS_SWITCH(V0ptHadPiKaProt, processMCRec, "Process Monte-carlo reconstructed data", false); // process Data void processData(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) @@ -1301,17 +1418,17 @@ struct V0ptHadPiKaProt { if (isPion) { histos.fill(HIST("h2DnsigmaPionTpcVsPtAfterCut"), trkPt, nSigmaTpcPi); histos.fill(HIST("h2DnsigmaPionTofVsPtAfterCut"), trkPt, nSigmaTofPi); - histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), nSigmaTpcPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), trkPt, nSigmaTpcPi, nSigmaTofPi); } if (isKaon) { histos.fill(HIST("h2DnsigmaKaonTpcVsPtAfterCut"), trkPt, nSigmaTpcKa); histos.fill(HIST("h2DnsigmaKaonTofVsPtAfterCut"), trkPt, nSigmaTofKa); - histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), nSigmaTpcKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), trkPt, nSigmaTpcKa, nSigmaTofKa); } if (isProton) { histos.fill(HIST("h2DnsigmaProtonTpcVsPtAfterCut"), trkPt, nSigmaTpcProt); histos.fill(HIST("h2DnsigmaProtonTofVsPtAfterCut"), trkPt, nSigmaTofProt); - histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), trkPt, nSigmaTpcProt, nSigmaTofProt); } if (track.sign() != 0) { From 5be3cf46ea4e1e3178f839f5a34814d03a432a43 Mon Sep 17 00:00:00 2001 From: Jinhyun Park <125851562+jinhyunni@users.noreply.github.com> Date: Mon, 4 May 2026 09:45:38 +0900 Subject: [PATCH 017/449] [PWGHF] [xic0omegac0] Updated candidate creator & candidate selector (#16042) Co-authored-by: Jinhyun Park Co-authored-by: ALICE Action Bot --- .../candidateCreatorXic0Omegac0Qa.cxx | 47 ++++--------------- .../candidateSelectorToXiPiQa.cxx | 44 ++++++++--------- 2 files changed, 33 insertions(+), 58 deletions(-) diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx index 20b4fcaf307..f531919ebd9 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx @@ -258,16 +258,15 @@ struct HfCandidateCreatorXic0Omegac0Qa { HfEventSelection hfEvSel; // PDG Id of daughter tracks & V0s & cascades & charm baryons - Used in KFParticle - int pdgIdOfV0DauPos, pdgIdOfV0DauNeg, pdgIdOfBach, pdgIdOfCharmBach; - int pdgIdOfAntiV0DauPos, pdgIdOfAntiV0DauNeg, pdgIdOfAntiBach, pdgIdOfAntiCharmBach; - int pdgIdOfV0, pdgIdOfCascade, pdgIdOfCharmBaryon; + int pdgIdOfV0DauPos{}, pdgIdOfV0DauNeg{}, pdgIdOfBach{}, pdgIdOfCharmBach{}; + int pdgIdOfV0{}, pdgIdOfCascade{}, pdgIdOfCharmBaryon{}; // Track PID - Used in DCAFitter - int trackPidOfCascade; + int trackPidOfCascade{}; // Mass of daughter tracks & V0s & cascades & charm baryons; - float massOfV0DauPos, massOfV0DauNeg, massOfBach, massOfCharmBach; - float massOfV0, massOfCascade, massOfCharmBaryon; + float massOfV0DauPos{}, massOfV0DauNeg{}, massOfCharmBach{}; + float massOfV0{}, massOfCascade{}; // Pointer of histograms for QA std::shared_ptr hInvMassCharmBaryonToXiPi, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaKa; @@ -317,11 +316,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { pdgIdOfBach = kPiMinus; pdgIdOfCharmBach = kPiPlus; - pdgIdOfAntiV0DauPos = kPiPlus; - pdgIdOfAntiV0DauNeg = kProton; - pdgIdOfAntiBach = kPiPlus; - pdgIdOfAntiCharmBach = kPiMinus; - pdgIdOfV0 = kLambda0; pdgIdOfCascade = kXiMinus; pdgIdOfCharmBaryon = kXiC0; @@ -339,11 +333,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { pdgIdOfBach = kKMinus; pdgIdOfCharmBach = kPiPlus; - pdgIdOfAntiV0DauPos = kPiPlus; - pdgIdOfAntiV0DauNeg = kProton; - pdgIdOfAntiBach = kKPlus; - pdgIdOfAntiCharmBach = kPiMinus; - pdgIdOfV0 = kLambda0; pdgIdOfCascade = kOmegaMinus; pdgIdOfCharmBaryon = kOmegaC0; @@ -361,11 +350,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { pdgIdOfBach = kKMinus; pdgIdOfCharmBach = kKPlus; - pdgIdOfAntiV0DauPos = kPiPlus; - pdgIdOfAntiV0DauNeg = kProton; - pdgIdOfAntiBach = kKPlus; - pdgIdOfAntiCharmBach = kKMinus; - pdgIdOfV0 = kLambda0; pdgIdOfCascade = kOmegaMinus; pdgIdOfCharmBaryon = kOmegaC0; @@ -384,11 +368,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { LOGF(info, "PDG ID of Bachelor: %d", pdgIdOfBach); LOGF(info, "PDG ID of Charm Bachelor: %d", pdgIdOfCharmBach); LOGF(info, "-------------------------------------------"); - LOGF(info, "PDG ID of anti V0 positive daughter: %d", pdgIdOfAntiV0DauPos); - LOGF(info, "PDG ID of anti V0 negative daughter: %d", pdgIdOfAntiV0DauNeg); - LOGF(info, "PDG ID of anti Bachelor: %d", pdgIdOfAntiBach); - LOGF(info, "PDG ID of anti Charm Bachelor: %d", pdgIdOfAntiCharmBach); - LOGF(info, "-------------------------------------------"); LOGF(info, "PDG ID of V0: %d", pdgIdOfV0); LOGF(info, "PDG ID of Cascade: %d", pdgIdOfCascade); LOGF(info, "PDG ID of Charm Baryon: %d", pdgIdOfCharmBaryon); @@ -512,12 +491,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { } // end of initialization - //////////////////////////////////////////////////////////// - // // - // Candidate reconstruction with DCAFitter // - // // - //////////////////////////////////////////////////////////// - // template function for running charm baryon reconstruction with DCAFitter /// \brief centEstimator is for different centrality estimators /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmeagaK @@ -962,10 +935,10 @@ struct HfCandidateCreatorXic0Omegac0Qa { bool isAnti = (bachTrack.signed1Pt() > 0 ? true : false); - KFParticle kfPos(kfTrack0, (isAnti ? pdgIdOfAntiV0DauPos : pdgIdOfV0DauPos)); - KFParticle kfNeg(kfTrack1, (isAnti ? pdgIdOfAntiV0DauNeg : pdgIdOfV0DauNeg)); - KFParticle kfBach(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); - KFParticle kfBachRej(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); // Rej -> Used for Omegac0->OmegaPi only + KFParticle kfPos(kfTrack0, (isAnti ? -pdgIdOfV0DauNeg : pdgIdOfV0DauPos)); + KFParticle kfNeg(kfTrack1, (isAnti ? -pdgIdOfV0DauPos : pdgIdOfV0DauNeg)); + KFParticle kfBach(kfTrackBach, (isAnti ? -pdgIdOfBach : pdgIdOfBach)); + KFParticle kfBachRej(kfTrackBach, (isAnti ? -pdgIdOfBach : pdgIdOfBach)); // Rej -> Used for Omegac0->OmegaPi only // ~~~~~~~Construct V0 with KF~~~~~~~ const KFParticle* v0Daughters[2] = {&kfPos, &kfNeg}; @@ -1049,7 +1022,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { //~~~~~~~Construct Charm Baryon with KF~~~~~~~ auto trackCharmBachelor = tracks.rawIteratorAt(cand.prong0Id()); const KFPTrack kfTrackCharmBach = createKFPTrackFromTrack(trackCharmBachelor); - const KFParticle kfCharmBach(kfTrackCharmBach, (isAnti ? pdgIdOfAntiCharmBach : pdgIdOfCharmBach)); + const KFParticle kfCharmBach(kfTrackCharmBach, (isAnti ? -pdgIdOfCharmBach : pdgIdOfCharmBach)); const KFParticle* charmBaryonDaughters[2] = {&kfCharmBach, &kfCasc}; KFParticle kfCharmBaryon; diff --git a/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx index b6b40705557..8845d78ee70 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx @@ -295,7 +295,7 @@ struct HfCandidateSelectorToXiPiQa { // Selection on LF related informations // returns true if all cuts are passed template - bool SelectOnLF(const T& candidate, const int& inputPtBin) + bool selectOnLf(const T& candidate, const int& inputPtBin) { registry.fill(HIST("hSelStatusLf"), 0.0); @@ -442,7 +442,7 @@ struct HfCandidateSelectorToXiPiQa { // Apply cuts with charm baryon & charm bachelor related informations // returns true if all cuts are passed template - bool SelectOnHF(const T& candidate, const int& inputPtBin) + bool selectOnHf(const T& candidate, const int& inputPtBin) { registry.fill(HIST("hSelStatusHf"), 0.0); @@ -561,8 +561,8 @@ struct HfCandidateSelectorToXiPiQa { } // Topological selection - const bool selectionResOnLF = SelectOnLF(candidate, pTBin); - const bool selectionResOnHF = SelectOnHF(candidate, pTBin); + const bool selectionResOnLF = selectOnLf(candidate, pTBin); + const bool selectionResOnHF = selectOnHf(candidate, pTBin); if (!selectionResOnLF || !selectionResOnHF) { resultSelections = false; } @@ -699,23 +699,6 @@ struct HfCandidateSelectorToXiPiQa { statusInvMassCharmBaryon = true; } - // ML BDT selection - if (applyMl) { - bool isSelectedMlXic0 = false; - std::vector inputFeaturesXic0 = {}; - if constexpr (svReco == doDcaFitter) { - inputFeaturesXic0 = hfMlResponseDca.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); - isSelectedMlXic0 = hfMlResponseDca.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); - } else { - inputFeaturesXic0 = hfMlResponseKf.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); - isSelectedMlXic0 = hfMlResponseKf.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); - } - if (!isSelectedMlXic0) { - continue; - } - hfMlToXiPi(outputMlXic0ToXiPi); - } - // Fill in selection result if constexpr (svReco == doDcaFitter) { hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidCharmBaryon, statusInvMassLambda, statusInvMassCascade, statusInvMassCharmBaryon, resultSelections, infoTpcStored, infoTofStored, @@ -732,6 +715,25 @@ struct HfCandidateSelectorToXiPiQa { trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); } + // ML BDT selection if required + if (applyMl) { + bool isSelectedMlXic0 = false; + std::vector inputFeaturesXic0 = {}; + if constexpr (svReco == doDcaFitter) { + inputFeaturesXic0 = hfMlResponseDca.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseDca.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } else { + inputFeaturesXic0 = hfMlResponseKf.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseKf.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } + + hfMlToXiPi(outputMlXic0ToXiPi); + + if (!isSelectedMlXic0) { + continue; + } + } + // Fill in invariant mass histogram if (resultSelections) { registry.fill(HIST("hInvMassCharmBaryonWoPidInvMassCut"), invMassCharmBaryon); From b10c50b02a64ca673adce1e35c1792ad9bb7486d Mon Sep 17 00:00:00 2001 From: JStaa <39123272+JStaa@users.noreply.github.com> Date: Mon, 4 May 2026 11:30:17 +0200 Subject: [PATCH 018/449] [PWGCF] Changed the default value of several configurables (#16076) --- .../Tasks/threeParticleCorrelations.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index b6aab98d17e..d1aca1a5aab 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -82,14 +82,14 @@ struct ThreeParticleCorrelations { std::string prefix = "EventSelection"; Configurable zvtxMax{"zvtxMax", 10.0, "Maximum collision Z-vertex position (cm)"}; Configurable occupMin{"occupMin", 0, "Minimum collision occupancy"}; - Configurable occupMax{"occupMax", 15000, "Maximum collision occupancy"}; + Configurable occupMax{"occupMax", 500, "Maximum collision occupancy"}; Configurable useOccupCut{"useOccupCut", true, "Use the kNoCollInTimeRangeStandard cut"}; } evSelGroup; // V0 filter parameters struct : ConfigurableGroup { std::string prefix = "V0Selection"; - Configurable v0PtMin{"v0PtMin", 0.6, "Minimum V0 transverse momentum"}; + Configurable v0PtMin{"v0PtMin", 1.6, "Minimum V0 transverse momentum"}; Configurable v0PtMax{"v0PtMax", 12.0, "Maximum V0 transverse momentum"}; Configurable tpcNCrossedRows{"tpcNCrossedRows", 70.0, "Minimum number of TPC crossed rows"}; Configurable decayR{"decayR", 1.2, "Minimum V0 decay radius (cm)"}; @@ -191,7 +191,7 @@ struct ThreeParticleCorrelations { struct : ConfigurableGroup { std::string prefix = "processSwitchBoard"; Configurable confBfieldSwitch{"confBfieldSwitch", 0, "Switch for the detector magnetic field (1 if Pos, -1 if Neg, 0 if both)"}; - Configurable confRatioCorrectionSwitch{"confRatioCorrectionSwitch", false, "Switch for correcting the negative spectra back to the positive spectra"}; + Configurable confRatioCorrectionSwitch{"confRatioCorrectionSwitch", true, "Switch for correcting the negative spectra back to the positive spectra"}; Configurable confFakeV0Switch{"confFakeV0Switch", false, "Switch for the fakeV0Filter function"}; Configurable confRDSwitch{"confRDSwitch", true, "Switch for the radialDistanceFilter function"}; } switchGroup; From 5faec3d071e2332419c9ce78f2baf91b186ccd2b Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 4 May 2026 12:06:31 +0200 Subject: [PATCH 019/449] [PWGEM/Dilepton] add occupancy selection in MC (#16078) --- PWGEM/Dilepton/Core/DileptonMC.h | 6 ++++++ PWGEM/Dilepton/Core/SingleTrackQCMC.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index b7f34d5b398..a4950ca0233 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -2123,6 +2123,12 @@ struct DileptonMC { if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + continue; + } + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + continue; + } fRegistry.fill(HIST("MCEvent/after/hZvtx"), mccollision.posZ()); auto posTracks_per_coll = posTracksMC.sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 4abe7e585f7..2135886fa0e 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -953,6 +953,12 @@ struct SingleTrackQCMC { if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + continue; + } + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + continue; + } fRegistry.fill(HIST("MCEvent/after/hZvtx"), mccollision.posZ()); auto leptonsMC_per_coll = leptonsMC.sliceByCachedUnsorted(o2::aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); From 6198494fc50b1573538f3afb060e0463cfa138c9 Mon Sep 17 00:00:00 2001 From: glegras <71757105+glegras@users.noreply.github.com> Date: Mon, 4 May 2026 12:19:13 +0200 Subject: [PATCH 020/449] [PWGDQ] add tag and probe method for dalitz selection (#15948) --- PWGDQ/Core/AnalysisCut.h | 23 +- PWGDQ/Core/CutsLibrary.cxx | 382 +++++++++++++++++++------------- PWGDQ/Tasks/DalitzSelection.cxx | 276 +++++++++++++++++------ 3 files changed, 447 insertions(+), 234 deletions(-) diff --git a/PWGDQ/Core/AnalysisCut.h b/PWGDQ/Core/AnalysisCut.h index 16f2916fe93..f5144227868 100644 --- a/PWGDQ/Core/AnalysisCut.h +++ b/PWGDQ/Core/AnalysisCut.h @@ -9,9 +9,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no -// -// Class for analysis cuts applied on the variables defined in the VarManager +/// \author Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +/// \file AnalysisCut.h +/// \brief Class for analysis cuts applied on the variables defined in the VarManager // #ifndef PWGDQ_CORE_ANALYSISCUT_H_ @@ -22,6 +22,7 @@ #include +#include #include //_________________________________________________________________________ @@ -49,29 +50,29 @@ class AnalysisCut : public TNamed void PrintCuts(); struct CutContainer { - short fVar; // variable to be cut upon + int16_t fVar; // variable to be cut upon float fLow; // lower limit for the var float fHigh; // upper limit for the var bool fExclude; // if true, use the selection range for exclusion - short fDepVar; // first (optional) variable on which the cut depends + int16_t fDepVar; // first (optional) variable on which the cut depends float fDepLow; // lower limit for the first dependent var float fDepHigh; // upper limit for the first dependent var bool fDepExclude; // if true, then use the dependent variable range as exclusion - short fDepVar2; // second (optional) variable on which the cut depends + int16_t fDepVar2; // second (optional) variable on which the cut depends float fDep2Low; // lower limit for the second dependent var float fDep2High; // upper limit for the second dependent var bool fDep2Exclude; // if true, then use the dependent variable range as exclusion - TF1* fFuncLow; // function for the lower limit cut - TF1* fFuncHigh; // function for the upper limit cut + std::shared_ptr fFuncLow; // function for the lower limit cut + std::shared_ptr fFuncHigh; // function for the upper limit cut }; protected: std::vector fCuts; - ClassDef(AnalysisCut, 1); + ClassDef(AnalysisCut, 2); }; //____________________________________________________________________________ @@ -85,7 +86,7 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, // CutContainer cut = {}; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v>) { if (dependentVar < 0) { return; } @@ -95,7 +96,7 @@ void AnalysisCut::AddCut(int var, T1 cutLow, T2 cutHigh, bool exclude, cut.fFuncLow = nullptr; cut.fLow = cutLow; } - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v>) { if (dependentVar < 0) { return; } diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 5c0a0a67de9..a72dccc0888 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -9,8 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no -// +/// \author Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +/// \file CutsLibrary.cxxx +/// \brief Library with cuts to use + #include "PWGDQ/Core/CutsLibrary.h" #include "AnalysisCompositeCut.h" @@ -29,7 +31,7 @@ #include #include -#include +#include #include #include #include @@ -1182,7 +1184,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (int iCut = 0; iCut < 10; iCut++) { + for (int iCut = 0; iCut < 10; iCut++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("jpsiEleSel%d_ionut", iCut))) { cut->AddCut(GetAnalysisCut("kineJpsiEle_ionut")); cut->AddCut(GetAnalysisCut("dcaCut1_ionut")); @@ -1482,13 +1484,50 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (int i = 1; i <= 8; i++) { + for (int i = 1; i <= 8; i++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("dalitzSelected%d", i))) { cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); return cut; } } + if (!nameStr.compare("electronPrimaryTag0")) { + // with tight 3 sigma DCA cut for selecting primary electrons + cut->AddCut(GetAnalysisCut("electronPID_TPCnsigma_loose")); // 3 sigma inclusion, 3sigma rejection + cut->AddCut(GetAnalysisCut("electronPrimary_dca3sigma")); + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + return cut; + } + + if (!nameStr.compare("electronPrimaryTag1")) { + // with 7 sigma DCA cut for selecting primary electrons + cut->AddCut(GetAnalysisCut("electronPID_TPCnsigma_loose")); // 3 sigma inclusion, 3sigma rejection + cut->AddCut(GetAnalysisCut("electronPrimary_dca7sigma")); + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); + return cut; + } + + if (!nameStr.compare("electronPrimaryProbe_TPC")) { + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + return cut; + } + + if (!nameStr.compare("electronPrimaryProbe_ITS")) { + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCA")); + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + return cut; + } + + if (!nameStr.compare("electronPrimaryProbe_ITSTPC")) { + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCA")); + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + return cut; + } + if (!nameStr.compare("jpsiPIDworseRes")) { cut->AddCut(GetAnalysisCut("jpsiStandardKine")); cut->AddCut(GetAnalysisCut("electronStandardQuality")); @@ -1956,7 +1995,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (unsigned int i = 0; i < 30; i++) { + for (unsigned int i = 0; i < 30; i++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("ElSelCutVar%s%i", vecPIDcase.at(icase).Data(), i))) { cut->AddCut(GetAnalysisCut("lmeeStandardKine")); cut->AddCut(GetAnalysisCut(Form("lmeeCutVarTrackCuts%i", i))); @@ -2726,7 +2765,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (int i = 1; i <= 8; i++) { + for (int i = 1; i <= 8; i++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("lmee%s_pp502TeV_PID%s_UsePrefilter%d", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data(), i))) { cut->AddCut(GetAnalysisCut(Form("notDalitzLeg%d", i))); cut->AddCut(GetAnalysisCut("lmeeStandardKine")); @@ -2783,7 +2822,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (int i = 1; i <= 8; i++) { + for (int i = 1; i <= 8; i++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("lmee%s_eNSigmaRun3%s_UsePrefilter%d", vecTypetrackWithPID.at(jcase).Data(), vecPIDcase.at(icase).Data(), i))) { cut->AddCut(GetAnalysisCut(Form("notDalitzLeg%d", i))); cut->AddCut(GetAnalysisCut("lmeeStandardKine")); @@ -4232,14 +4271,14 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("eventStandardSel8PbPbMultCorr")) { - TF1* fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); + std::shared_ptr fMultPVCutLow = std::make_shared("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - TF1* fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); + std::shared_ptr fMultPVCutHigh = std::make_shared("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - TF1* fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + std::shared_ptr fMultCutLow = std::make_shared("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); - TF1* fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + std::shared_ptr fMultCutHigh = std::make_shared("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); cut->AddCut(VarManager::kVtxNcontribReal, fMultPVCutLow, fMultPVCutHigh, false, VarManager::kCentFT0C, 0.0, 100.0, false); cut->AddCut(VarManager::kMultA, fMultCutLow, fMultCutHigh, false, VarManager::kCentFT0C, 0.0, 100.0, false); @@ -4792,44 +4831,44 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) // loop to define PID cuts with and without post calibration for (size_t icase = 1; icase < vecTypetrack.size(); icase++) { if (!nameStr.compare(Form("lmeeQCTrackCuts%s", vecTypetrack.at(icase).Data()))) { - if (icase == 1) { + if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); cut->AddCut(VarManager::kITSncls, 6.5, 7.5); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); cut->AddCut(VarManager::kTPCncls, 90.0, 170.); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); cut->AddCut(VarManager::kITSncls, 4.5, 7.5); - } else if (icase == 3) { + } else if (icase == 3) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); cut->AddCut(VarManager::kITSncls, 4.5, 7.5); cut->AddCut(VarManager::kHasTPC, -0.5, 0.5); - } else if (icase == 4) { + } else if (icase == 4) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); cut->AddCut(VarManager::kTPCncls, 90.0, 170.); - } else if (icase == 5) { + } else if (icase == 5) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); cut->AddCut(VarManager::kTPCncls, 90.0, 170.); cut->AddCut(VarManager::kHasITS, -0.5, 0.5); - } else if (icase == 6) { + } else if (icase == 6) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); cut->AddCut(VarManager::kTPCncls, 90.0, 170.); cut->AddCut(VarManager::kHasTRD, -0.5, 0.5); - } else if (icase == 7) { + } else if (icase == 7) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); cut->AddCut(VarManager::kITSncls, 4.5, 7.5); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); cut->AddCut(VarManager::kTPCncls, 130.0, 170.); - } else if (icase == 8) { + } else if (icase == 8) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); @@ -5064,6 +5103,44 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("electronPrimary_dca3sigma") || !nameStr.compare("electronPrimary_dca7sigma")) { + std::shared_ptr fDCAxyresLow = std::make_shared("fDCAxyresLow", "[0] + [1] * pow(x, -[2])", 0.1, 1000.); + std::shared_ptr fDCAzresLow = std::make_shared("fDCAzresLow", "[0] + [1] * pow(x, -[2])", 0.1, 1000.); + std::shared_ptr fDCAxyresUp = std::make_shared("fDCAxyresUp", "[0] + [1] * pow(x, -[2])", 0.1, 1000.); + std::shared_ptr fDCAzresUp = std::make_shared("fDCAzresUp", "[0] + [1] * pow(x, -[2])", 0.1, 1000.); + + if (!nameStr.compare("electronPrimary_dca3sigma")) { + // DCAxy and DCAz 3 sigma cut. DCA resolution vs pt extracted from fits of Users/m/mfaggin/test/inputsTrackTuner/pp2024/pass1_minBias/vsPhi (used for the track tuner) + // we add in addition a term for the misalignment of the mean of the distribution, which seems to be at most 20 mum for DCAxy and 10 mum for DCAz + fDCAxyresLow->SetParameters(-3 * 8.7e-4 - 20e-4, -3 * 25.4e-4, 0.79); // res is 8.7 + 25.4/pt^0.79 mum + fDCAzresLow->SetParameters(-3 * 9.4e-4 - 10e-4, -3 * 26.5e-4, 0.79); // res is 9.4 + 26.5/pt^0.79 mum + fDCAxyresUp->SetParameters(3 * 8.7e-4 + 20e-4, 3 * 25.4e-4, 0.79); // res is 8.7 + 25.4/pt^0.79 mum + fDCAzresUp->SetParameters(3 * 9.4e-4 + 10e-4, 3 * 26.5e-4, 0.79); // res is 9.4 + 26.5/pt^0.79 mum + cut->AddCut(VarManager::kTrackDCAxy, fDCAxyresLow, fDCAxyresUp, false, VarManager::kPt, 0.2, 1000.); + cut->AddCut(VarManager::kTrackDCAz, fDCAzresLow, fDCAzresUp, false, VarManager::kPt, 0.2, 1000.); + cut->AddCut(VarManager::kIsITSibFirst, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 100, 161.); + return cut; + } + + if (!nameStr.compare("electronPrimary_dca7sigma")) { + // DCAxy and DCAz 7 sigma cut + fDCAxyresLow->SetParameters(-7 * 8.7e-4 - 20e-4, -7 * 25.4e-4, 0.79); + fDCAzresLow->SetParameters(-7 * 9.4e-4 - 10e-4, -7 * 26.5e-4, 0.79); + fDCAxyresUp->SetParameters(7 * 8.7e-4 + 20e-4, 7 * 25.4e-4, 0.79); + fDCAzresUp->SetParameters(7 * 9.4e-4 + 10e-4, 7 * 26.5e-4, 0.79); + cut->AddCut(VarManager::kTrackDCAxy, fDCAxyresLow, fDCAxyresUp, false, VarManager::kPt, 0.2, 1000.); + cut->AddCut(VarManager::kTrackDCAz, fDCAzresLow, fDCAzresUp, false, VarManager::kPt, 0.2, 1000.); + cut->AddCut(VarManager::kIsITSibFirst, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 100, 161.); + return cut; + } + } + if (!nameStr.compare("dcaCut1_ionut")) { cut->AddCut(VarManager::kTrackDCAxy, -0.5, 0.5); cut->AddCut(VarManager::kTrackDCAz, -0.5, 0.5); @@ -5239,7 +5316,7 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) // ----------------------------------------------------- // V0 and Dalitz legs selections - for (int i = 1; i <= 8; i++) { + for (int i = 1; i <= 8; i++) { // o2-linter: disable=magic-number (number of cuts) if (!nameStr.compare(Form("dalitzLeg%d", i))) { cut->AddCut(VarManager::kIsDalitzLeg + i - 1, 0.5, 1.5); return cut; @@ -5420,40 +5497,42 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - TF1* cutLow1 = new TF1("cutLow1", "pol1", 0., 10.); - if (!nameStr.compare("electronPID1")) { - cutLow1->SetParameters(130., -40.0); - cut->AddCut(VarManager::kTPCsignal, 70., 100.); - cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); - return cut; - } + if (!nameStr.compare("electronPID1") || !nameStr.compare("electronPID1shiftUp") || !nameStr.compare("electronPID1shiftDown") || !nameStr.compare("electronPID2") || !nameStr.compare("electronPID3")) { + std::shared_ptr cutLow1 = std::make_shared("cutLow1", "pol1", 0., 10.); + if (!nameStr.compare("electronPID1")) { + cutLow1->SetParameters(130., -40.0); + cut->AddCut(VarManager::kTPCsignal, 70., 100.); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + return cut; + } - if (!nameStr.compare("electronPID1shiftUp")) { - cut->AddCut(VarManager::kTPCsignal, 70. - 0.85, 100. - 0.85); - cutLow1->SetParameters(130. - 0.85, -40.0); - cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0 - 0.85, false, VarManager::kPin, 0.5, 3.0); - return cut; - } + if (!nameStr.compare("electronPID1shiftUp")) { + cut->AddCut(VarManager::kTPCsignal, 70. - 0.85, 100. - 0.85); + cutLow1->SetParameters(130. - 0.85, -40.0); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0 - 0.85, false, VarManager::kPin, 0.5, 3.0); + return cut; + } - if (!nameStr.compare("electronPID1shiftDown")) { - cut->AddCut(VarManager::kTPCsignal, 70.0 + 0.85, 100.0 + 0.85); - cutLow1->SetParameters(130. + 0.85, -40.0); - cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0 + 0.85, false, VarManager::kPin, 0.5, 3.0); - return cut; - } + if (!nameStr.compare("electronPID1shiftDown")) { + cut->AddCut(VarManager::kTPCsignal, 70.0 + 0.85, 100.0 + 0.85); + cutLow1->SetParameters(130. + 0.85, -40.0); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0 + 0.85, false, VarManager::kPin, 0.5, 3.0); + return cut; + } - if (!nameStr.compare("electronPID2")) { - cutLow1->SetParameters(130., -40.0); - cut->AddCut(VarManager::kTPCsignal, 73., 100.); - cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); - return cut; - } + if (!nameStr.compare("electronPID2")) { + cutLow1->SetParameters(130., -40.0); + cut->AddCut(VarManager::kTPCsignal, 73., 100.); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + return cut; + } - if (!nameStr.compare("electronPID3")) { - cutLow1->SetParameters(130., -40.0); - cut->AddCut(VarManager::kTPCsignal, 60., 110.); - cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); - return cut; + if (!nameStr.compare("electronPID3")) { + cutLow1->SetParameters(130., -40.0); + cut->AddCut(VarManager::kTPCsignal, 60., 110.); + cut->AddCut(VarManager::kTPCsignal, cutLow1, 100.0, false, VarManager::kPin, 0.5, 3.0); + return cut; + } } if (!nameStr.compare("electronPIDnsigma")) { @@ -5486,26 +5565,26 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) // loop to define TPC PID cuts with and without post calibration for (size_t icase = 0; icase < vecPIDcase.size(); icase++) { if (!nameStr.compare(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3.0, 3.0); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3.0, 3.0); } return cut; } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_loose", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5515,17 +5594,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { // previously known as electronPID_TPCnsigma_tight + if (icase == 0) { // previously known as electronPID_TPCnsigma_tight // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5535,17 +5614,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5555,17 +5634,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5575,19 +5654,19 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5598,19 +5677,19 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_lowB_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5623,17 +5702,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5645,17 +5724,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5667,17 +5746,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPCnsigma%s_tightNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5700,17 +5779,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) for (unsigned int i = 0; i < cutVar_TPCnSigmaEl_low.size(); i++) { if (!nameStr.compare(Form("electronPID_TPCnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, cutVar_TPCnSigmaPr_low.at(i), cutVar_TPCnSigmaPr_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, cutVar_TPCnSigmaPr_low.at(i), cutVar_TPCnSigmaPr_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, cutVar_TPCnSigmaKa_low.at(i), cutVar_TPCnSigmaKa_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); @@ -5721,17 +5800,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TPC%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5741,19 +5820,19 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_lowB_TPC%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5775,10 +5854,10 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TPCPbPbnopkrej%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); } @@ -5786,17 +5865,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TPCloose%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1) { + } else if (icase == 1) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 2) { + } else if (icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); @@ -5974,50 +6053,50 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("tpc_pion_rejection")) { - TF1* f1maxPi = new TF1("f1maxPi", "[0]+[1]*x", 0, 10); + std::shared_ptr f1maxPi = std::make_shared("f1maxPi", "[0]+[1]*x", 0, 10); f1maxPi->SetParameters(85, -50); cut->AddCut(VarManager::kTPCsignal, 70, f1maxPi, true, VarManager::kPin, 0.0, 0.4, false); return cut; } if (!nameStr.compare("tpc_pion_band_rejection")) { - TF1* f1minPi = new TF1("f1minPi", "[0]+[1]*log(x)", 0, 10); + std::shared_ptr f1minPi = std::make_shared("f1minPi", "[0]+[1]*log(x)", 0, 10); f1minPi->SetParameters(-115, -90); - TF1* f1maxPi = new TF1("f1maxPi", "[0]+[1]*log(x)", 0, 10); + std::shared_ptr f1maxPi = std::make_shared("f1maxPi", "[0]+[1]*log(x)", 0, 10); f1maxPi->SetParameters(-70, -90); cut->AddCut(VarManager::kTPCsignal, f1minPi, f1maxPi, true, VarManager::kPin, 0.05, 0.3, false); return cut; } if (!nameStr.compare("tpc_pion_muon_band_rejection")) { - TF1* f1minPi = new TF1("f1minPi", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1minPi = std::make_shared("f1minPi", "[0]+exp([1]*x+[2])", 0, 10); f1minPi->SetParameters(37, -18, 5.5); - TF1* f1maxPi = new TF1("f1maxPi", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1maxPi = std::make_shared("f1maxPi", "[0]+exp([1]*x+[2])", 0, 10); f1maxPi->SetParameters(67, -17, 5.9); cut->AddCut(VarManager::kTPCsignal, f1minPi, f1maxPi, true, VarManager::kPin, 0.0, 10, false); return cut; } if (!nameStr.compare("tpc_pion_rejection_highp")) { - TF1* f1minPi = new TF1("f1minPi", "[0]+[1]*x", 0, 10); + std::shared_ptr f1minPi = std::make_shared("f1minPi", "[0]+[1]*x", 0, 10); f1minPi->SetParameters(65, 4.); cut->AddCut(VarManager::kTPCsignal, f1minPi, 110., false, VarManager::kPin, 0.0, 10, false); return cut; } if (!nameStr.compare("tpc_kaon_rejection")) { - TF1* f1minKa = new TF1("f1minKa", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1minKa = std::make_shared("f1minKa", "[0]+exp([1]*x+[2])", 0, 10); f1minKa->SetParameters(37, -4, 5.6); - TF1* f1maxKa = new TF1("f1maxKa", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1maxKa = std::make_shared("f1maxKa", "[0]+exp([1]*x+[2])", 0, 10); f1maxKa->SetParameters(60, -4.1, 6.); cut->AddCut(VarManager::kTPCsignal, f1minKa, f1maxKa, true, VarManager::kPin, 0.0, 10.0, false); return cut; } if (!nameStr.compare("tpc_proton_rejection")) { - TF1* f1minPr = new TF1("f1minPr", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1minPr = std::make_shared("f1minPr", "[0]+exp([1]*x+[2])", 0, 10); f1minPr->SetParameters(37, -2.6, 6.1); - TF1* f1maxPr = new TF1("f1maxPr", "[0]+exp([1]*x+[2])", 0, 10); + std::shared_ptr f1maxPr = std::make_shared("f1maxPr", "[0]+exp([1]*x+[2])", 0, 10); f1maxPr->SetParameters(60, -2.4, 6.2); cut->AddCut(VarManager::kTPCsignal, f1minPr, f1maxPr, true, VarManager::kPin, 0.0, 10, false); return cut; @@ -6051,11 +6130,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) // loop to define TOF PID cuts with and without post calibration for (size_t icase = 0; icase < vecPIDcase.size(); icase++) { if (!nameStr.compare(Form("electronPID_TOFnsigma%s_loose", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6064,11 +6143,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { // previously known as electronPID_TOFnsigma_tight + if (icase == 0) { // previously known as electronPID_TOFnsigma_tight // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6077,11 +6156,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6090,11 +6169,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6112,11 +6191,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) for (unsigned int i = 0; i < cutVar_TOFnSigmaEl_low.size(); i++) { if (!nameStr.compare(Form("electronPID_TOFnsigma_cutVar%s%i", vecPIDcase.at(icase).Data(), i))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, cutVar_TOFnSigmaEl_low.at(i), cutVar_TOFnSigmaEl_up.at(i), false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, cutVar_TPCnSigmaEl_low.at(i), cutVar_TPCnSigmaEl_up.at(i), false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, cutVar_TPCnSigmaPi_low.at(i), cutVar_TPCnSigmaPi_up.at(i), true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, cutVar_TOFnSigmaEl_low.at(i), cutVar_TOFnSigmaEl_up.at(i), false, VarManager::kPin, 0.3, 1e+10, false); @@ -6126,13 +6205,13 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TPC_TOFnsigma%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { // previously known as electronPID_TOFnsigma_tight + if (icase == 0) { // previously known as electronPID_TOFnsigma_tight // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); @@ -6143,12 +6222,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.3, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.25, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.3, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.25, 1e+10, false); @@ -6158,12 +6237,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_lowB_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.3, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.25, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.3, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.25, 1e+10, false); @@ -6175,11 +6254,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6190,11 +6269,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6205,11 +6284,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFnsigma%s_tightNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 1., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 1., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6220,11 +6299,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFreq%s_strongNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -1., 2., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); @@ -6233,11 +6312,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("electronPID_TOFreq%s_tightNSigEPbPb_rejBadTOF", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 1., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, 0., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 1., false, VarManager::kPin, 0.0, 1e+10, false); @@ -6246,11 +6325,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TOF%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); @@ -6259,12 +6338,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_lowB_TOF%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); @@ -6274,12 +6353,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TOFloose%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3., true, VarManager::kPin, 0.0, 4.0, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 4.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -4., 4., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3., true, VarManager::kPin, 0.0, 4.0, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 4.0, 1e+10, false); @@ -6289,12 +6368,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare(Form("lmee_pp_502TeV_TOFloose_pionrej%s", vecPIDcase.at(icase).Data()))) { - if (icase == 0) { + if (icase == 0) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3.5, true, VarManager::kPin, 0.0, 2.0, false); cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 2.0, 1e+10, false); cut->AddCut(VarManager::kTOFnSigmaEl, -4., 4., false, VarManager::kPin, 0.3, 1e+10, false); - } else if (icase == 1 || icase == 2) { + } else if (icase == 1 || icase == 2) { // o2-linter: disable=magic-number (number of cuts) cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 2.0, false); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 2.0, 1e+10, false); @@ -6515,9 +6594,9 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) if (!nameStr.compare("pairDalitz1")) { cut->AddCut(VarManager::kMass, 0.0, 0.015, false, VarManager::kPt, 0., 1.); cut->AddCut(VarManager::kMass, 0.0, 0.035, false, VarManager::kPt, 0., 1., true); - TF1* fcutHigh = new TF1("f1", "[0] - [0]/[1]*x", -1.5, 1.5); + std::shared_ptr fcutHigh = std::make_shared("f1", "[0] - [0]/[1]*x", -1.5, 1.5); fcutHigh->SetParameters(0.6, 0.12); - TF1* fcutLow = new TF1("f2", "-[0] + [0]/[1]*x", -1.5, 1.5); + std::shared_ptr fcutLow = std::make_shared("f2", "-[0] + [0]/[1]*x", -1.5, 1.5); fcutLow->SetParameters(0.6, 0.12); cut->AddCut(VarManager::kPsiPair, fcutLow, fcutHigh, true, VarManager::kDeltaPhiPair, 0, 0.12); return cut; @@ -6926,7 +7005,7 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("pairLxyProjected3sigmaLambdacCand")) { - TF1* f1minLxyProjected = new TF1("f1minLxyProjected", "[0]+[1]*x", 0., 20.); + std::shared_ptr f1minLxyProjected = std::make_shared("f1minLxyProjected", "[0]+[1]*x", 0., 20.); f1minLxyProjected->SetParameters(0.0065, -0.00023); cut->AddCut(VarManager::kVertexingLxyProjected, f1minLxyProjected, 1., false, VarManager::kPt, 0., 20.); return cut; @@ -7425,8 +7504,8 @@ AnalysisCut* o2::aod::dqcuts::ParseJSONAnalysisCut(T cut, const char* cutName) bool depCut2Exclude = (addcut.HasMember("depCut2Exclude") ? addcut.FindMember("depCut2Exclude")->value.GetBool() : false); LOG(info) << "depCut2Exclude " << depCut2Exclude; - TF1* cutLowFunc = nullptr; - TF1* cutHighFunc = nullptr; + std::shared_ptr cutLowFunc = nullptr; + std::shared_ptr cutHighFunc = nullptr; double cutLowNumber = 0.0; double cutHighNumber = 0.0; if (cutLow_isNumber) { @@ -7434,8 +7513,8 @@ AnalysisCut* o2::aod::dqcuts::ParseJSONAnalysisCut(T cut, const char* cutName) LOG(info) << "cutLowNumber " << cutLowNumber; } else { auto& cutLow = addcut.FindMember("cutLow")->value; - cutLowFunc = new TF1(cutLow.FindMember("funcName")->value.GetString(), cutLow.FindMember("funcBody")->value.GetString(), - cutLow.FindMember("xLow")->value.GetDouble(), cutLow.FindMember("xHigh")->value.GetDouble()); + cutLowFunc = std::make_shared(cutLow.FindMember("funcName")->value.GetString(), cutLow.FindMember("funcBody")->value.GetString(), + cutLow.FindMember("xLow")->value.GetDouble(), cutLow.FindMember("xHigh")->value.GetDouble()); LOG(info) << "cutLowFunc " << cutLow.FindMember("funcName")->value.GetString() << ", " << cutLow.FindMember("funcBody")->value.GetString() << ", " << cutLow.FindMember("xLow")->value.GetDouble() << ", " << cutLow.FindMember("xHigh")->value.GetDouble(); } @@ -7444,8 +7523,8 @@ AnalysisCut* o2::aod::dqcuts::ParseJSONAnalysisCut(T cut, const char* cutName) LOG(info) << "cutHighNumber " << cutHighNumber; } else { auto& cutHigh = addcut.FindMember("cutHigh")->value; - cutHighFunc = new TF1(cutHigh.FindMember("funcName")->value.GetString(), cutHigh.FindMember("funcBody")->value.GetString(), - cutHigh.FindMember("xLow")->value.GetDouble(), cutHigh.FindMember("xHigh")->value.GetDouble()); + cutHighFunc = std::make_shared(cutHigh.FindMember("funcName")->value.GetString(), cutHigh.FindMember("funcBody")->value.GetString(), + cutHigh.FindMember("xLow")->value.GetDouble(), cutHigh.FindMember("xHigh")->value.GetDouble()); LOG(info) << "cutHighFunc " << cutHigh.FindMember("funcName")->value.GetString() << ", " << cutHigh.FindMember("funcBody")->value.GetString() << ", " << cutHigh.FindMember("xLow")->value.GetDouble() << ", " << cutHigh.FindMember("xHigh")->value.GetDouble(); } @@ -7705,12 +7784,15 @@ o2::aod::dqmlcuts::BdtScoreConfig o2::aod::dqmlcuts::GetBdtScoreCutsAndConfigFro cutsMl.push_back(binCuts); labelsFlatBin.push_back(Form("%s_cent%.0f_%.0f_pt%.1f_%.1f", cent.c_str(), centMin, centMax, ptMin, ptMax)); LOG(info) << "Added cut for " << Form("%s_cent%.0f_%.0f_pt%.1f_%.1f", cent.c_str(), centMin, centMax, ptMin, ptMax) << " with cuts: ["; + std::string msg = ""; for (size_t i = 0; i < binCuts.size(); ++i) { - std::cout << binCuts[i]; + msg += std::to_string(binCuts[i]); if (i != binCuts.size() - 1) - std::cout << ", "; + msg += ", "; } - std::cout << "] and direction: " << (exclude ? "CutGreater" : "CutSmaller") << std::endl; + msg += "] and direction: "; + msg += (exclude ? "CutGreater" : "CutSmaller"); + LOG(info) << msg; } } diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index c3768b02918..da755a538ef 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -9,9 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Task to select electrons from dalitz decay -// It can produce track and pair histograms for selected tracks -// It creates a bitmap with selections to be stored during skimming +// +/// \file DalitzSelection.cxx +/// \author Gauthier Legras, glegras@uni-muenster.de, gauthier.legras@cern.ch +/// \brief Task to select electrons from dalitz decay +/// It can produce track and pair histograms for selected tracks +/// It creates a bitmap with selections to be stored during skimming // #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" @@ -65,86 +68,147 @@ using MyBarrelTracks = soa::Join; -constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::Collision; -constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID; +constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision; +constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID; -struct dalitzPairing { +struct DalitzSelection { Produces dalitzbits; Preslice perCollision = aod::track::collisionId; // Configurables - Configurable fConfigEventCuts{"cfgEventCuts", "eventStandardNoINT7", "Event selection"}; - Configurable fConfigDalitzTrackCuts{"cfgDalitzTrackCuts", "", "Dalitz track selection cuts, separated by a comma"}; - Configurable fConfigDalitzPairCuts{"cfgDalitzPairCuts", "", "Dalitz pair selection cuts"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; - Configurable fQA{"cfgQA", true, "QA histograms"}; - Configurable fConfigBarrelTrackPINLow{"cfgBarrelLowPIN", 0.1f, "Low pt cut for Dalitz tracks in the barrel"}; - Configurable fConfigEtaCut{"cfgEtaCut", 0.9f, "Eta cut for Dalitz tracks in the barrel"}; - Configurable fConfigTPCNSigLow{"cfgTPCNSigElLow", -3.f, "Low TPCNSigEl cut for Dalitz tracks in the barrel"}; - Configurable fConfigTPCNSigHigh{"cfgTPCNSigElHigh", 3.f, "High TPCNsigEl cut for Dalitz tracks in the barrel"}; - // Configurables for TPC post-calibration maps - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; - Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; - Configurable fUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; - Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + // cuts + struct : ConfigurableGroup { + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandardNoINT7", "Event selection"}; + Configurable fConfigDalitzTrackCuts{"cfgDalitzTrackCuts", "", "Dalitz track selection cuts for tag, separated by a comma"}; + Configurable fConfigDalitzTrackCutsProbe{"cfgDalitzTrackCutsProbe", "", "Dalitz track selection cuts for probe, separated by a comma (if empty, use same selections as the tag)"}; + Configurable fConfigDalitzPairCuts{"cfgDalitzPairCuts", "", "Dalitz pair selection cuts"}; + Configurable fConfigTrackCutsJSON{"cfgTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; + Configurable fConfigTrackCutsProbeJSON{"cfgTrackCutsProbeJSON", "", "Additional list of barrel track cuts for the probe in JSON format"}; + Configurable fConfigPairCutsJSON{"cfgPairCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; + Configurable fConfigBarrelTrackPINLow{"cfgBarrelLowPIN", 0.1f, "Low pt cut for Dalitz tracks in the barrel"}; + Configurable fConfigEtaCut{"cfgEtaCut", 0.9f, "Eta cut for Dalitz tracks in the barrel"}; + Configurable fConfigTPCNSigLow{"cfgTPCNSigElLow", -3.f, "Low TPCNSigEl cut for Dalitz tracks in the barrel"}; + Configurable fConfigTPCNSigHigh{"cfgTPCNSigElHigh", 3.f, "High TPCNsigEl cut for Dalitz tracks in the barrel"}; + } fConfigCuts; + + // histograms + struct : ConfigurableGroup { + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddPairHistogram{"cfgAddPairHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format for tracks"}; + } fConfigHistograms; + + // additional options + struct : ConfigurableGroup { + Configurable fConfigEnableLikeSign{"cfgEnableLikeSign", false, "Whether or not also add like-sign pairs (for studying combinatorial background which might contain misID or non-primary electrons)"}; + Configurable fQA{"cfgQA", true, "QA histograms"}; + // Configurables for TPC post-calibration maps + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; + Configurable fUseRemoteField{"cfgUseRemoteField", true, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; + Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + } fConfigOptions; Service fCCDB; o2::parameters::GRPMagField* grpmag = nullptr; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - Filter filterBarrelTrack = o2::aod::track::tpcInnerParam >= fConfigBarrelTrackPINLow && nabs(o2::aod::track::eta) <= fConfigEtaCut && o2::aod::pidtpc::tpcNSigmaEl <= fConfigTPCNSigHigh && o2::aod::pidtpc::tpcNSigmaEl >= fConfigTPCNSigLow; + Filter filterBarrelTrack = o2::aod::track::tpcInnerParam >= fConfigCuts.fConfigBarrelTrackPINLow && nabs(o2::aod::track::eta) <= fConfigCuts.fConfigEtaCut && o2::aod::pidtpc::tpcNSigmaEl <= fConfigCuts.fConfigTPCNSigHigh && o2::aod::pidtpc::tpcNSigmaEl >= fConfigCuts.fConfigTPCNSigLow; OutputObj fOutputList{"output"}; //! the histogram manager output list OutputObj fStatsList{"Statistics"}; //! skimming statistics - std::map fTrackmap; - std::map fDalitzmap; + std::map fTrackmap; // whether it is selected with symmetric or tag cut + std::map fTrackmapProbe; // whether it is selected with probe cut + std::map fDalitzmap; // whether it is selected as dalitz decay daughter with symmetric or tag cut + std::map fDalitzmapProbe; // whether it is selected as dalitz decay daughter with probe cut AnalysisCompositeCut* fEventCut; std::vector fTrackCuts; + std::vector fTrackCutsProbe; std::vector fPairCuts; + bool fIsTagAndProbe; // whether we are doing tag and probe, or just symmetric cuts + HistogramManager* fHistMan; void init(o2::framework::InitContext&) { + fIsTagAndProbe = false; + // Event cuts fEventCut = new AnalysisCompositeCut(true); - TString eventCutStr = fConfigEventCuts.value; + TString eventCutStr = fConfigCuts.fConfigEventCuts.value; fEventCut->AddCut(dqcuts::GetAnalysisCut(eventCutStr.Data())); // Barrel track cuts - TString cutNamesStr = fConfigDalitzTrackCuts.value; + // Tag cuts or symmetric cuts + TString cutNamesStr = fConfigCuts.fConfigDalitzTrackCuts.value; if (!cutNamesStr.IsNull()) { std::unique_ptr objArray(cutNamesStr.Tokenize(",")); for (int icut = 0; icut < objArray->GetEntries(); ++icut) { fTrackCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); } } + // extra cuts via JSON + TString addTrackCutsStr = fConfigCuts.fConfigTrackCutsJSON.value; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + } + } + + // Probe cuts + TString cutNamesProbeStr = fConfigCuts.fConfigDalitzTrackCutsProbe.value; + TString addTrackCutsProbeStr = fConfigCuts.fConfigTrackCutsProbeJSON.value; + if (!cutNamesProbeStr.IsNull() && (cutNamesProbeStr.CompareTo(cutNamesStr) != 0 || addTrackCutsProbeStr.CompareTo(addTrackCutsStr) != 0)) { + std::unique_ptr objArray(cutNamesProbeStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fTrackCutsProbe.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + fIsTagAndProbe = true; + } + // extra cuts via JSON + if (addTrackCutsProbeStr != "" && (cutNamesProbeStr.CompareTo(cutNamesStr) != 0 || addTrackCutsProbeStr.CompareTo(addTrackCutsStr) != 0)) { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsProbeStr.Data()); + for (const auto& t : addTrackCuts) { + fTrackCutsProbe.push_back(reinterpret_cast(t)); + } + fIsTagAndProbe = true; + } // Pair cuts - TString cutNamesPairStr = fConfigDalitzPairCuts.value; + TString cutNamesPairStr = fConfigCuts.fConfigDalitzPairCuts.value; if (!cutNamesPairStr.IsNull()) { std::unique_ptr objArray(cutNamesPairStr.Tokenize(",")); for (int icut = 0; icut < objArray->GetEntries(); ++icut) { fPairCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); } } + // extra cuts via JSON + TString addPairCutsStr = fConfigCuts.fConfigPairCutsJSON.value; + if (addPairCutsStr != "") { + std::vector addPairCuts = dqcuts::GetCutsFromJSON(addPairCutsStr.Data()); + for (const auto& t : addPairCuts) { + fPairCuts.push_back(reinterpret_cast(t)); + } + } - if (fTrackCuts.size() != fPairCuts.size()) { + if (fTrackCuts.size() != fPairCuts.size() || (fTrackCuts.size() != fTrackCutsProbe.size() && fIsTagAndProbe)) { LOGF(fatal, "YOU SHOULD PROVIDE THE SAME NUMBER OF TRACK AND PAIR CUTS"); } // CCDB configuration - if (fConfigComputeTPCpostCalib) { - fCCDB->setURL(fConfigCcdbUrl.value); + if (fConfigOptions.fConfigComputeTPCpostCalib) { + fCCDB->setURL(fConfigOptions.fConfigCcdbUrl.value); fCCDB->setCaching(true); fCCDB->setLocalObjectValidityChecking(); // Not later than now objects - fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + fCCDB->setCreatedNotAfter(fConfigOptions.fConfigNoLaterThan.value); } VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill @@ -156,11 +220,24 @@ struct dalitzPairing { // Create the histogram class names to be added to the histogram manager TString histClasses = ""; - if (fQA) { + if (fConfigOptions.fQA) { auto trackCut = fTrackCuts.begin(); - for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++) { - histClasses += Form("TrackBarrel_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); - histClasses += Form("Pair_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); + int iCut = 0; + for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, iCut++) { + if (fIsTagAndProbe) { + histClasses += Form("TrackBarrelTag_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); + histClasses += Form("TrackBarrelProbe_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); + histClasses += Form("Pair_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); + if (fConfigOptions.fConfigEnableLikeSign) { + histClasses += Form("Pair_LS_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); + } + } else { + histClasses += Form("TrackBarrel_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); + histClasses += Form("Pair_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); + if (fConfigOptions.fConfigEnableLikeSign) { + histClasses += Form("Pair_LS_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); + } + } } } @@ -174,28 +251,42 @@ struct dalitzPairing { if (classStr.Contains("Event")) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "event", ""); } - TString histTrackName = fConfigAddTrackHistogram.value; + + TString histTrackName = fConfigHistograms.fConfigAddTrackHistogram.value; if (classStr.Contains("Track")) { dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "track", histTrackName); + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "software-trigger", histTrackName); } + TString histPairName = fConfigHistograms.fConfigAddPairHistogram.value; if (classStr.Contains("Pair")) { - dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "pair", "barreldalitz"); + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "pair", histPairName); } } + // Additional histogram via the JSON configurable + TString addHistsStr = fConfigHistograms.fConfigAddJSONHistograms.value; + if (addHistsStr != "") { + dqhistograms::AddHistogramsFromJSON(fHistMan, addHistsStr.Data()); + } + fStatsList.setObject(new TList()); fStatsList->SetOwner(kTRUE); // Dalitz selection statistics: one bin for each (track,pair) selection - TH1I* histTracks = new TH1I("TrackStats", "Dalitz selection statistics", fPairCuts.size() + 1, -0.5, fPairCuts.size() + 0.5); + TH1I* histTracks = new TH1I("TrackStats", "Dalitz selection statistics", fPairCuts.size() * (1 + fIsTagAndProbe) + 1, -0.5, fPairCuts.size() * (1 + fIsTagAndProbe) + 0.5); histTracks->GetXaxis()->SetBinLabel(1, "Events selected"); auto trackCut = fTrackCuts.begin(); int icut = 1; for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, icut++) { - histTracks->GetXaxis()->SetBinLabel(icut + 1, Form("%s_%s", (*trackCut).GetName(), (*pairCut).GetName())); + if (fIsTagAndProbe) { + histTracks->GetXaxis()->SetBinLabel(2 * icut, Form("%s_%s_%s tag", (*trackCut).GetName(), fTrackCutsProbe.at(icut - 1).GetName(), (*pairCut).GetName())); + histTracks->GetXaxis()->SetBinLabel(2 * icut + 1, Form("%s_%s_%s probe", (*trackCut).GetName(), fTrackCutsProbe.at(icut - 1).GetName(), (*pairCut).GetName())); + } else { + histTracks->GetXaxis()->SetBinLabel(icut + 1, Form("%s_%s", (*trackCut).GetName(), (*pairCut).GetName())); + } } - if (fQA) { + if (fConfigOptions.fQA) { fStatsList->Add(histTracks); } @@ -206,8 +297,9 @@ struct dalitzPairing { template void runTrackSelection(TTracks const& tracksBarrel) { - for (auto& track : tracksBarrel) { + for (const auto& track : tracksBarrel) { uint8_t filterMap = uint8_t(0); + uint8_t filterMapProbe = uint8_t(0); VarManager::FillTrack(track); int i = 0; for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { @@ -215,23 +307,41 @@ struct dalitzPairing { filterMap |= (uint8_t(1) << i); } } + if (fIsTagAndProbe) { + i = 0; + for (auto cut = fTrackCutsProbe.begin(); cut != fTrackCutsProbe.end(); ++cut, ++i) { + if ((*cut).IsSelected(VarManager::fgValues)) { + filterMapProbe |= (uint8_t(1) << i); + } + } + } if (filterMap) { fTrackmap[track.globalIndex()] = filterMap; } + if (filterMapProbe) { + fTrackmapProbe[track.globalIndex()] = filterMapProbe; + } } // end loop over tracks } template void runDalitzPairing(TTracks const& tracks1, TTracks const& tracks2) { - for (auto& [track1, track2] : o2::soa::combinations(CombinationsStrictlyUpperIndexPolicy(tracks1, tracks2))) { - if (track1.sign() * track2.sign() > 0) { + for (const auto& [track1, track2] : o2::soa::combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (track1.globalIndex() == track2.globalIndex()) { + continue; + } + if (!fIsTagAndProbe && track1.globalIndex() >= track2.globalIndex()) { + continue; + } + if (!fConfigOptions.fConfigEnableLikeSign && track1.sign() * track2.sign() > 0) { continue; } - uint8_t twoTracksFilterMap = fTrackmap[track1.globalIndex()] & fTrackmap[track2.globalIndex()]; - if (!twoTracksFilterMap) + uint8_t twoTracksFilterMap = fTrackmap[track1.globalIndex()] & (fIsTagAndProbe ? fTrackmapProbe[track2.globalIndex()] : fTrackmap[track2.globalIndex()]); + if (!twoTracksFilterMap) { continue; + } // pairing VarManager::FillPair(track1, track2); @@ -244,20 +354,34 @@ struct dalitzPairing { continue; } if ((*pairCut).IsSelected(VarManager::fgValues)) { - fDalitzmap[track1.globalIndex()] |= (uint8_t(1) << icut); - fDalitzmap[track2.globalIndex()] |= (uint8_t(1) << icut); - if (fQA) { - fHistMan->FillHistClass(Form("Pair_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); - } - } - } + if (track1.sign() * track2.sign() < 0) { + fDalitzmap[track1.globalIndex()] |= (uint8_t(1) << icut); + if (fIsTagAndProbe) { + fDalitzmapProbe[track2.globalIndex()] |= (uint8_t(1) << icut); + if (fConfigOptions.fQA) { + fHistMan->FillHistClass(Form("Pair_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } + } else { + fDalitzmap[track2.globalIndex()] |= (uint8_t(1) << icut); + if (fConfigOptions.fQA) { + fHistMan->FillHistClass(Form("Pair_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } + } + } else { + if (fConfigOptions.fQA) { + fHistMan->FillHistClass(fIsTagAndProbe ? Form("PairLS_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()) : Form("PairLS_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } + } // end if like-sign + } // end if isSelected + } // end cut loop } // end of tracksP,N loop // Fill Hists - if (fQA) { - for (auto& track : tracks1) { + if (fConfigOptions.fQA) { + for (const auto& track : tracks1) { uint8_t filterMap = fDalitzmap[track.globalIndex()]; - if (!filterMap) { + uint8_t filterMapProbe = fDalitzmapProbe[track.globalIndex()]; + if (!filterMap && !filterMapProbe) { continue; } VarManager::FillTrack(track); @@ -266,8 +390,12 @@ struct dalitzPairing { auto trackCut = fTrackCuts.begin(); for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, icut++) { if (filterMap & (uint8_t(1) << icut)) { - reinterpret_cast(fStatsList->At(0))->Fill(icut + 1); - fHistMan->FillHistClass(Form("TrackBarrel_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + reinterpret_cast(fStatsList->At(0))->Fill(fIsTagAndProbe ? 2 * icut + 1 : icut + 1); + fHistMan->FillHistClass(fIsTagAndProbe ? Form("TrackBarrelTag_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()) : Form("TrackBarrel_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } + if (filterMapProbe & (uint8_t(1) << icut)) { + reinterpret_cast(fStatsList->At(0))->Fill(2 * icut + 2); + fHistMan->FillHistClass(Form("TrackBarrelProbe_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } } } @@ -278,11 +406,13 @@ struct dalitzPairing { { const int pairType = VarManager::kDecayToEE; fDalitzmap.clear(); + fDalitzmapProbe.clear(); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { fTrackmap.clear(); + fTrackmapProbe.clear(); VarManager::ResetValues(VarManager::kNRunWiseVariables, VarManager::kNBarrelTrackVariables); - VarManager::FillEvent(collision); + VarManager::FillEvent(collision); bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); if (isEventSelected) { @@ -296,15 +426,15 @@ struct dalitzPairing { // We setup the magnetic field, because the conversion rejection cut might depend on it float magField = 0.; - if (fUseRemoteField.value) { - grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); + if (fConfigOptions.fUseRemoteField.value) { + grpmag = fCCDB->getForTimeStamp(fConfigOptions.grpmagPath, bc.timestamp()); if (grpmag != nullptr) { magField = grpmag->getNominalL3Field(); } else { LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bc.timestamp()); } } else { - magField = fConfigMagField.value; + magField = fConfigOptions.fConfigMagField.value; } LOGF(info, "setting mag field to %f", magField); if (magField == 0.) { @@ -312,8 +442,8 @@ struct dalitzPairing { } VarManager::SetMagneticField(magField); - if (fConfigComputeTPCpostCalib) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); + if (fConfigOptions.fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigOptions.fConfigCcdbPathTPC.value, bc.timestamp()); VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); @@ -325,26 +455,26 @@ struct dalitzPairing { } auto groupedFilteredTracks = filteredTracks.sliceBy(perCollision, collision.globalIndex()); - runTrackSelection(groupedFilteredTracks); - runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks); + runTrackSelection(groupedFilteredTracks); + runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks); } } - for (auto& track : tracks) { // Fill dalitz bits + for (const auto& track : tracks) { // Fill dalitz bits dalitzbits(fDalitzmap[track.globalIndex()]); } } - void processDummy(MyEvents&) + void processDummy(MyEvents const&) { } - PROCESS_SWITCH(dalitzPairing, processFullTracks, "Run Dalitz selection on AO2D tables", false); - PROCESS_SWITCH(dalitzPairing, processDummy, "Do nothing", false); + PROCESS_SWITCH(DalitzSelection, processFullTracks, "Run Dalitz selection on AO2D tables", false); + PROCESS_SWITCH(DalitzSelection, processDummy, "Do nothing", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } From 5b20de586a4242f7b310f961cb302d019d816db8 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Mon, 4 May 2026 13:26:44 +0200 Subject: [PATCH 021/449] [PWGDQ] add acceptance cut for pbpb (#16077) --- PWGDQ/Core/CutsLibrary.cxx | 9 +++++++++ PWGDQ/Core/VarManager.cxx | 1 + PWGDQ/Core/VarManager.h | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index a72dccc0888..bcd357e3e6d 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -4661,6 +4661,15 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("acceptance_PbPb5360")) { + cut->AddCut(VarManager::kMCY, -0.9, 0.9); + cut->AddCut(VarManager::kMCP1, 1.0, 1000.0); + cut->AddCut(VarManager::kMCP2, 1.0, 1000.0); + cut->AddCut(VarManager::kMCEta1, -0.9, 0.9); + cut->AddCut(VarManager::kMCEta2, -0.9, 0.9); + return cut; + } + // --------------------------------------------------- // MC generated particle acceptance cuts diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index b236b849b1a..fa081babced 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -1953,6 +1953,7 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kMCEventWeight"] = kMCEventWeight; fgVarNamesMap["kMCEventImpParam"] = kMCEventImpParam; fgVarNamesMap["kMCEventPlaneAngle"] = kMCEventPlaneAngle; + fgVarNamesMap["kMCEventCentrFT0C"] = kMCEventCentrFT0C; fgVarNamesMap["kQ1ZNAX"] = kQ1ZNAX; fgVarNamesMap["kQ1ZNAY"] = kQ1ZNAY; fgVarNamesMap["kQ1ZNCX"] = kQ1ZNCX; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 6d45eb620cf..37e0523cd91 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -715,8 +715,10 @@ class VarManager : public TObject // MC pair variables kMCPt1, kMCEta1, + kMCP1, kMCPt2, kMCEta2, + kMCP2, kMCCosThetaHE, kMCPhiHE, kMCPhiTildeHE, @@ -4201,6 +4203,8 @@ void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values) values[kMCPt2] = t2.pt(); values[kMCEta1] = t1.eta(); values[kMCEta2] = t2.eta(); + values[kMCP1] = t1.p(); + values[kMCP2] = t2.p(); // polarization parameters bool useHE = fgUsedVars[kMCCosThetaHE] || fgUsedVars[kMCPhiHE]; // helicity frame From e3f2eca6f1277fad35ffbb4b28c9ae8f7e3540b4 Mon Sep 17 00:00:00 2001 From: gengjiabin12 <997406694@qq.com> Date: Mon, 4 May 2026 19:28:04 +0800 Subject: [PATCH 022/449] [PWGLF] fix bugs (#16079) --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 3014156399b..0ac5e6f72e9 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -977,14 +977,14 @@ struct HStrangeCorrelation { } if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { if (mixingInBf) { - currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiencyTrigg, efficiencyError, Index); + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiency, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { if (mixingInBf) { - currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiencyTrigg, efficiencyError, Index); + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiency, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } From 4cbad3c289abb4bbe2fc800446399e38f0a405b9 Mon Sep 17 00:00:00 2001 From: hfribert Date: Mon, 4 May 2026 13:59:18 +0200 Subject: [PATCH 023/449] [PWGLF] Ancestor info for sigmas and mult. option for mixing (#16075) Co-authored-by: Henrik Fribert --- PWGLF/DataModel/LFSigmaHadTables.h | 20 +- .../Strangeness/sigmaHadCorr.cxx | 377 ++++++++++++------ 2 files changed, 273 insertions(+), 124 deletions(-) diff --git a/PWGLF/DataModel/LFSigmaHadTables.h b/PWGLF/DataModel/LFSigmaHadTables.h index 77c91c30349..984aa9005a5 100644 --- a/PWGLF/DataModel/LFSigmaHadTables.h +++ b/PWGLF/DataModel/LFSigmaHadTables.h @@ -36,14 +36,17 @@ DECLARE_SOA_COLUMN(PyHad, pyHad, float); //! Py of the hadron cand DECLARE_SOA_COLUMN(PzHad, pzHad, float); //! Pz of the hadron candidate DECLARE_SOA_COLUMN(NSigmaTPCHad, nSigmaTPCHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TPC DECLARE_SOA_COLUMN(NSigmaTOFHad, nSigmaTOFHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Collision multiplicity // MC Columns -DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma daughter -DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter -DECLARE_SOA_COLUMN(HadPDG, hadPDG, int); //! PDG code of the hadron candidate -DECLARE_SOA_COLUMN(SigmaGenPt, sigmaGenPt, float); //! Generated pT of the Sigma candidate -DECLARE_SOA_COLUMN(HadGenPt, hadGenPt, float); //! Generated pT of the hadron candidate -DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-hadron pair +DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma candidate +DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter +DECLARE_SOA_COLUMN(HadPDG, hadPDG, int); //! PDG code of the hadron candidate +DECLARE_SOA_COLUMN(SigmaMotherPDG, sigmaMotherPDG, int); //! PDG code of the direct mother of the Sigma +DECLARE_SOA_COLUMN(SigmaPartonicMotherPDG, sigmaPartonicMotherPDG, int); //! PDG code of the partonic (quark/gluon) ancestor of the Sigma +DECLARE_SOA_COLUMN(SigmaGenPt, sigmaGenPt, float); //! Generated pT of the Sigma candidate +DECLARE_SOA_COLUMN(HadGenPt, hadGenPt, float); //! Generated pT of the hadron candidate +DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-hadron pair } // namespace sigmaproton @@ -52,15 +55,16 @@ DECLARE_SOA_TABLE(SigmaProtonCands, "AOD", "SIGMAPROTONCANDS", sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, - sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad); + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad, sigmaproton::Multiplicity); DECLARE_SOA_TABLE(SigmaProtonMCCands, "AOD", "SIGMAPROTONMCCANDS", o2::soa::Index<>, sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, - sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad, + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad, sigmaproton::Multiplicity, sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::HadPDG, + sigmaproton::SigmaMotherPDG, sigmaproton::SigmaPartonicMotherPDG, sigmaproton::SigmaGenPt, sigmaproton::HadGenPt, sigmaproton::GenKStar); } // namespace o2::aod diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index 3eaee6351b3..1884caad6a7 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -17,6 +17,7 @@ #include "PWGLF/DataModel/LFSigmaHadTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" @@ -37,6 +38,7 @@ #include #include +#include #include #include @@ -50,8 +52,8 @@ using namespace o2::framework::expressions; using TracksFull = soa::Join; using TracksFullMC = soa::Join; -using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; struct sigmaHadCand { @@ -86,6 +88,11 @@ struct sigmaHadCand { int kinkDauID = -1; // ID of the pion from Sigma decay in MC int sigmaID = -1; // ID of the Sigma candidate in MC int hadID = -1; // ID of the hadron candidate in MC + + int sigmaMotherPDG = -999; // PDG of the direct mother of the Sigma in MC + int sigmaPartonicMotherPDG = -999; // PDG of the first or last partonic ancestor of the Sigma in MC + + float multiplicity = -1.f; }; struct sigmaHadCorrTask { @@ -124,6 +131,9 @@ struct sigmaHadCorrTask { Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-hadron candidates"}; Configurable fillSparseInvMassKstar{"fillSparseInvMassKstar", false, "If true, fill THn with invmass, k*, sigma charge, proton charge, sigma decay radius, cosPA, sigma pt"}; + Configurable saveMultiplicity{"saveMultiplicity", false, "If true, save collision multiplicity in the output table"}; + Configurable useMultNTracksPV{"useMultNTracksPV", false, "If true, use multNTracksPV for multiplicity and mixing bins; if false, use numContrib"}; + Configurable findLastPartonicMother{"findLastPartonicMother", true, "If true, store the initial hard-scattering parton (last partonic mother). If false, store the last parton before hadronization (first partonic mother)"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; @@ -278,6 +288,103 @@ struct sigmaHadCorrTask { return doSigmaPion ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; } + // Section of functions to retrieve MC truth information for the Sigma candidate (adapted from PWGCF/Femto) + // Get the PDG code of the direct mother of the Sigma candidate + template + int getSigmaMotherPDG(const TMcParticle& mcParticle, const TMcParticles& mcParticles) + { + if (!mcParticle.has_mothers()) { + return -999; + } + auto motherIds = mcParticle.mothersIds(); + int mcMotherIndex = motherIds.front(); + if (mcMotherIndex < 0 || mcMotherIndex >= static_cast(mcParticles.size())) { + return -999; + } + return mcParticles.iteratorAt(mcMotherIndex).pdgCode(); + } + + // Walk up the decay chain and return the PDG of the first quark or gluon ancestor found + template + int findFirstPartonicMotherPDG(const TMcParticle& mcParticle, const TMcParticles& mcParticles) + { + if (!mcParticle.has_mothers()) { + return -999; + } + auto motherIds = mcParticle.mothersIds(); + const int defaultMotherSize = 2; + std::vector allMotherIds; + if (motherIds.size() == defaultMotherSize && motherIds[1] > motherIds[0]) { + for (int i = motherIds[0]; i <= motherIds[1]; i++) + allMotherIds.push_back(i); + } else { + for (const int& id : motherIds) + allMotherIds.push_back(id); + } + for (const int& i : allMotherIds) { + if (i < 0 || i >= static_cast(mcParticles.size())) + continue; + const auto& mother = mcParticles.iteratorAt(i); + int pdgAbs = std::abs(mother.pdgCode()); + if (pdgAbs <= PDG_t::kTop || pdgAbs == PDG_t::kGluon) { + return mother.pdgCode(); + } + int found = findFirstPartonicMotherPDG(mother, mcParticles); + if (found != -999) + return found; + } + return -999; + } + + // Walk up the decay chain iteratively and return the PDG of the last quark or gluon before beam remnants + template + int findLastPartonicMotherPDG(const TMcParticle& mcParticle, const TMcParticles& mcParticles) + { + int lastPartonPDG = -999; + int64_t currentIndex = mcParticle.globalIndex(); + while (currentIndex >= 0 && currentIndex < static_cast(mcParticles.size())) { + const auto& current = mcParticles.iteratorAt(currentIndex); + if (!current.has_mothers()) + break; + auto motherIds = current.mothersIds(); + int nextIndex = -1; + const int defaultMotherSize = 2; + if (motherIds.size() == defaultMotherSize && motherIds[1] > motherIds[0]) { + nextIndex = motherIds[0]; + } else { + for (const int& id : motherIds) { + if (id >= 0 && id < static_cast(mcParticles.size())) { + nextIndex = id; + break; + } + } + } + if (nextIndex < 0 || nextIndex >= static_cast(mcParticles.size())) + break; + const auto& mother = mcParticles.iteratorAt(nextIndex); + int pdgAbs = std::abs(mother.pdgCode()); + int status = std::abs(o2::mcgenstatus::getGenStatusCode(mother.statusCode())); + bool isParton = (pdgAbs <= PDG_t::kTop || pdgAbs == PDG_t::kGluon); + const int isBeamParticleLowerLimit = 11; + const int isBeamParticleUpperLimit = 19; + bool isBeam = (status >= isBeamParticleLowerLimit && status <= isBeamParticleUpperLimit); + if (isBeam) + return lastPartonPDG; + if (isParton) + lastPartonPDG = mother.pdgCode(); + currentIndex = nextIndex; + } + return lastPartonPDG; + } + + int getPartonicMotherPDG(const auto& mcParticle, const auto& mcParticles) + { + if (findLastPartonicMother.value) { + return findLastPartonicMotherPDG(mcParticle, mcParticles); + } + return findFirstPartonicMotherPDG(mcParticle, mcParticles); + } + float getSigmaMassForKstar() { return doSigmaMinus ? o2::constants::physics::MassSigmaMinus : o2::constants::physics::MassSigmaPlus; @@ -455,6 +562,7 @@ struct sigmaHadCorrTask { candidate.sigmaID = sigmaCand.trackMothId(); candidate.kinkDauID = sigmaCand.trackDaugId(); candidate.hadID = hadTrack.globalIndex(); + candidate.multiplicity = saveMultiplicity.value ? (useMultNTracksPV.value ? collision.multNTracksPV() : collision.numContrib()) : -1.f; float kStar = getKStar(sigmaPRecal[0], sigmaPRecal[1], sigmaPRecal[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); if (kStar > cutMaxKStar) { @@ -510,7 +618,8 @@ struct sigmaHadCorrTask { candidate.pyHad, candidate.pzHad, candidate.nSigmaTPCHad, - candidate.nSigmaTOFHad); + candidate.nSigmaTOFHad, + candidate.multiplicity); } } } @@ -519,54 +628,64 @@ struct sigmaHadCorrTask { // Processing Event Mixing SliceCache cache; - using BinningType = ColumnBinningPolicy; - BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; + using BinningTypeNumContrib = ColumnBinningPolicy; + using BinningTypeMultNTracksPV = ColumnBinningPolicy; + BinningTypeNumContrib colBinningNumContrib{{CfgVtxBins, CfgMultBins}, true}; + BinningTypeMultNTracksPV colBinningPVMult{{CfgVtxBins, CfgMultBins}, true}; void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaHadCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; + if (useMultNTracksPV.value) { + for (auto const& [collision1, collision2] : + selfCombinations(colBinningPVMult, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) + continue; + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) + continue; + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, false); + if (fillOutputTree) { + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz, + candidate.sigmaDecRadius, candidate.sigmaCosPA, candidate.chargeHad, + candidate.pxHad, candidate.pyHad, candidate.pzHad, + candidate.nSigmaTPCHad, candidate.nSigmaTOFHad, candidate.multiplicity); + } + } } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, false); - - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaHadCandidates) { - outputDataTable(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargeHad, - candidate.pxHad, - candidate.pyHad, - candidate.pzHad, - candidate.nSigmaTPCHad, - candidate.nSigmaTOFHad); + } else { + for (auto const& [collision1, collision2] : + selfCombinations(colBinningNumContrib, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) + continue; + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) + continue; + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, false); + if (fillOutputTree) { + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz, + candidate.sigmaDecRadius, candidate.sigmaCosPA, candidate.chargeHad, + candidate.pxHad, candidate.pyHad, candidate.pzHad, + candidate.nSigmaTPCHad, candidate.nSigmaTOFHad, candidate.multiplicity); + } } } } - LOG(debug) << "Processing mixed event"; } PROCESS_SWITCH(sigmaHadCorrTask, processMixedEvent, "Process Mixed event", false); - void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const&) + void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const& mcParticles) { for (auto const& collision : collisions) { @@ -594,6 +713,8 @@ struct sigmaHadCorrTask { auto pdgSigma = mcPartSigma.pdgCode(); auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + auto sigmaMotherPDG = getSigmaMotherPDG(mcPartSigma, mcParticles); + auto sigmaPartonicMotherPDG = getPartonicMotherPDG(mcPartSigma, mcParticles); float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); @@ -631,9 +752,12 @@ struct sigmaHadCorrTask { candidate.pzHad, candidate.nSigmaTPCHad, candidate.nSigmaTOFHad, + candidate.multiplicity, pdgSigma, pdgSigmaDau, pdgHad, + sigmaMotherPDG, + sigmaPartonicMotherPDG, sigmaPtGen, hadPtGen, kStarGen); @@ -643,86 +767,107 @@ struct sigmaHadCorrTask { } PROCESS_SWITCH(sigmaHadCorrTask, processSameEventMC, "Process Same event MC", false); - void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles&) + void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles& mcParticles) { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaHadCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; - } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, true); - - for (const auto& candidate : sigmaHadCandidates) { - auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); - auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); - auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); - - if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) { - continue; // Skip candidates where MC truth is not available - } - - auto mcPartSigma = mcLabelSigma.mcParticle_as(); - auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); - auto mcPartHad = mcLabelHad.mcParticle_as(); - auto pdgSigma = mcPartSigma.pdgCode(); - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; - auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; - float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); - float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); - float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); - - if (fillSparseInvMassKstar) { - auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, - candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz); - float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); - float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); - rSigmaHad.fill(HIST("hSparseSigmaHadMC"), - candidate.sigmaMass, - kStarRec, - candidate.sigmaCharge, - candidate.chargeHad, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - sigmaPtUsed, - kStarGen); + if (useMultNTracksPV.value) { + for (auto const& [collision1, collision2] : + selfCombinations(colBinningPVMult, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) + continue; + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) + continue; + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, true); + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) + continue; + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + auto sigmaMotherPDG = getSigmaMotherPDG(mcPartSigma, mcParticles); + auto sigmaPartonicMotherPDG = getPartonicMotherPDG(mcPartSigma, mcParticles); + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), candidate.sigmaMass, kStarRec, candidate.sigmaCharge, + candidate.chargeHad, candidate.sigmaDecRadius, candidate.sigmaCosPA, sigmaPtUsed, kStarGen); + } + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz, + candidate.sigmaDecRadius, candidate.sigmaCosPA, candidate.chargeHad, + candidate.pxHad, candidate.pyHad, candidate.pzHad, + candidate.nSigmaTPCHad, candidate.nSigmaTOFHad, candidate.multiplicity, + pdgSigma, pdgSigmaDau, pdgHad, sigmaMotherPDG, sigmaPartonicMotherPDG, + sigmaPtGen, hadPtGen, kStarGen); + } } - - if (fillOutputTree) { - outputDataTableMC(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargeHad, - candidate.pxHad, - candidate.pyHad, - candidate.pzHad, - candidate.nSigmaTPCHad, - candidate.nSigmaTOFHad, - pdgSigma, - pdgSigmaDau, - pdgHad, - sigmaPtGen, - hadPtGen, - kStarGen); + } + } else { + for (auto const& [collision1, collision2] : + selfCombinations(colBinningNumContrib, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) + continue; + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) + continue; + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, true); + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) + continue; + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + auto sigmaMotherPDG = getSigmaMotherPDG(mcPartSigma, mcParticles); + auto sigmaPartonicMotherPDG = getPartonicMotherPDG(mcPartSigma, mcParticles); + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), candidate.sigmaMass, kStarRec, candidate.sigmaCharge, + candidate.chargeHad, candidate.sigmaDecRadius, candidate.sigmaCosPA, sigmaPtUsed, kStarGen); + } + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz, + candidate.sigmaDecRadius, candidate.sigmaCosPA, candidate.chargeHad, + candidate.pxHad, candidate.pyHad, candidate.pzHad, + candidate.nSigmaTPCHad, candidate.nSigmaTOFHad, candidate.multiplicity, + pdgSigma, pdgSigmaDau, pdgHad, sigmaMotherPDG, sigmaPartonicMotherPDG, + sigmaPtGen, hadPtGen, kStarGen); + } } } } - LOG(debug) << "Processing mixed event MC"; } PROCESS_SWITCH(sigmaHadCorrTask, processMixedEventMC, "Process Mixed event MC", false); }; From 091affe6bbb62cb3b58473dc5a525bfa92e9c4f0 Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Mon, 4 May 2026 15:18:26 +0200 Subject: [PATCH 024/449] [PWGCF] FemtoUniverse: Add pT max limit for ITS signal (#16082) --- .../TableProducer/femtoUniverseProducerTask.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index b514d43615a..a112f5f4768 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -1313,7 +1313,10 @@ struct FemtoUniverseProducerTask { if (track.itsChi2NCl() > ConfTrkSelection.confTrkMaxChi2PerClusterITS) { continue; } - if ((ConfTrkSelection.confTrkTPCRefit && !track.hasTPC()) || (ConfTrkSelection.confTrkITSRefit && !track.hasITS())) { + if (ConfTrkSelection.confTrkTPCRefit && !track.hasTPC()) { + continue; + } + if (ConfTrkSelection.confTrkITSRefit && track.pt() < confTOFpTmin && !track.hasITS()) { continue; } From 49e3d7d5d382ef3aa7455833f5ab545ded99a5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Mon, 4 May 2026 15:43:34 +0200 Subject: [PATCH 025/449] [PWGJE] Fix includes (#16092) --- PWGJE/TableProducer/slimTablesProducer.cxx | 10 +++++----- PWGJE/Tasks/hfFragmentationFunction.cxx | 2 -- PWGJE/Tasks/jetDsSpecSubs.cxx | 3 ++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/PWGJE/TableProducer/slimTablesProducer.cxx b/PWGJE/TableProducer/slimTablesProducer.cxx index a346a1404f2..58fea43fdae 100644 --- a/PWGJE/TableProducer/slimTablesProducer.cxx +++ b/PWGJE/TableProducer/slimTablesProducer.cxx @@ -17,21 +17,21 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include #include #include #include #include +#include +#include #include #include +#include #include -#include +#include +#include #include #include diff --git a/PWGJE/Tasks/hfFragmentationFunction.cxx b/PWGJE/Tasks/hfFragmentationFunction.cxx index e2f8d467661..50e1e2b0ef0 100644 --- a/PWGJE/Tasks/hfFragmentationFunction.cxx +++ b/PWGJE/Tasks/hfFragmentationFunction.cxx @@ -17,9 +17,7 @@ /// The task store data relevant to the calculation of hadronization observables radial /// profile and/or jet momentum fraction for charmed hadrons -#include "PWGHF/Core/DecayChannels.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" diff --git a/PWGJE/Tasks/jetDsSpecSubs.cxx b/PWGJE/Tasks/jetDsSpecSubs.cxx index 1c4ff913f74..12253f021c6 100644 --- a/PWGJE/Tasks/jetDsSpecSubs.cxx +++ b/PWGJE/Tasks/jetDsSpecSubs.cxx @@ -16,18 +16,19 @@ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include #include #include #include #include -#include #include #include #include #include +#include #include #include From cb76f5c90a21e76016eb0558a8e0a61890d0ed4d Mon Sep 17 00:00:00 2001 From: choich08365 <157435123+choich08365@users.noreply.github.com> Date: Mon, 4 May 2026 22:55:09 +0900 Subject: [PATCH 026/449] [PWGJE] Removed collisionId criteria for processMcTrackLabelsWithCollisionAssociator in derivedDataProducer.cxx (#16070) Co-authored-by: Changhwan Choi Co-authored-by: ALICE Action Bot --- PWGJE/Core/JetTaggingUtilities.h | 12 ++++++++---- PWGJE/TableProducer/derivedDataProducer.cxx | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index 0e8b08c3fa2..754c19331dc 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -990,12 +990,16 @@ int vertexClustering(AnyCollision const& collision, AnalysisJet const& jet, AnyT int trkIdx = 0; for (auto const& constituent : jet.template tracks_as()) { if (!constituent.has_mcParticle() || !constituent.template mcParticle_as().isPhysicalPrimary() || constituent.pt() < trackPtMin) { - trkLabels["trkOrigin"].push_back(0); + trkLabels["trkOrigin"].push_back(0); // fake track, non-physical primary track } else { const auto& particle = constituent.template mcParticle_as(); - int orig = RecoDecay::getParticleOrigin(particles, particle, searchUpToQuark); - trkLabels["trkOrigin"].push_back((orig > 0) ? orig : (trkLabels["trkVtxIndex"][trkIdx] == 0) ? 3 - : 4); + if (particle.mcCollisionId() != collision.globalIndex()) { + trkLabels["trkOrigin"].push_back(0); // mismatched coll track + } else { + int orig = RecoDecay::getParticleOrigin(particles, particle, searchUpToQuark); + trkLabels["trkOrigin"].push_back((orig != RecoDecay::OriginType::None) ? static_cast(orig) : (trkLabels["trkVtxIndex"][trkIdx] == 0) ? 3 + : 4); // 1: charm, 2: beauty, 3: primary, 4: other secondary + } } trkIdx++; diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index 6a482f981df..3676ab5a6e9 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -582,7 +582,7 @@ struct JetDerivedDataProducerTask { auto collisionTrackIndices = assocCollisions.sliceBy(preslices.perCollisionTrackIndices, collision.globalIndex()); for (auto const& collisionTrackIndex : collisionTrackIndices) { auto track = collisionTrackIndex.track_as>(); - if (track.collisionId() == collision.globalIndex() && track.has_mcParticle()) { + if (track.has_mcParticle()) { products.jMcTracksLabelTable(track.mcParticleId()); } else { products.jMcTracksLabelTable(-1); From 22f79969cbf8b5076a73907b92bae7c31b665c8f Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Mon, 4 May 2026 22:23:50 +0800 Subject: [PATCH 027/449] [PWGCF] Read phi from TracksIU (#16060) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 290 ++++++++++--------- 1 file changed, 149 insertions(+), 141 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index 96608586509..62544deb592 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -85,11 +85,11 @@ using namespace o2::framework::expressions; namespace o2::aod { -using JoinedCollisions = soa::Join; -using JoinedTracks = soa::Join; -using JoinedCollisionsWithMc = soa::Join; -using JoinedTracksWithMc = soa::Join; -using JoinedMcCollisions = soa::Join; +using JoinedCollisions = soa::Join; +using JoinedTracks = soa::Join; +using JoinedCollisionsWithMc = soa::Join; +using JoinedTracksWithMc = soa::Join; +using JoinedMcCollisions = soa::Join; namespace derived_collision { @@ -695,74 +695,6 @@ inline constexpr bool isEnabled(const Configurable>& cfg) } // namespace struct PartNumFluc { - struct : ConfigurableGroup { - Configurable cfgCcdbUrl{"cfgCcdbUrl", "http://ccdb-test.cern.ch:8080", "Url of CCDB"}; - Configurable cfgCcdbPath{"cfgCcdbPath", "Users/f/fasi/test", "Path in CCDB"}; - Configurable cfgCcdbTimestampLatest{"cfgCcdbTimestampLatest", 0, "Latest timestamp in CCDB"}; - } groupCcdb; - - struct : ConfigurableGroup { - Configurable cfgFlagQaRun{"cfgFlagQaRun", false, "Run QA flag"}; - Configurable cfgFlagQaEvent{"cfgFlagQaEvent", false, "Event QA flag"}; - Configurable cfgFlagQaCentrality{"cfgFlagQaCentrality", false, "Centrality QA flag"}; - Configurable cfgFlagQaTrack{"cfgFlagQaTrack", false, "Track QA flag"}; - Configurable cfgFlagQaDca{"cfgFlagQaDca", false, "DCA QA flag"}; - Configurable> cfgFlagQaAcceptance{"cfgFlagQaAcceptance", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "Acceptance QA flag"}; - Configurable> cfgFlagQaPhi{"cfgFlagQaPhi", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "Phi QA flag"}; - Configurable> cfgFlagQaPid{"cfgFlagQaPid", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "PID QA flag"}; - Configurable cfgFlagQaMc{"cfgFlagQaMc", false, "MC QA flag"}; - Configurable> cfgFlagCalculationYield{"cfgFlagCalculationYield", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Yield calculation flag"}; - Configurable> cfgFlagCalculationPurity{"cfgFlagCalculationPurity", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Purity calculation flag"}; - Configurable> cfgFlagCalculationFractionPrimary{"cfgFlagCalculationFractionPrimary", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Primary fraction calculation flag"}; - Configurable> cfgFlagCalculationFluctuation{"cfgFlagCalculationFluctuation", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Fluctuation calculation flag"}; - } groupAnalysis; - - struct : ConfigurableGroup { - Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", false, "Bad run rejection flag"}; - Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", false, "MC bad run rejection flag"}; - Configurable cfgLabelFlagsRct{"cfgLabelFlagsRct", "CBT_hadronPID", "RCT flags label"}; - Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", std::uint64_t{0b10000000001101000000000000000000000000000000000000}, "Event selection bits"}; - Configurable cfgFlagInelEvent{"cfgFlagInelEvent", true, "Flag of requiring inelastic event"}; - Configurable cfgFlagInelEventMc{"cfgFlagInelEventMc", false, "Flag of requiring inelastic MC event"}; - Configurable cfgCutMaxAbsVz{"cfgCutMaxAbsVz", 6., "Maximum absolute z-vertex position (cm)"}; - Configurable cfgFlagCutVzMc{"cfgFlagCutVzMc", false, "Flag of requiring MC z-vertex cut"}; - Configurable cfgCutMinDeviationNPvContributors{"cfgCutMinDeviationNPvContributors", -4, "Minimum nPvContributors deviation from nGlobalTracks"}; - Configurable cfgIndexDefinitionCentrality{"cfgIndexDefinitionCentrality", 2, "Centrality definition index"}; - ConfigurableAxis cfgAxisCentrality{"cfgAxisCentrality", {VARIABLE_WIDTH, 0., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 90.}, "Centrality axis in fluctuation calculation"}; - Configurable cfgNSubgroups{"cfgNSubgroups", 20, "Number of subgroups in fluctuation calculation"}; - } groupEvent; - - struct : ConfigurableGroup { - Configurable cfgFlagPvContributor{"cfgFlagPvContributor", true, "Flag of requiring PV contributor"}; - Configurable cfgCutMinItsNCls{"cfgCutMinItsNCls", 5, "Minimum number of clusters ITS"}; - Configurable cfgCutMaxItsChi2NCls{"cfgCutMaxItsChi2NCls", 30., "Maximum chi2 per cluster ITS"}; - Configurable cfgCutMinTpcNCls{"cfgCutMinTpcNCls", 55, "Minimum number of clusters TPC"}; - Configurable cfgCutMaxTpcChi2NCls{"cfgCutMaxTpcChi2NCls", 3.5, "Maximum chi2 per cluster TPC"}; - Configurable cfgCutMaxTpcNClsSharedRatio{"cfgCutMaxTpcNClsSharedRatio", 0.25, "Maximum ratio of shared clusters over clusters TPC"}; - Configurable cfgCutMinTpcNCrossedRows{"cfgCutMinTpcNCrossedRows", 75, "Minimum number of crossed rows TPC"}; - Configurable cfgCutMinTpcNCrossedRowsRatio{"cfgCutMinTpcNCrossedRowsRatio", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; - Configurable cfgFlagRecalibrationDca{"cfgFlagRecalibrationDca", false, "DCA recalibration flag"}; - Configurable> cfgCutMaxAbsNSigmaDca{"cfgCutMaxAbsNSigmaDca", {std::array>{2.5, 2.5}.data(), NEs, getDisplayNames()}, "Maximum absolute nSigma of DCA (cm)"}; - Configurable cfgCutMinPt{"cfgCutMinPt", 0.4, "Minimum pT (GeV/c)"}; - Configurable cfgCutMaxPt{"cfgCutMaxPt", 2., "Maximum pT (GeV/c)"}; - Configurable cfgCutMaxAbsEta{"cfgCutMaxAbsEta", 0.8, "Maximum absolute eta"}; - Configurable> cfgThresholdPtTofPid{"cfgThresholdPtTofPid", {std::array>{0.5, 0.5, 0.8}.data(), NEs, getDisplayNames()}, "pT (GeV/c) threshold for TOF PID"}; - Configurable> cfgFlagRecalibrationNSigmaPid{"cfgFlagRecalibrationNSigmaPid", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "nSigma PID recalibration flag"}; - Configurable cfgFlagRejectionOthers{"cfgFlagRejectionOthers", false, "Other particle species rejection flag"}; - Configurable cfgCutMaxAbsNSigmaPid{"cfgCutMaxAbsNSigmaPid", 2., "Maximum absolute nSigma for PID"}; - Configurable cfgFlagMcParticlePhysicalPrimary{"cfgFlagMcParticlePhysicalPrimary", true, "Flag of requiring physical primary MC particle"}; - Configurable cfgFlagMcParticleMomentum{"cfgFlagMcParticleMomentum", true, "Flag of using momentum of MC particle"}; - } groupTrack; - - aod::rctsel::RCTFlagsChecker rctFlagsChecker; - - Service pdg; - Service ccdb; - - Produces derivedCollision; - Produces derivedParticle; - Produces derivedTrack; - struct HolderCcdb { static constexpr std::int32_t NDimensionsEfficiency{4}; @@ -840,7 +772,6 @@ struct PartNumFluc { std::int32_t charge{}; double pt{}; double eta{}; - double phi{}; void clear() { *this = {}; } } holderMcParticle; @@ -855,6 +786,7 @@ struct PartNumFluc { double pt{}; double eta{}; double phi{}; + double phiIu{}; std::array> hasPid{}; std::array>, NEs> nSigmaPid{[] { std::array>, NEs> a{}; @@ -879,16 +811,85 @@ struct PartNumFluc { return std::numeric_limits::min() <= value && value <= std::numeric_limits::max() ? std::round(value) : (std::is_signed_v ? std::numeric_limits::min() : std::numeric_limits::max()); } - std::uint16_t nChargedParticlesAll{}; - std::uint16_t nChargedParticlesIn{}; - std::uint16_t nTracksAll{}; - std::uint16_t nTracksIn{}; + aod::derived_collision::NChargedParticlesAll::type nChargedParticlesAll{}; + aod::derived_collision::NChargedParticlesIn::type nChargedParticlesIn{}; + aod::derived_collision::NTracksAll::type nTracksAll{}; + aod::derived_collision::NTracksIn::type nTracksIn{}; + std::vector signedEfficienciesParticle{[] {std::vector v{}; v.reserve(256); return v; }()}; + std::vector signedEfficienciesTrack{[] {std::vector v{}; v.reserve(256); return v; }()}; - void clear() { *this = {}; } + void clear() + { + nChargedParticlesAll = {}; + nChargedParticlesIn = {}; + nTracksAll = {}; + nTracksIn = {}; + signedEfficienciesParticle.clear(); + signedEfficienciesTrack.clear(); + } } holderDerivedData; std::array, NEs>, NEs> fluctuationCalculatorTrack{}; + struct : ConfigurableGroup { + Configurable cfgCcdbUrl{"cfgCcdbUrl", "http://ccdb-test.cern.ch:8080", "Url of CCDB"}; + Configurable cfgCcdbPath{"cfgCcdbPath", "Users/f/fasi/test", "Path in CCDB"}; + Configurable cfgCcdbTimestampLatest{"cfgCcdbTimestampLatest", std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(), "Latest timestamp in CCDB"}; + } groupCcdb; + + struct : ConfigurableGroup { + Configurable cfgFlagQaRun{"cfgFlagQaRun", false, "Run QA flag"}; + Configurable cfgFlagQaEvent{"cfgFlagQaEvent", false, "Event QA flag"}; + Configurable cfgFlagQaCentrality{"cfgFlagQaCentrality", false, "Centrality QA flag"}; + Configurable cfgFlagQaTrack{"cfgFlagQaTrack", false, "Track QA flag"}; + Configurable cfgFlagQaDca{"cfgFlagQaDca", false, "DCA QA flag"}; + Configurable> cfgFlagQaAcceptance{"cfgFlagQaAcceptance", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "Acceptance QA flag"}; + Configurable> cfgFlagQaPhi{"cfgFlagQaPhi", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "Phi QA flag"}; + Configurable> cfgFlagQaPid{"cfgFlagQaPid", {std::array>{false, false, false, false}.data(), NEs, getDisplayNames()}, "PID QA flag"}; + Configurable cfgFlagQaMc{"cfgFlagQaMc", false, "MC QA flag"}; + Configurable> cfgFlagCalculationYield{"cfgFlagCalculationYield", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Yield calculation flag"}; + Configurable> cfgFlagCalculationPurity{"cfgFlagCalculationPurity", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Purity calculation flag"}; + Configurable> cfgFlagCalculationFractionPrimary{"cfgFlagCalculationFractionPrimary", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Primary fraction calculation flag"}; + Configurable> cfgFlagCalculationFluctuation{"cfgFlagCalculationFluctuation", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "Fluctuation calculation flag"}; + } groupAnalysis; + + struct : ConfigurableGroup { + Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", false, "Bad run rejection flag"}; + Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", false, "MC bad run rejection flag"}; + Configurable cfgLabelFlagsRct{"cfgLabelFlagsRct", "CBT_hadronPID", "RCT flags label"}; + Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", std::uint64_t{0b10000000001101000000000000000000000000000000000000}, "Event selection bits"}; + Configurable cfgFlagInelEvent{"cfgFlagInelEvent", true, "Flag of requiring inelastic event"}; + Configurable cfgFlagInelEventMc{"cfgFlagInelEventMc", false, "Flag of requiring inelastic MC event"}; + Configurable cfgCutMaxAbsVz{"cfgCutMaxAbsVz", 6., "Maximum absolute z-vertex position (cm)"}; + Configurable cfgFlagCutVzMc{"cfgFlagCutVzMc", false, "Flag of requiring MC z-vertex cut"}; + Configurable cfgCutMinDeviationNPvContributors{"cfgCutMinDeviationNPvContributors", -4, "Minimum nPvContributors deviation from nGlobalTracks"}; + Configurable cfgIndexDefinitionCentrality{"cfgIndexDefinitionCentrality", 2, "Centrality definition index"}; + ConfigurableAxis cfgAxisCentrality{"cfgAxisCentrality", {VARIABLE_WIDTH, 0., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 90.}, "Centrality axis in fluctuation calculation"}; + Configurable cfgNSubgroups{"cfgNSubgroups", 20, "Number of subgroups in fluctuation calculation"}; + } groupEvent; + + struct : ConfigurableGroup { + Configurable cfgFlagPvContributor{"cfgFlagPvContributor", true, "Flag of requiring PV contributor"}; + Configurable cfgCutMinItsNCls{"cfgCutMinItsNCls", 5, "Minimum number of clusters ITS"}; + Configurable cfgCutMaxItsChi2NCls{"cfgCutMaxItsChi2NCls", 30., "Maximum chi2 per cluster ITS"}; + Configurable cfgCutMinTpcNCls{"cfgCutMinTpcNCls", 55, "Minimum number of clusters TPC"}; + Configurable cfgCutMaxTpcChi2NCls{"cfgCutMaxTpcChi2NCls", 3.5, "Maximum chi2 per cluster TPC"}; + Configurable cfgCutMaxTpcNClsSharedRatio{"cfgCutMaxTpcNClsSharedRatio", 0.25, "Maximum ratio of shared clusters over clusters TPC"}; + Configurable cfgCutMinTpcNCrossedRows{"cfgCutMinTpcNCrossedRows", 75, "Minimum number of crossed rows TPC"}; + Configurable cfgCutMinTpcNCrossedRowsRatio{"cfgCutMinTpcNCrossedRowsRatio", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; + Configurable cfgFlagRecalibrationDca{"cfgFlagRecalibrationDca", false, "DCA recalibration flag"}; + Configurable> cfgCutMaxAbsNSigmaDca{"cfgCutMaxAbsNSigmaDca", {std::array>{2.5, 2.5}.data(), NEs, getDisplayNames()}, "Maximum absolute nSigma of DCA (cm)"}; + Configurable cfgCutMinPt{"cfgCutMinPt", 0.4, "Minimum pT (GeV/c)"}; + Configurable cfgCutMaxPt{"cfgCutMaxPt", 2., "Maximum pT (GeV/c)"}; + Configurable cfgCutMaxAbsEta{"cfgCutMaxAbsEta", 0.8, "Maximum absolute eta"}; + Configurable> cfgThresholdPtTofPid{"cfgThresholdPtTofPid", {std::array>{0.5, 0.5, 0.8}.data(), NEs, getDisplayNames()}, "pT (GeV/c) threshold for TOF PID"}; + Configurable> cfgFlagRecalibrationNSigmaPid{"cfgFlagRecalibrationNSigmaPid", {std::array>{false, false, false}.data(), NEs, getDisplayNames()}, "nSigma PID recalibration flag"}; + Configurable cfgFlagRejectionOthers{"cfgFlagRejectionOthers", false, "Other particle species rejection flag"}; + Configurable cfgCutMaxAbsNSigmaPid{"cfgCutMaxAbsNSigmaPid", 2., "Maximum absolute nSigma for PID"}; + Configurable cfgFlagMcParticlePhysicalPrimary{"cfgFlagMcParticlePhysicalPrimary", true, "Flag of requiring physical primary MC particle"}; + Configurable cfgFlagMcParticleMomentum{"cfgFlagMcParticleMomentum", true, "Flag of using momentum of MC particle"}; + } groupTrack; + HistogramRegistry hrCalculationFluctuation{"hrCalculationFluctuation", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrCalculationFractionPrimary{"hrCalculationFractionPrimary", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrCalculationPurity{"hrCalculationPurity", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -904,11 +905,20 @@ struct PartNumFluc { HistogramRegistry hrQaRun{"hrQaRun", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrCounter{"hrCounter", {}, OutputObjHandlingPolicy::AnalysisObject}; + aod::rctsel::RCTFlagsChecker rctFlagsChecker; + + Service pdg; + Service ccdb; + Filter filterCollision = (aod::evsel::sel8 == true); Filter filterTrack = requireQualityTracksInFilter(); Filter filterMcCollision = (aod::mccollisionprop::numRecoCollision > 0); - Preslice presliceTracksPerCollision = aod::track::collisionId; + Preslice presliceTracksPerCollision{aod::track::collisionId}; + + Produces derivedCollision; + Produces derivedParticle; + Produces derivedTrack; void init(InitContext&) { @@ -932,10 +942,9 @@ struct PartNumFluc { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(true); if (groupCcdb.cfgCcdbTimestampLatest.value >= 0) { - ccdb->setCreatedNotAfter(groupCcdb.cfgCcdbTimestampLatest.value > 0 ? groupCcdb.cfgCcdbTimestampLatest.value : std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count()); + ccdb->setCreatedNotAfter(groupCcdb.cfgCcdbTimestampLatest.value); } - - const TList* const ccdbObject{ccdb->getForTimeStamp(groupCcdb.cfgCcdbPath.value, -1)}; + const TList* const ccdbObject{ccdb->get(groupCcdb.cfgCcdbPath.value)}; if (!ccdbObject || ccdbObject->IsA() != TList::Class()) { LOG(fatal) << "Invalid ccdb_object!"; } @@ -1208,21 +1217,10 @@ struct PartNumFluc { const HistogramConfigSpec hcsQaPhi(HistType::kTHnSparseF, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}, {360, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); - if (doprocessMc.value) { + for (std::int32_t const& iPidStrategy : std::views::iota(0, NEs)) { for (std::int32_t const& iChargeSpecies : std::views::iota(0, NEs)) { - hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhiMc_mc%s%s", getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); - } - for (std::int32_t const& iPidStrategy : std::views::iota(0, NEs)) { - for (std::int32_t const& iChargeSpecies : std::views::iota(0, NEs)) { - hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhiMc_mc%s%s%s", getName(iPidStrategy).data(), getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); - hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhi_mc%s%s%s", getName(iPidStrategy).data(), getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); - } - } - } else { - for (std::int32_t const& iPidStrategy : std::views::iota(0, NEs)) { - for (std::int32_t const& iChargeSpecies : std::views::iota(0, NEs)) { - hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhi_%s%s%s", getName(iPidStrategy).data(), getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); - } + hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhi_%s%s%s", doprocessMc.value ? Form("mc%s", getName(iPidStrategy).data()) : getName(iPidStrategy).data(), getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); + hrQaPhi.add(Form("QaPhi/hCentralityPtEtaPhiIu_%s%s%s", doprocessMc.value ? Form("mc%s", getName(iPidStrategy).data()) : getName(iPidStrategy).data(), getName(iParticleSpeciesAll).data(), getName(iChargeSpecies).data()), "", hcsQaPhi); } } } @@ -1699,7 +1697,7 @@ struct PartNumFluc { } template - requires IsValid + requires IsValid && (dataMode != DataMode::kMcMcParticle) void fillQaPhiByParticleSpeciesAll() { if (!groupAnalysis.cfgFlagQaPhi.value.get(toI(particleSpeciesAll))) { @@ -1714,29 +1712,24 @@ struct PartNumFluc { const auto fillByChargeSpecies = [&] requires IsValid () { - if constexpr (dataMode == DataMode::kMcMcParticle) { - if (isPid()) { - hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhiMc_mc") + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - } - } else { - const auto fillByPidStrategy = [&] - requires IsValid - () { - if constexpr (dataMode == DataMode::kMcTrack) { - if (isPid() && isPid(pidStrategy), particleSpeciesAll>(false)) { - hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhiMc_mc") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhi_mc") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); - } - } else { // dataMode == DataMode::kRawTrack - if (isPid(pidStrategy), particleSpeciesAll>(false)) { - hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhi_") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); - } + const auto fillByPidStrategy = [&] + requires IsValid + () { + if constexpr (dataMode == DataMode::kMcTrack) { + if (isPid() && isPid(pidStrategy), particleSpeciesAll>(false)) { + hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhi_mc") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhiIu_mc") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phiIu); } - }; // NOLINT(readability/braces) + } else { // dataMode == DataMode::kRawTrack + if (isPid(pidStrategy), particleSpeciesAll>(false)) { + hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhi_") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(C_CS("QaPhi/hCentralityPtEtaPhiIu_") + C_SV(getName(pidStrategy)) + C_SV(getName(particleSpeciesAll)) + C_SV(getName(chargeSpecies)), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phiIu); + } + } + }; // NOLINT(readability/braces) - fillByPidStrategy.template operator()(); - fillByPidStrategy.template operator()(); - } + fillByPidStrategy.template operator()(); + fillByPidStrategy.template operator()(); }; // NOLINT(readability/braces) if (chargeSign > 0) { @@ -1969,11 +1962,11 @@ struct PartNumFluc { ++holderMcEvent.numbersEff[toI(particleNumber)][toI(chargeSpecies)]; fill(); } - derivedParticle(derivedCollision.lastIndex() + 1, HolderDerivedData::convertRound(std::copysign(1., chargeSign) * efficiency * 32767.)); + holderDerivedData.signedEfficienciesParticle.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); } else { ++holderEvent.numbers[toI(particleNumber)][toI(chargeSpecies)]; fill(); - derivedTrack(derivedCollision.lastIndex() + 1, HolderDerivedData::convertRound(std::copysign(1., chargeSign) * efficiency * 32767.)); + holderDerivedData.signedEfficienciesTrack.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); } }; // NOLINT(readability/braces) @@ -2028,8 +2021,8 @@ struct PartNumFluc { fillByChargeNumber.template operator()(); } - template - bool initTrack(const T& track) + template + bool initTrack(const T& track, const TIs& tracksIu) { holderTrack.clear(); holderTrack.dca[toI(DcaAxis::kXy)] = track.dcaXY(); @@ -2039,6 +2032,19 @@ struct PartNumFluc { holderTrack.pt = track.pt(); holderTrack.eta = track.eta(); holderTrack.phi = track.phi(); + { + const std::int64_t localIndexTrackIu = track.globalIndex() - tracksIu.offset(); + if (0 <= localIndexTrackIu && localIndexTrackIu < static_cast(tracksIu.size())) { + const auto& trackIu = tracksIu.iteratorAt(localIndexTrackIu); + if (track.globalIndex() == trackIu.globalIndex()) { + holderTrack.phiIu = trackIu.phi(); + } else { + LOG(warning) << "Mismatched track " << track.globalIndex() << " and trackIu " << trackIu.globalIndex(); + } + } else { + LOG(warning) << "Invalid trackIu " << track.globalIndex(); + } + } holderTrack.hasPid[toI(Detector::kTpc)] = (track.hasTPC() && track.tpcSignal() > 0.); if (holderTrack.hasPid[toI(Detector::kTpc)]) { holderTrack.nSigmaPid[toI(PidStrategyAll::kTpc)] = {HolderTrack::truncateNSigmaPid(track.tpcNSigmaPi() - getShiftNSigmaPid()), HolderTrack::truncateNSigmaPid(track.tpcNSigmaKa() - getShiftNSigmaPid()), HolderTrack::truncateNSigmaPid(track.tpcNSigmaPr() - getShiftNSigmaPid())}; @@ -2137,7 +2143,6 @@ struct PartNumFluc { } holderMcParticle.pt = mcParticle.pt(); holderMcParticle.eta = mcParticle.eta(); - holderMcParticle.phi = mcParticle.phi(); if (!isGoodMcParticle(mcParticle)) { return false; @@ -2146,8 +2151,8 @@ struct PartNumFluc { return true; } - template - bool initEvent(const C& collision, const Ts& tracks) + template + bool initEvent(const C& collision, const Ts& tracks, const TIs& tracksIu) { holderEvent.clear(); holderEvent.vz = collision.posZ(); @@ -2235,7 +2240,7 @@ struct PartNumFluc { continue; } - initTrack(track); + initTrack(track, tracksIu); } for (std::int32_t const& iChargeSpecies : std::views::iota(0, NEs)) { if (holderEvent.nGlobalTracks[iChargeSpecies] > 0) { @@ -2327,9 +2332,9 @@ struct PartNumFluc { return true; } - void processRaw(const soa::Filtered::iterator& collision, const soa::Filtered& tracks, const aod::BCsWithTimestamps&) + void processRaw(const soa::Filtered::iterator& collision, const soa::Filtered& tracks, const aod::TracksIU& tracksIu, const aod::BCsWithTimestamps&) { - if (!initEvent(collision, tracks) || (!groupAnalysis.cfgFlagQaTrack.value && !groupAnalysis.cfgFlagQaDca.value && !isEnabled(groupAnalysis.cfgFlagQaAcceptance) && !isEnabled(groupAnalysis.cfgFlagQaPhi) && !isEnabled(groupAnalysis.cfgFlagQaPid) && !isEnabled(groupAnalysis.cfgFlagCalculationYield) && !isEnabled(groupAnalysis.cfgFlagCalculationFluctuation))) { + if (!initEvent(collision, tracks, tracksIu) || (!groupAnalysis.cfgFlagQaTrack.value && !groupAnalysis.cfgFlagQaDca.value && !isEnabled(groupAnalysis.cfgFlagQaAcceptance) && !isEnabled(groupAnalysis.cfgFlagQaPhi) && !isEnabled(groupAnalysis.cfgFlagQaPid) && !isEnabled(groupAnalysis.cfgFlagCalculationYield) && !isEnabled(groupAnalysis.cfgFlagCalculationFluctuation))) { return; } @@ -2344,7 +2349,7 @@ struct PartNumFluc { continue; } - const bool isGood{initTrack(track)}; + const bool isGood{initTrack(track, tracksIu)}; if (isEnabled(groupAnalysis.cfgFlagCalculationFluctuation) && holderTrack.sign != 0) { ++holderDerivedData.nTracksAll; } @@ -2384,11 +2389,14 @@ struct PartNumFluc { fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); derivedCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); + for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesTrack) { + derivedTrack(derivedCollision.lastIndex(), signedEfficiency); + } } } PROCESS_SWITCH(PartNumFluc, processRaw, "Process raw data", true); - void processMc(const soa::Filtered::iterator& mcCollision, const aod::McParticles& mcParticles, const soa::SmallGroups& collisions, const soa::Filtered& tracksUngrouped, const aod::BCsWithTimestamps&) + void processMc(const soa::Filtered::iterator& mcCollision, const aod::McParticles& mcParticles, const soa::SmallGroups& collisions, const soa::Filtered& tracksUngrouped, const aod::TracksIU& tracksIuUngrouped, const aod::BCsWithTimestamps&) { if (!initMcEvent(mcCollision)) { return; @@ -2400,8 +2408,9 @@ struct PartNumFluc { } const auto& tracks{tracksUngrouped.sliceBy(presliceTracksPerCollision, collision.globalIndex())}; + const auto& tracksIu{tracksIuUngrouped.sliceBy(presliceTracksPerCollision, collision.globalIndex())}; - if (!initEvent(collision, tracks)) { + if (!initEvent(collision, tracks, tracksIu)) { continue; } @@ -2409,7 +2418,7 @@ struct PartNumFluc { hrQaMc.fill(C_CS("QaMc/hCentralityVzDeltaVz"), holderEvent.centrality, holderEvent.vz, holderEvent.vz - holderMcEvent.vz); } - if (isEnabled(groupAnalysis.cfgFlagQaPhi) || isEnabled(groupAnalysis.cfgFlagCalculationYield) || isEnabled(groupAnalysis.cfgFlagCalculationFluctuation)) { + if (isEnabled(groupAnalysis.cfgFlagCalculationYield) || isEnabled(groupAnalysis.cfgFlagCalculationFluctuation)) { if (isEnabled(groupAnalysis.cfgFlagCalculationFluctuation)) { holderEvent.subgroupIndex = gRandom->Integer(groupEvent.cfgNSubgroups.value); initCalculationFluctuation(); @@ -2429,13 +2438,6 @@ struct PartNumFluc { continue; } - if (isEnabled(groupAnalysis.cfgFlagQaPhi)) { - fillQaPhiByParticleSpeciesAll(); - fillQaPhiByParticleSpeciesAll(); - fillQaPhiByParticleSpeciesAll(); - fillQaPhiByParticleSpeciesAll(); - } - if (isEnabled(groupAnalysis.cfgFlagCalculationYield)) { fillCalculationYieldByParticleSpecies(); fillCalculationYieldByParticleSpecies(); @@ -2471,7 +2473,7 @@ struct PartNumFluc { continue; } - const bool isGood{initTrack(track) && initMcParticle(mcParticle)}; + const bool isGood{initTrack(track, tracksIu) && initMcParticle(mcParticle)}; if (isEnabled(groupAnalysis.cfgFlagCalculationFluctuation) && holderTrack.sign != 0) { ++holderDerivedData.nTracksAll; } @@ -2528,6 +2530,12 @@ struct PartNumFluc { fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); derivedCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); + for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesParticle) { + derivedParticle(derivedCollision.lastIndex(), signedEfficiency); + } + for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesTrack) { + derivedTrack(derivedCollision.lastIndex(), signedEfficiency); + } } } From b86daa219da6b21032dbae7fe141118063a82c60 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Mon, 4 May 2026 16:38:24 +0200 Subject: [PATCH 028/449] [PWGCF] Fixes in femto framework (#16097) --- PWGCF/Femto/Core/pairHistManager.h | 24 ++++++++++++++--------- PWGCF/Femto/Core/tripletHistManager.h | 19 +++++++++--------- PWGCF/Femto/Tasks/femtoPairEfficiency.cxx | 2 +- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index 079f217c5f3..9c533c8bf4d 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -32,6 +32,7 @@ #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include +#include #include #include #include @@ -903,15 +904,20 @@ class PairHistManager float getKstar(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) { - // compute pair momentum - auto sum = part1 + part2; - // Boost particle 1 to the pair rest frame (Prf) and calculate k* (would be equivalent using particle 2) - // make a copy of particle 1 - auto particle1Prf = ROOT::Math::PtEtaPhiMVector(part1); - // get lorentz boost into pair rest frame - ROOT::Math::Boost boostPrf(sum.BoostToCM()); - // boost particle 1 into pair rest frame and calculate its momentum, which has the same value as k* - return static_cast(boostPrf(particle1Prf).P()); + // Use Cartesian 4-vectors: addition/M2() become pure arithmetic + const ROOT::Math::PxPyPzEVector p1(part1); + const ROOT::Math::PxPyPzEVector p2(part2); + + // Mandelstam s = (p1 + p2)^2 + const double s = (p1 + p2).M2(); + const double m1sq = p1.M2(); + const double m2sq = p2.M2(); + + // Källen function λ(s, m1^2, m2^2) = (s - m1^2 - m2^2)² - 4*m1^2*m2^2 + const double kallen = (s - m1sq - m2sq) * (s - m1sq - m2sq) - 4.0 * m1sq * m2sq; + + // k* = 0.5 * sqrt(λ/s) + return static_cast(0.5 * std::sqrt(std::max(0.0, kallen) / s)); } o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; diff --git a/PWGCF/Femto/Core/tripletHistManager.h b/PWGCF/Femto/Core/tripletHistManager.h index 6f9f2323f31..8e6674f0c10 100644 --- a/PWGCF/Femto/Core/tripletHistManager.h +++ b/PWGCF/Femto/Core/tripletHistManager.h @@ -383,23 +383,24 @@ class TripletHistManager float getQ3() const { return mQ3; } private: - ROOT::Math::PxPyPzEVector getqij(ROOT::Math::PtEtaPhiMVector const& pi, ROOT::Math::PtEtaPhiMVector const& pj) + ROOT::Math::PxPyPzEVector getqij(ROOT::Math::PxPyPzEVector const& vi, ROOT::Math::PxPyPzEVector const& vj) { - // Convert to PxPyPzEVector to get proper Lorentz dot product - ROOT::Math::PxPyPzEVector vi(pi); - ROOT::Math::PxPyPzEVector vj(pj); - auto trackSum = vi + vj; auto trackDifference = vi - vj; - double scaling = trackDifference.Dot(trackSum) / trackSum.Dot(trackSum); + const double s = trackSum.M2(); + const double scaling = (s != 0.0) ? (vi.M2() - vj.M2()) / s : 0.0; return trackDifference - scaling * trackSum; } float getQ3(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2, ROOT::Math::PtEtaPhiMVector const& part3) { - auto q12 = getqij(part1, part2); - auto q23 = getqij(part2, part3); - auto q31 = getqij(part3, part1); + // upfront conversion to PxPyPzEVector + const ROOT::Math::PxPyPzEVector p1(part1); + const ROOT::Math::PxPyPzEVector p2(part2); + const ROOT::Math::PxPyPzEVector p3(part3); + auto q12 = getqij(p1, p2); + auto q23 = getqij(p2, p3); + auto q31 = getqij(p3, p1); double q = q12.M2() + q23.M2() + q31.M2(); return static_cast(std::sqrt(-q)); } diff --git a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx index 10179a63fba..6705f731599 100644 --- a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx +++ b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx @@ -431,7 +431,7 @@ struct FemtoPairEfficiency { ROOT::Math::PtEtaPhiMVector particle1; ROOT::Math::PtEtaPhiMVector particle2; - for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsUpperIndexPolicy(tracks, tracks))) { + for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { bool order1 = checkTrack(p1, TrackSel1) && checkTrackPid(p1, TrackSel1) && checkTrack(p2, TrackSel2) && checkTrackPid(p2, TrackSel2); From 3e7dec77cb2fe6fd7f5a875037f6bd386676a3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Mon, 4 May 2026 16:44:09 +0200 Subject: [PATCH 029/449] [PWGUD] Fix includes (#16095) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index d66ffc6b90d..64bae3adc4c 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -15,15 +15,11 @@ /// copied from Thor Jensen (thor.kjaersgaard.jensen@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch) #include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/GenericFramework/Core/GFW.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" #include #include @@ -37,32 +33,20 @@ #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 From 27796ce03c5caaad1fd1cde95082c01a454fd292 Mon Sep 17 00:00:00 2001 From: a-m-andrushko <96832230+a-m-andrushko@users.noreply.github.com> Date: Mon, 4 May 2026 17:41:30 +0200 Subject: [PATCH 030/449] [PWGCF] FemtoUniverse -- Add hInvMassK0Short to helicity analysis. (#16102) --- .../femtoUniversePairTaskTrackV0Helicity.cxx | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx index 972f511e926..a32bf8392d6 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -188,6 +189,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { Configurable cfgProcessHel4{"cfgProcessHel4", false, "Process particle pairs from the helicity range 4"}; // -0.5 > cosineTheta >= -1.0 ConfigurableAxis confInvMassMotherpTBinsHel{"confInvMassMotherpTBinsHel", {5, 0, 5}, "pT binning in the pT vs. InvMassMother plot for helicity"}; ConfigurableAxis confInvMassMotherBinsHel{"confInvMassMotherBinsHel", {1000, 0.8, 1.4}, "InvMassMother binning in the pT vs. InvMassMother plot for helicity"}; + ConfigurableAxis confInvMassK0Short{"confInvMassK0s", {1000, 0.2, 0.8}, "Invariant mass binning for K0 Short"}; /// Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; @@ -321,6 +323,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.add("Theta/Mother/hInvMassMotherHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/hInvMassMotherHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/hInvMassMotherHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassK0Short", " ; M_{K^{0}_{S}}; ;", kTH1F, {confInvMassK0Short}); /// MC Truth registryMCtruth.add("plus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); @@ -450,7 +453,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { } /// This function processes the same event for Track-V0 - template + template void doSameEvent(FilteredFDCollision const& col, PartType const& parts, PartitionType& groupPartsOne, PartitionType& groupPartsTwo, int helRange, [[maybe_unused]] MCParticles mcParts = nullptr) { const auto& magFieldTesla = col.magField(); @@ -496,6 +499,14 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel3"), part.pt(), part.mLambda()); else if (cosineTheta < -0.5 && cosineTheta >= -1) thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel4"), part.pt(), part.mLambda()); + + if constexpr (confIsMC) { + if (part.has_fdMCParticle()) { + if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0Short"), part.mKaon()); + } + } + } } for (const auto& part : groupPartsOne) { @@ -599,19 +610,19 @@ struct FemtoUniversePairTaskTrackV0Helicity { auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); if (cfgProcessHel) - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 0); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 0); if (cfgProcessHel1) - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 1); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 1); if (cfgProcessHel2) - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 2); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 2); if (cfgProcessHel3) - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 3); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 3); if (cfgProcessHel4) - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 4); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 4); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEvent, "Enable processing same event for track - V0", false); @@ -619,7 +630,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { { auto groupPartsOne = partsOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 0, mcparts); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 0, mcparts); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEventMCReco, "Enable processing same event for track - V0 MC Reco", false); @@ -1099,7 +1110,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { if (!pdgParticle) continue; - if (pdgCode == 3122) { + if (pdgCode == kLambda0) { registryMCtruth.fill(HIST("plus/MCtruthLambda"), part.pt(), part.eta()); // Helicity angle @@ -1125,7 +1136,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { registryMCtruth.fill(HIST("ThetaMCTruth/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); continue; - } else if (pdgCode == -3122) { + } else if (pdgCode == -kLambda0) { registryMCtruth.fill(HIST("minus/MCtruthLambda"), part.pt(), part.eta()); continue; } @@ -1133,11 +1144,11 @@ struct FemtoUniversePairTaskTrackV0Helicity { if (pdgParticle->Charge() > 0.0) { registryMCtruth.fill(HIST("plus/MCtruthAllPt"), part.pt()); } - if (pdgCode == 211) { + if (pdgCode == kPiPlus) { registryMCtruth.fill(HIST("plus/MCtruthPi"), part.pt(), part.eta()); registryMCtruth.fill(HIST("plus/MCtruthPiPt"), part.pt()); } - if (pdgCode == 2212) { + if (pdgCode == kProton) { registryMCtruth.fill(HIST("plus/MCtruthPr"), part.pt(), part.eta()); registryMCtruth.fill(HIST("plus/MCtruthPrPt"), part.pt()); } @@ -1145,11 +1156,11 @@ struct FemtoUniversePairTaskTrackV0Helicity { if (pdgParticle->Charge() < 0.0) { registryMCtruth.fill(HIST("minus/MCtruthAllPt"), part.pt()); } - if (pdgCode == -211) { + if (pdgCode == kPiMinus) { registryMCtruth.fill(HIST("minus/MCtruthPi"), part.pt(), part.eta()); registryMCtruth.fill(HIST("minus/MCtruthPiPt"), part.pt()); } - if (pdgCode == -2212) { + if (pdgCode == -kProton) { registryMCtruth.fill(HIST("minus/MCtruthPr"), part.pt(), part.eta()); registryMCtruth.fill(HIST("minus/MCtruthPrPt"), part.pt()); } @@ -1166,7 +1177,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { const auto& mcpart = mcparts.iteratorAt(mcPartId); // if (part.partType() == aod::femtouniverseparticle::ParticleType::kV0) { - if (mcpart.pdgMCTruth() == 3122) { + if (mcpart.pdgMCTruth() == kLambda0) { const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); /// Daughters that do not pass this condition are not selected @@ -1181,7 +1192,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { registryMCreco.fill(HIST("plus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // lambda pion child } } - } else if (mcpart.pdgMCTruth() == -3122) { + } else if (mcpart.pdgMCTruth() == -kLambda0) { const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); /// Daughters that do not pass this condition are not selected @@ -1200,10 +1211,10 @@ struct FemtoUniversePairTaskTrackV0Helicity { } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { if (part.sign() > 0) { registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == 211 && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiPlus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == 2212 && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == kProton && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); } @@ -1211,10 +1222,10 @@ struct FemtoUniversePairTaskTrackV0Helicity { if (part.sign() < 0) { registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == -211 && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiMinus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == -2212 && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == -kProton && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); } From 43fb9aaf9d22aedf4a770b68676813fbad8d9023 Mon Sep 17 00:00:00 2001 From: Stefano Cannito <143754257+scannito@users.noreply.github.com> Date: Mon, 4 May 2026 17:56:04 +0200 Subject: [PATCH 031/449] [PWGLF] Possible change in MC trigger definition (#16085) --- .../Strangeness/phiStrangeCorrelator.cxx | 104 +++++++++++------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx index 87df3768a0e..87baf4ea3c4 100644 --- a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx +++ b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx @@ -96,6 +96,8 @@ struct PhiMesonCandProducer { Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; } phiConfigs; + Configurable trueGenPhi{"trueGenPhi", false, "Phi trigger in MC Collisions: false - gen K+K- pair, true - gen phi meson"}; + // Configurables on phi pT bins Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; @@ -315,28 +317,41 @@ struct PhiMesonCandProducer { void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) { - for (const auto& mcParticle1 : mcParticles) { - if (!mcParticle1.isPhysicalPrimary() || std::abs(mcParticle1.eta()) > trackConfigs.etaMax) - continue; - - for (const auto& mcParticle2 : mcParticles) { - if (!mcParticle2.isPhysicalPrimary() || std::abs(mcParticle2.eta()) > trackConfigs.etaMax) + if (trueGenPhi) { + for (const auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.pdgCode()) != o2::constants::physics::Pdg::kPhi) + continue; + if (mcParticle.pt() < phiConfigs.minPhiPt) + continue; + if (std::abs(mcParticle.y()) > phiConfigs.cfgYAcceptance) continue; - if (!(mcParticle1.pdgCode() == PDG_t::kKPlus && mcParticle2.pdgCode() == PDG_t::kKMinus) && - !(mcParticle1.pdgCode() == PDG_t::kKMinus && mcParticle2.pdgCode() == PDG_t::kKPlus)) + phimesonCandidatesMcGen(mcCollision.globalIndex(), 0, mcParticle.pt(), mcParticle.y(), mcParticle.phi()); + } + } else { + for (const auto& mcParticle1 : mcParticles) { + if (!mcParticle1.isPhysicalPrimary() || std::abs(mcParticle1.eta()) > trackConfigs.etaMax) continue; - ROOT::Math::PxPyPzMVector genKPair = recMother(mcParticle1, mcParticle2, massKa, massKa); + for (const auto& mcParticle2 : mcParticles) { + if (!mcParticle2.isPhysicalPrimary() || std::abs(mcParticle2.eta()) > trackConfigs.etaMax) + continue; - if (genKPair.Pt() < phiConfigs.minPhiPt) - continue; - if (genKPair.M() > phiConfigs.maxMPhi) - continue; - if (std::abs(genKPair.Rapidity()) > phiConfigs.cfgYAcceptance) - continue; + if (!(mcParticle1.pdgCode() == PDG_t::kKPlus && mcParticle2.pdgCode() == PDG_t::kKMinus) && + !(mcParticle1.pdgCode() == PDG_t::kKMinus && mcParticle2.pdgCode() == PDG_t::kKPlus)) + continue; + + ROOT::Math::PxPyPzMVector genKPair = recMother(mcParticle1, mcParticle2, massKa, massKa); + + if (genKPair.Pt() < phiConfigs.minPhiPt) + continue; + if (genKPair.M() > phiConfigs.maxMPhi) + continue; + if (std::abs(genKPair.Rapidity()) > phiConfigs.cfgYAcceptance) + continue; - phimesonCandidatesMcGen(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); + phimesonCandidatesMcGen(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); + } } } } @@ -546,6 +561,7 @@ struct PionTrackProducer { // Configurable forceTOF{"forceTOF", false, "force the TOF signal for the PID"}; Configurable tofPIDThreshold{"tofPIDThreshold", 0.5, "minimum pT after which TOF PID is applicable"}; Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID rejection, kaon, proton"}; + Configurable applyElRejection{"applyElRejection", false, "Apply or not the electron rejection"}; Configurable> pidRangeTPCEl{"pidRangeTPCEl", {-3.0f, 5.0f}, "nSigma TPC range for electrons"}; Configurable pidTPCMaxHadrons{"pidTPCMaxHadrons", 3.0f, "maximum nSigma TPC for hadrons"}; Configurable pidTOFMaxHadrons{"pidTOFMaxHadrons", 3.0f, "maximum nSigma TOF for hadrons"}; @@ -632,18 +648,20 @@ struct PionTrackProducer { template bool pidHypothesesRejection(const T& track) { - // Electron rejection - auto nSigmaTPCEl = aod::pidutils::tpcNSigma(o2::track::PID::Electron, track); - - if (nSigmaTPCEl > trackConfigs.pidRangeTPCEl->first && nSigmaTPCEl < trackConfigs.pidRangeTPCEl->second) { - auto nSigmaTPCPi = aod::pidutils::tpcNSigma(o2::track::PID::Pion, track); - auto nSigmaTPCKa = aod::pidutils::tpcNSigma(o2::track::PID::Kaon, track); - auto nSigmaTPCPr = aod::pidutils::tpcNSigma(o2::track::PID::Proton, track); - - if (std::abs(nSigmaTPCPi) > trackConfigs.pidTPCMaxHadrons && - std::abs(nSigmaTPCKa) > trackConfigs.pidTPCMaxHadrons && - std::abs(nSigmaTPCPr) > trackConfigs.pidTPCMaxHadrons) { - return false; + // Electron rejection (if enabled) + if (trackConfigs.applyElRejection) { + auto nSigmaTPCEl = aod::pidutils::tpcNSigma(o2::track::PID::Electron, track); + + if (nSigmaTPCEl > trackConfigs.pidRangeTPCEl->first && nSigmaTPCEl < trackConfigs.pidRangeTPCEl->second) { + auto nSigmaTPCPi = aod::pidutils::tpcNSigma(o2::track::PID::Pion, track); + auto nSigmaTPCKa = aod::pidutils::tpcNSigma(o2::track::PID::Kaon, track); + auto nSigmaTPCPr = aod::pidutils::tpcNSigma(o2::track::PID::Proton, track); + + if (std::abs(nSigmaTPCPi) > trackConfigs.pidTPCMaxHadrons && + std::abs(nSigmaTPCKa) > trackConfigs.pidTPCMaxHadrons && + std::abs(nSigmaTPCPr) > trackConfigs.pidTPCMaxHadrons) { + return false; + } } } @@ -806,6 +824,8 @@ struct EventSelectionProducer { Configurable maxMPhiSignal{"maxMPhiSignal", 1.029f, "Upper limits on Phi mass for signal extraction"}; } phiConfigs; + Configurable withTrueGenPhi{"withTrueGenPhi", false, "Require the presence of a true generated phi meson in the event"}; + // Defining the type of the collisions for data and MC using SelCollisions = soa::Join; using SimCollisions = soa::Join; @@ -911,23 +931,27 @@ struct EventSelectionProducer { template bool eventHasPhi(const T1& collision, const T2& phiCandidates) { - uint16_t nPhi{0}; + if (withTrueGenPhi) { + if (phiCandidates.size() < 1) + return false; + } else { + uint16_t nPhi{0}; - for (const auto& phiCand : phiCandidates) { + for (const auto& phiCand : phiCandidates) { + if (phiCand.inMassRegion(phiConfigs.minMPhiSignal, phiConfigs.maxMPhiSignal)) + nPhi++; - if (phiCand.inMassRegion(phiConfigs.minMPhiSignal, phiConfigs.maxMPhiSignal)) - nPhi++; + // histos.fill(HIST("hEta"), track1.eta()); + // histos.fill(HIST("hNsigmaKaonTPC"), track1.tpcInnerParam(), track1.tpcNSigmaKa()); + // histos.fill(HIST("hNsigmaKaonTOF"), track1.tpcInnerParam(), track1.tofNSigmaKa()); + // histos.fill(HIST("h2DauTracksPhiDCAxy"), track1.pt(), track1.dcaXY()); + // histos.fill(HIST("h2DauTracksPhiDCAz"), track1.pt(), track1.dcaZ()); + } - // histos.fill(HIST("hEta"), track1.eta()); - // histos.fill(HIST("hNsigmaKaonTPC"), track1.tpcInnerParam(), track1.tpcNSigmaKa()); - // histos.fill(HIST("hNsigmaKaonTOF"), track1.tpcInnerParam(), track1.tofNSigmaKa()); - // histos.fill(HIST("h2DauTracksPhiDCAxy"), track1.pt(), track1.dcaXY()); - // histos.fill(HIST("h2DauTracksPhiDCAz"), track1.pt(), track1.dcaZ()); + if (nPhi == 0) + return false; } - if (nPhi == 0) - return false; - float multPercentile{0.0f}; if constexpr (!isMC) { From c891bb33109bf2f3796f5ff5913a8ffb649a41cd Mon Sep 17 00:00:00 2001 From: a-m-andrushko <96832230+a-m-andrushko@users.noreply.github.com> Date: Mon, 4 May 2026 17:57:59 +0200 Subject: [PATCH 032/449] [PWGCF] FemtoUniverse -- Add hInvMassK0Short to helicity analysis. (#16102) From 177780bbb54c82fbc9c290e6a7bd88c7d4f6cee0 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 4 May 2026 21:16:10 +0200 Subject: [PATCH 033/449] [PWGEM/Dilepton] update taggingHFE.cxx for TOF (#16105) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 4 +- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 170 +++++++++++++++++++----- 2 files changed, 143 insertions(+), 31 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index bc76880a9ec..5cfdd002928 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -248,7 +248,9 @@ DECLARE_SOA_COLUMN(FoundCommonMother, foundCommonMother, bool); //! decay length DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! emmllhpair::EMMLLeptonId, track::Signed1Pt, track::Eta, - track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, + track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, + pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, + pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, emmllhpair::Lxyz, emmllhpair::LxyzSigma, emmllhpair::Lxy, emmllhpair::LxySigma, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 7bb44ccc588..aeb99b84873 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -45,12 +45,11 @@ #include #include #include +#include #include #include #include -// #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) -// #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #include #include @@ -78,7 +78,7 @@ struct taggingHFE { using MyTracks = soa::Join; + aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFbeta, aod::TOFSignal, aod::TOFEvTime>; using MyTracksWithMCLabel = soa::Join; // using MyV0s = soa::Join; @@ -101,6 +101,7 @@ struct taggingHFE { Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgPdgLepton{"cfgPdgLepton", 11, "pdg code of desired lepton: 11 or 13"}; Configurable cfgDownSampling{"cfgDownSampling", 1.1, "down sampling for fake matches"}; + Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", true, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; struct : ConfigurableGroup { std::string prefix = "dcaFitterGroup_eK"; @@ -122,7 +123,7 @@ struct taggingHFE { struct : ConfigurableGroup { std::string prefix = "electronCut"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.4, "min pT for single track"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; @@ -167,7 +168,6 @@ struct taggingHFE { Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; Configurable requirePiKa{"requirePiKa", false, "require hadron to be pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. - Configurable requireKa{"requireKa", false, "require hadron to be kaon"}; // Mostly, kaon is involved in semileptonic decay of charm hadrons. } hadronCut; struct : ConfigurableGroup { @@ -272,6 +272,7 @@ struct taggingHFE { } lCPairCut; o2::aod::rctsel::RCTFlagsChecker rctChecker; + Service mTOFResponse; HistogramRegistry fRegistry{"fRegistry"}; static constexpr std::string_view hadron_names[6] = {"LF/", "Jpsi/", "D0/", "Dpm/", "Ds/", "Lc/"}; @@ -279,7 +280,7 @@ struct taggingHFE { static constexpr std::string_view hTypes[4] = {"findable/", "correct/", "fake/", "miss/"}; static constexpr std::string_view promptTypes[2] = {"prompt/", "nonprompt/"}; - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& initContext) { // if (doprocessSA && doprocessTTCA) { // LOGF(fatal, "Cannot enable doprocessWithoutFTTCA and doprocessWithFTTCA at the same time. Please choose one."); @@ -291,6 +292,9 @@ struct taggingHFE { ccdb->setFatalWhenNull(false); rctChecker.init(eventCut.cfgRCTLabel.value, eventCut.cfgCheckZDC.value, eventCut.cfgTreatLimitedAcceptanceAsBad.value); + LOGF(info, "intializing TOFResponse"); + mTOFResponse->initSetup(ccdb, initContext); + std::random_device seed_gen; engine = std::mt19937(seed_gen()); dist01 = std::uniform_real_distribution(0.0f, 1.0f); @@ -452,21 +456,15 @@ struct taggingHFE { fRegistry.add("Cascade/hMassOmega", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", kTH1F, {{100, 1.62, 1.72}}, false); } - template - bool isKaon(TTrack const& track) - { - bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; - bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; - return is_ka_included_TPC && is_ka_included_TOF; - } - - template - bool isKaon_or_isPion(TTrack const& track) + template + bool isKaon_or_isPion(TCollision const& collision, TTrack const& track) { + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; - bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; + bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < hadronCut.cfg_max_TOFNsigmaKa) : true; bool is_pi_included_TPC = hadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < hadronCut.cfg_max_TPCNsigmaPi; - bool is_pi_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < hadronCut.cfg_max_TOFNsigmaPi) : true; + bool is_pi_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < hadronCut.cfg_max_TOFNsigmaPi) : true; return (is_ka_included_TPC && is_ka_included_TOF) || (is_pi_included_TPC && is_pi_included_TOF); } @@ -479,6 +477,14 @@ struct taggingHFE { return is_pi_included_TPC && is_pi_included_TOF; } + template + bool isKaon(TTrack const& track) + { + bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; + bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; + return is_ka_included_TPC && is_ka_included_TOF; + } + template bool isProton(TTrack const& track) { @@ -559,8 +565,8 @@ struct taggingHFE { return true; } - template - bool isSelectedHadron(TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) + template + bool isSelectedHadron(TCollision const& collision, TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) { if (!track.hasITS() || !track.hasTPC()) { return false; @@ -614,11 +620,7 @@ struct taggingHFE { return false; } - if (hadronCut.requirePiKa && !isKaon_or_isPion(track)) { - return false; - } - - if (hadronCut.requireKa && !isKaon(track)) { + if (hadronCut.requirePiKa && !isKaon_or_isPion(collision, track)) { return false; } @@ -827,6 +829,87 @@ struct taggingHFE { return true; } + std::map, float> mapTOFNsigmaPiReassociated; // map pair(collisionId, trackId) -> tof n sigma pi + std::map, float> mapTOFNsigmaKaReassociated; // map pair(collisionId, trackId) -> tof n sigma ka + std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta + std::unordered_map mapCollisionTime; + std::unordered_map mapCollisionTimeError; + + template + void calculateTOFNSigmaWithReassociation(TCollisions const& collisions, TBCs const&, TTracks const& tracks, TTrackAssoc const& trackIndices) + { + if (useTOFNSigmaDeltaBC) { + if constexpr (withTTCA) { + for (const auto& collision : collisions) { + if (mapCollisionTime.find(collision.globalIndex()) == mapCollisionTime.end()) { + continue; + } + auto bcCollision = collision.template bc_as(); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + + if (track.hasTOF() && track.has_collision()) { // TTCA may use orphan tracks. + auto bcTrack = track.template collision_as().template bc_as(); + float tofNSigmaPi = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + float tofNSigmaKa = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + float beta = track.length() / (track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()) - mapCollisionTime[collision.globalIndex()]) / (TMath::C() * 1e+2 * 1e-12); + mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaPi; + mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaKa; + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = beta; + } else { + mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + } else { + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + } else { + if constexpr (withTTCA) { + for (const auto& collision : collisions) { + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } // end of track loop + } // end of collision loop + } else { + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + } + } + template void runPairing(TBCs const&, TCollisions const& collisions, TTracks const& tracks, TTrackAssoc const& trackIndices, TV0s const& v0s, TCascades const& cascades, TMCCollisions const&, TMCParticles const& mcParticles) { @@ -898,7 +981,7 @@ struct taggingHFE { fRegistry.fill(HIST("Electron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); fRegistry.fill(HIST("Electron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); - fRegistry.fill(HIST("Electron/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Electron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); if (track.sign() > 0) { // positron positronIds.emplace_back(trackId.trackId()); } else { // electron @@ -912,10 +995,10 @@ struct taggingHFE { dcaXY = mDcaInfoCov.getY(); dcaZ = mDcaInfoCov.getZ(); - if (isSelectedHadron(track, trackParCov, dcaXY, dcaZ)) { // electrons can be included in hadron sample. + if (isSelectedHadron(collision, track, trackParCov, dcaXY, dcaZ)) { // electrons can be included in hadron sample. fRegistry.fill(HIST("Hadron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); fRegistry.fill(HIST("Hadron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); - fRegistry.fill(HIST("Hadron/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Hadron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); if (track.sign() > 0) { // K+ kaonPlusIds.emplace_back(trackId.trackId()); } else { // K- @@ -1070,9 +1153,13 @@ struct taggingHFE { } } + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaKa(), kaon.tofNSigmaKa(), + kaon.tpcNSigmaPi(), tofNSigmaPi, + kaon.tpcNSigmaKa(), tofNSigmaKa, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -1386,9 +1473,13 @@ struct taggingHFE { } } + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaKa(), kaon.tofNSigmaKa(), + kaon.tpcNSigmaPi(), tofNSigmaPi, + kaon.tpcNSigmaKa(), tofNSigmaKa, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -1814,8 +1905,26 @@ struct taggingHFE { void processMC(FilteredMyCollisionsWithMCLabel const& collisions, aod::BCsWithTimestamps const& bcs, MyTracksWithMCLabel const& tracks, aod::TrackAssoc const& trackIndices, filteredV0s const& v0s, filteredMyCascades const& cascades, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + // LOGF(info, "track.collisionId() = %d, track.tofEvTime() = %f, track.tofEvTimeErr() = %f", track.collisionId(), track.tofEvTime(), track.tofEvTimeErr()); + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); + runPairing(bcs, collisions, tracks, trackIndices, v0s, cascades, mcCollisions, mcParticles); runGen(mcCollisions, mcParticles); + + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaPiReassociated.clear(); + mapTOFNsigmaKaReassociated.clear(); + mapTOFBetaReassociated.clear(); } PROCESS_SWITCH(taggingHFE, processMC, "process with TTCA", true); @@ -1824,5 +1933,6 @@ struct taggingHFE { }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"tagging-hfe"})}; } From 52f73faa489a13e555f7e29d4cf58a3ab848281d Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Mon, 4 May 2026 21:23:30 +0200 Subject: [PATCH 034/449] [PWGDQ] fill event information in runMCGen (#16101) --- PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index 24e09701e6f..59d0d15930d 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -2017,7 +2017,7 @@ struct AnalysisSameEventPairing { PresliceUnsorted perReducedMcEvent = aod::mcparticle::mcCollisionId; // template - template + template void runMCGen(TEvents const& events, TEventsMC const& mcEvents, McParticles const& mcTracks) { cout << "AnalysisSameEventPairing::runMCGen() called" << endl; @@ -2053,7 +2053,11 @@ struct AnalysisSameEventPairing { eFromJpsiMcParticleIndices.clear(); auto mcCollisionGlobalIndex = event.mcCollisionId(); - // auto mcEvent = mcEvents.rawIteratorAt(mcCollisionGlobalIndex); + auto mcEvent = mcEvents.rawIteratorAt(mcCollisionGlobalIndex); + + // fill event information + VarManager::FillEvent(event); + VarManager::FillEvent(mcEvent); auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, mcCollisionGlobalIndex); groupedMCTracks.bindInternalIndicesTo(&mcTracks); @@ -2161,7 +2165,7 @@ struct AnalysisSameEventPairing { { cout << "AnalysisSameEventPairing::processBarrelOnly() called" << endl; runSameEventPairing(events, bcs, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); - runMCGen(events, mcEvents, mcTracks); + runMCGen(events, mcEvents, mcTracks); cout << "AnalysisSameEventPairing::processBarrelOnly() completed" << endl; } @@ -2171,7 +2175,7 @@ struct AnalysisSameEventPairing { { cout << "AnalysisSameEventPairing::processBarrelPbPbOnly() called" << endl; runSameEventPairing(events, bcs, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); - runMCGen(events, mcEvents, mcTracks); + runMCGen(events, mcEvents, mcTracks); cout << "AnalysisSameEventPairing::processBarrelPbPbOnly() completed" << endl; } From d1db7c7dab9981ea059513373a5e5b973ddf212f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Mon, 4 May 2026 21:28:12 +0200 Subject: [PATCH 035/449] [PWGLF] Fix includes (#16093) --- PWGLF/TableProducer/Nuspex/photonDeuteron.cxx | 12 +++++++++- .../Strangeness/sigmaHadCorr.cxx | 1 + .../Tasks/GlobalEventProperties/dndetaHi.cxx | 23 +++++++++---------- .../Tasks/GlobalEventProperties/studyPnch.cxx | 2 -- .../Tasks/Strangeness/cascpostprocessing.cxx | 19 +++++++++------ .../Strangeness/strangenessInJetsIons.cxx | 1 + 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/photonDeuteron.cxx b/PWGLF/TableProducer/Nuspex/photonDeuteron.cxx index 496eb51914b..a0d5d894398 100644 --- a/PWGLF/TableProducer/Nuspex/photonDeuteron.cxx +++ b/PWGLF/TableProducer/Nuspex/photonDeuteron.cxx @@ -21,12 +21,22 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include #include +#include #include +#include +#include #include using namespace o2; diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index 1884caad6a7..20777c211c3 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/PWGLF/Tasks/GlobalEventProperties/dndetaHi.cxx b/PWGLF/Tasks/GlobalEventProperties/dndetaHi.cxx index f91fccf9775..2da575aed40 100644 --- a/PWGLF/Tasks/GlobalEventProperties/dndetaHi.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/dndetaHi.cxx @@ -24,20 +24,19 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/InitContext.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include #include diff --git a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx index 60917e919a5..0d56f859b1f 100644 --- a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx @@ -15,8 +15,6 @@ /// \author Abhi Modak (abhi.modak@cern.ch), Lucas José (lucas.jose.franco.da.silva@cern.ch) /// \since September 10, 2025 -#include "PWGLF/DataModel/LFStrangenessTables.h" - #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" diff --git a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx index c65c6e2041c..94dafc57939 100644 --- a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx +++ b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx @@ -16,17 +16,22 @@ /// \modified by Roman Nepeivoda (roman.nepeivoda@cern.ch) /// \since June 1, 2023 -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/cascqaanalysis.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include - +#include +#include +#include +#include +#include +#include + +#include +#include #include +#include + +#include #include diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index ffb3b001f4d..477b1138515 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -63,6 +63,7 @@ #include #include +#include #include #include #include From a956b56daa5e1f65198e01fcfbd21a9b7ddf5341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Mon, 4 May 2026 21:29:08 +0200 Subject: [PATCH 036/449] [PWGLF,PWGMM] Fix includes (#16094) --- PWGMM/Mult/Tasks/mftReassociationValidation.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx index ea99e6b354f..b65d22bde62 100644 --- a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx +++ b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx @@ -39,6 +39,7 @@ #include #include #include +#include #include #include From f749e6a081011b91497eacdbb0d1c9ee6a8722b4 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Tue, 5 May 2026 01:10:08 +0530 Subject: [PATCH 037/449] [PWGCF] Fix O2-linter errors (#16104) --- .../Tasks/v0ptHadPiKaProt.cxx | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index 5e3bf2b9d14..ab0452aac82 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -36,7 +36,6 @@ #include #include -#include "TDatabasePDG.h" #include #include #include @@ -71,6 +70,7 @@ struct V0ptHadPiKaProt { o2::aod::ITSResponse itsResponse; // Connect to ccdb Service ccdb; + Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPath{"ccdbPath", "Users/s/swati/PhiWeight", "CCDB path to ccdb object containing phi weight in a 3D histogram"}; @@ -114,7 +114,7 @@ struct V0ptHadPiKaProt { Configurable cfgnSigmaOtherParticles{"cfgnSigmaOtherParticles", 3.0f, "PID nSigma cut to remove other particles (default:3)"}; Configurable cfgnSigmaCutTPC{"cfgnSigmaCutTPC", 2.0f, "PID nSigma cut for TPC"}; Configurable cfgnSigmaCutTOF{"cfgnSigmaCutTOF", 2.0f, "PID nSigma cut for TOF"}; - Configurable cfgUseNewSeperationPid{"cfgUseNewSeperationPid", true, "Use seperation based PID cuts (NEW)"}; + Configurable cfgUseNewSeperationPid{"cfgUseNewSeperationPid", false, "Use seperation based PID cuts (NEW)"}; Configurable cfgnSigmaCutTPCHigherPt{"cfgnSigmaCutTPCHigherPt", 2.0f, "PID nSigma cut for TPC at higher pt"}; Configurable cfgnSigmaCutTOFHigherPt{"cfgnSigmaCutTOFHigherPt", 2.0f, "PID nSigma cut for TOF at higher pt"}; Configurable cfgnSigmaSeperationCut{"cfgnSigmaSeperationCut", 3.5f, "PID nSigma of other species must be greater than the vale"}; @@ -209,7 +209,7 @@ struct V0ptHadPiKaProt { HistogramRegistry histosAnalysis{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; std::vector>> subSample; std::vector>> subSampleV02; - std::vector>> subSampleV02_weighted; + std::vector>> subSampleV02weighted; TRandom3* funRndm = new TRandom3(0); // Phi weight histograms initialization @@ -418,11 +418,11 @@ struct V0ptHadPiKaProt { // initial array subSample.resize(cfgNSubsample); subSampleV02.resize(cfgNSubsample); - subSampleV02_weighted.resize(cfgNSubsample); + subSampleV02weighted.resize(cfgNSubsample); for (int i = 0; i < cfgNSubsample; i++) { subSample[i].resize(20); subSampleV02[i].resize(9); - subSampleV02_weighted[i].resize(9); + subSampleV02weighted[i].resize(9); } for (int i = 0; i < cfgNSubsample; i++) { subSample[i][0] = std::get>(histos.add(Form("subSample_%d/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); @@ -460,15 +460,15 @@ struct V0ptHadPiKaProt { subSampleV02[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); if (cfgV02WeightedFill) { - subSampleV02_weighted[i][0] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_XY_weighted", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); - subSampleV02_weighted[i][1] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_XYZ_weighted_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][2] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_Z_weighted_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][3] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_XYZ_weighted_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][4] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_Z_weighted_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][5] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_XYZ_weighted_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][6] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_Z_weighted_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_XYZ_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02_weighted[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02_weighted_%d/Prof_Z_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][0] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XY_weighted", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSampleV02weighted[i][1] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XYZ_weighted_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][2] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_Z_weighted_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][3] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XYZ_weighted_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][4] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_Z_weighted_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][5] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XYZ_weighted_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][6] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_Z_weighted_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XYZ_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weighted[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_Z_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); } } @@ -509,6 +509,7 @@ struct V0ptHadPiKaProt { if (cfgIsMC) { // MC event counts histos.add("MCGenerated/hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); + histos.add("MCGenerated/hCentgen", "MC generated centrality", kTH1F, {centAxis}); histos.add("MCGenerated/hPtEtaPhiCharged", "MC charged particles' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCGenerated/hPtEtaPhiPion", "MC charged pions' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); histos.add("MCGenerated/hPtEtaPhiKaon", "MC charged kaons' pt, eta, phi", kTH3D, {ptAxis, {100, 0., o2::constants::math::TwoPI}, {100, -2.01, 2.01}}); @@ -1017,19 +1018,19 @@ struct V0ptHadPiKaProt { if (!mcParticle.has_mcCollision()) continue; - // charged check - auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); - if (!pdgEntry) - continue; - if (pdgEntry->Charge() == 0) - continue; + auto pdgcode = std::abs(mcParticle.pdgCode()); + if (!(pdgcode == PDG_t::kPiPlus || + pdgcode == PDG_t::kKPlus || + pdgcode == PDG_t::kProton || + pdgcode == PDG_t::kElectron || + pdgcode == PDG_t::kMuonMinus)) { + continue; // skip this track + } if (mcParticle.isPhysicalPrimary()) { if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPtUpper) && (std::abs(mcParticle.eta()) < cfgCutEta)) { histos.fill(HIST("MCGenerated/hPtEtaPhiCharged_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); - auto pdgcode = std::abs(mcParticle.pdgCode()); - if (pdgcode == PDG_t::kPiPlus) histos.fill(HIST("MCGenerated/hPtEtaPhiPion_gen"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); @@ -1096,19 +1097,19 @@ struct V0ptHadPiKaProt { if (!mcParticle.has_mcCollision()) continue; - // charged check - auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); - if (!pdgEntry) - continue; - if (pdgEntry->Charge() == 0) - continue; + auto pdgcode = std::abs(mcParticle.pdgCode()); + if (!(pdgcode == PDG_t::kPiPlus || + pdgcode == PDG_t::kKPlus || + pdgcode == PDG_t::kProton || + pdgcode == PDG_t::kElectron || + pdgcode == PDG_t::kMuonMinus)) { + continue; // skip this track + } if (mcParticle.isPhysicalPrimary()) { if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPtUpper) && (std::abs(mcParticle.eta()) < cfgCutEta)) { histos.fill(HIST("MCGenerated/hPtEtaPhiCharged"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); - auto pdgcode = std::abs(mcParticle.pdgCode()); - if (pdgcode == PDG_t::kPiPlus) histos.fill(HIST("MCGenerated/hPtEtaPhiPion"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi()); @@ -1552,7 +1553,7 @@ struct V0ptHadPiKaProt { if (cfgV02WeightedFill) { histos.get(HIST("Prof_XY_weighted"))->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); - subSampleV02_weighted[sampleIndex][0]->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); + subSampleV02weighted[sampleIndex][0]->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); } // hadrons for (int i = 0; i < cfgNbinsV02pt; i++) { @@ -1567,8 +1568,8 @@ struct V0ptHadPiKaProt { if (cfgV02WeightedFill) { histos.get(HIST("Prof_XYZ_weighted_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinC)); histos.get(HIST("Prof_Z_weighted_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02_weighted[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinC)); - subSampleV02_weighted[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02weighted[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinC)); + subSampleV02weighted[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); } } @@ -1585,8 +1586,8 @@ struct V0ptHadPiKaProt { if (cfgV02WeightedFill) { histos.get(HIST("Prof_XYZ_weighted_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinC)); histos.get(HIST("Prof_Z_weighted_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02_weighted[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinC)); - subSampleV02_weighted[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02weighted[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinC)); + subSampleV02weighted[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); } } @@ -1603,8 +1604,8 @@ struct V0ptHadPiKaProt { if (cfgV02WeightedFill) { histos.get(HIST("Prof_XYZ_weighted_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinC)); histos.get(HIST("Prof_Z_weighted_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02_weighted[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinC)); - subSampleV02_weighted[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02weighted[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinC)); + subSampleV02weighted[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); } } @@ -1621,8 +1622,8 @@ struct V0ptHadPiKaProt { if (cfgV02WeightedFill) { histos.get(HIST("Prof_XYZ_weighted_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinC)); histos.get(HIST("Prof_Z_weighted_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02_weighted[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinC)); - subSampleV02_weighted[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02weighted[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinC)); + subSampleV02weighted[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); } } } From 6eebfd523c0c25787f54525d749fd6cca0c36eea Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 4 May 2026 21:40:16 +0200 Subject: [PATCH 038/449] [PWGEM/Dilepton] add TOFif option in taggingHFE.cxx (#16107) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index aeb99b84873..6f1f36e6fb1 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -168,6 +168,7 @@ struct taggingHFE { Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; Configurable requirePiKa{"requirePiKa", false, "require hadron to be pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. + Configurable applyTOFif{"applyTOFif", false, "apply TOFif for pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. } hadronCut; struct : ConfigurableGroup { @@ -465,6 +466,10 @@ struct taggingHFE { bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < hadronCut.cfg_max_TOFNsigmaKa) : true; bool is_pi_included_TPC = hadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < hadronCut.cfg_max_TPCNsigmaPi; bool is_pi_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < hadronCut.cfg_max_TOFNsigmaPi) : true; + if (!hadronCut.applyTOFif) { + is_ka_included_TOF = true; + is_pi_included_TOF = true; + } return (is_ka_included_TPC && is_ka_included_TOF) || (is_pi_included_TPC && is_pi_included_TOF); } From 6847aa43523ec8df9ecd9e09f9f287240e11dc29 Mon Sep 17 00:00:00 2001 From: amikals <111276362+amikals@users.noreply.github.com> Date: Mon, 4 May 2026 22:11:18 +0200 Subject: [PATCH 039/449] [PWGDQ] Fill StoredReducedEvent for JE framework (#16053) Co-authored-by: Andreas Mikalsen --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 16 +++++++++++++++- PWGDQ/Tasks/tableReader_withAssoc.cxx | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 608363e12c0..df76d33e777 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -275,6 +275,7 @@ void PrintBitMap(TMap map, int nbits) struct AnalysisEventSelection { Produces eventSel; Produces hash; + Produces JetEvents; OutputObj fOutputList{"output"}; Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; @@ -496,13 +497,26 @@ struct AnalysisEventSelection { runEventSelection(events, mcEvents); publishSelections(events); } - + void processFillEvents(MyEvents const& events) // Used to forward the event table from tablemaker, typical use for now is jet analysis. + { + for (auto& event : events) { + JetEvents(event.tag_raw(), + event.runNumber(), + event.posX(), + event.posY(), + event.posZ(), + event.numContrib(), + event.collisionTime(), + event.collisionTimeRes()); + } + } void processDummy(MyEvents&) { // do nothing } PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); + PROCESS_SWITCH(AnalysisEventSelection, processFillEvents, "Fill storedReducedEvents table for use in JE framework", false); PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", true); }; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 625fbd77440..d5bcfc56797 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -284,6 +284,7 @@ struct AnalysisEventSelection { Produces eventSel; Produces hash; + Produces JetEvents; OutputObj fOutputList{"output"}; // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) @@ -577,6 +578,19 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processFillEvents(MyEventsBasic const& events) // Used to forward the event table from tablemaker, typical use for now is jet analysis. + { + for (auto& event : events) { + JetEvents(event.tag_raw(), + event.runNumber(), + event.posX(), + event.posY(), + event.posZ(), + event.numContrib(), + event.collisionTime(), + event.collisionTimeRes()); + } + } void processDummy(MyEventsBasic&) { // do nothing @@ -589,6 +603,7 @@ struct AnalysisEventSelection { PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraZdc, "Run event selection on DQ skimmed events, with mult extra and ZDC", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraZdcFit, "Run event selection on DQ skimmed events, with mult extra, ZDC and FIT", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithQvectorCentr, "Run event selection on DQ skimmed events, with Q-vector", false); + PROCESS_SWITCH(AnalysisEventSelection, processFillEvents, "Fill storedReducedEvents table for use in JE framework", false); PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", true); }; From c960bc6ee6e280005dd96eb09e0c564f19db338a Mon Sep 17 00:00:00 2001 From: Katarzyna <116073883+kgwizdzi@users.noreply.github.com> Date: Mon, 4 May 2026 23:33:41 +0200 Subject: [PATCH 040/449] [PWGCF] FU: D0 task update (#16108) --- .../Tasks/femtoUniversePairTaskTrackD0.cxx | 62 +++++++++++-------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx index 3166d98990d..297bdb03f73 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx @@ -162,7 +162,6 @@ struct FemtoUniversePairTaskTrackD0 { struct : o2::framework::ConfigurableGroup { Configurable confMaxProbMlClass1Bg{"confMaxProbMlClass1Bg", 0.4, "ML: max prob. that D0/D0bar cand. is from the backgound"}; Configurable confMinProbMlClass2Prompt{"confMinProbMlClass2Prompt", 0.05, "ML: min prob. that D0/D0bar cand. is prompt"}; - Configurable confMaxProbMlClass3NonPrompt{"confMaxProbMlClass3NonPrompt", 1.0, "ML: max prob. that D0/D0bar cand. is non-prompt"}; Configurable confClass1BgProbStep{"confClass1BgProbStep", 0.05, "ML: prob. step for score class 1"}; Configurable confClass1BgProbStart{"confClass1BgProbStart", 0.05, "ML: starting prob. value in optimization for score class 1"}; Configurable confClass2PromptProbStep{"confClass2PromptProbStep", 0.05, "ML: prob. step for score class 2 - prompt"}; @@ -175,6 +174,8 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confChooseD0trackCorr{"confChooseD0trackCorr", 0, "If 0 correlations with D0s, if 1 with D0bars"}; // Correlated background for D0/D0bar candidates Configurable fillCorrBkgs{"fillCorrBkgs", false, "Fill histograms with correlated background candidates"}; + // Configurable to enable BDT vs pT histograms for D0/D0bar at MC Reco level + Configurable fillBDTvsPt{"fillBDTvsPt", false, "Fill BDT vs pT histograms for D0/D0bar candidates"}; // Efficiency Configurable doEfficiencyCorr{"doEfficiencyCorr", false, "Apply efficiency corrections"}; @@ -186,25 +187,25 @@ struct FemtoUniversePairTaskTrackD0 { /// Partitions for particle 2 /// Partition with all D0/D0bar mesons (which pass one and double mass hypothesis) - Partition partsAllDmesons = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > 0.0f) || (aod::femtouniverseparticle::mAntiLambda > 0.0f)) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); + Partition partsAllDmesons = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > 0.0f) || (aod::femtouniverseparticle::mAntiLambda > 0.0f)); /// Partition with D0 mesons only (one and double mass hypothesis) Partition partsAllD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition with D0 mesons only (one mass hypothesis) - Partition partsD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); + Partition partsD0s = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < 0.0f) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition with D0s selected from the side-band (SB) regions (candidates with double mass hypothesis included) Partition partsD0sFromSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition with D0bar mesons only (one and double mass hypothesis) Partition partsAllD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition with D0bar mesons only (one mass hypothesis) - Partition partsD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt); + Partition partsD0bars = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda < 0.0f) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition with D0bars selected from the side-band (SB) regions (candidates with double mass hypothesis included) Partition partsD0barsFromSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); /// Partition for MC Reco prompt D0/D0bar mesons - Partition partsPromptD0MCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); - Partition partsPromptD0barMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); + Partition partsPromptD0MCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); + Partition partsPromptD0barMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barSignal) && (aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barSignal) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); /// Partition for MC Reco prompt D0/D0bar mesons (sideband candidates) - Partition partsPromptD0MCRecoSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); - Partition partsPromptD0barMCRecoSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::decayVtxX < ConfMlOpt.confMaxProbMlClass1Bg) && (aod::femtouniverseparticle::decayVtxY > ConfMlOpt.confMinProbMlClass2Prompt) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); + Partition partsPromptD0MCRecoSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); + Partition partsPromptD0barMCRecoSB = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kD0)) && ((aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barLeftSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barLeftSB) || (aod::femtouniverseparticle::mAntiLambda > ConfDmesons.minInvMassD0D0barRightSB && aod::femtouniverseparticle::mAntiLambda < ConfDmesons.maxInvMassD0D0barRightSB)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar) && (aod::femtouniverseparticle::tpcNClsFound == ConfDmesons.confD0OriginFlag); // MC Truth D0/D0bar candidates Partition partsD0MCTruth = (aod::femtouniverseparticle::partType == static_cast(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pidCut == static_cast(ConfDmesons.confPDGCodeD0)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); Partition partsD0barMCTruth = (aod::femtouniverseparticle::partType == static_cast(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pidCut == static_cast(ConfDmesons.confPDGCodeD0bar)) && (aod::femtouniverseparticle::pt > ConfDmesons.confMinPtD0D0bar) && (aod::femtouniverseparticle::pt < ConfDmesons.confMaxPtD0D0bar); @@ -267,9 +268,8 @@ struct FemtoUniversePairTaskTrackD0 { FemtoUniverseDetaDphiStar pairCloseRejection; FemtoUniverseSoftPionRemoval softPionRemoval; FemtoUniverseTrackSelection trackCuts; - // Axes for BDT score classes' histograms + // Axis for BDT score classes' histograms AxisSpec axisBdtScore{100, 0.f, 1.f}; - AxisSpec axisSelStatus{2, -0.5f, 1.5f}; /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -300,7 +300,7 @@ struct FemtoUniversePairTaskTrackD0 { // PID for protons bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { - if (mom < ConfTrack.minMomPidTpcTofProton) { + if (mom <= ConfTrack.minMomPidTpcTofProton) { if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaTPCProton) { return true; } else { @@ -318,7 +318,7 @@ struct FemtoUniversePairTaskTrackD0 { bool isProtonNSigmaRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCKa, float nsigmaTOFKa) { - if (mom < ConfTrack.minMomPidTpcTofProton) { + if (mom <= ConfTrack.minMomPidTpcTofProton) { if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaPrRejectPiNsigma) { return true; } else if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaPrRejectKaNsigma) { @@ -338,9 +338,9 @@ struct FemtoUniversePairTaskTrackD0 { } } - bool isKaonNSigmaLF(float mom, float nsigmaTPCKa, float nsigmaTOFKa) + bool isKaonNSigma(float mom, float nsigmaTPCKa, float nsigmaTOFKa) { - if (mom < ConfTrack.minMomPidTpcTofKaon) { + if (mom <= ConfTrack.minMomPidTpcTofKaon) { if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaTPCKaon) { return true; } else { @@ -357,9 +357,9 @@ struct FemtoUniversePairTaskTrackD0 { } } - bool isKaonNSigmaLFRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCPr, float nsigmaTOFPr) + bool isKaonNSigmaRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCPr, float nsigmaTOFPr) { - if (mom < ConfTrack.minMomPidTpcTofKaon) { + if (mom <= ConfTrack.minMomPidTpcTofKaon) { if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaKaRejectPiNsigma) { return true; } else if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaKaRejectPrNsigma) { @@ -381,7 +381,7 @@ struct FemtoUniversePairTaskTrackD0 { bool isPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) { - if (mom < ConfTrack.minMomPidTpcTofPion) { + if (mom <= ConfTrack.minMomPidTpcTofPion) { if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaTPCPion) { return true; } else { @@ -399,7 +399,7 @@ struct FemtoUniversePairTaskTrackD0 { bool isPionNSigmaRejected(float mom, float nsigmaTPCKa, float nsigmaTOFKa, float nsigmaTPCPr, float nsigmaTOFPr) { - if (mom < ConfTrack.minMomPidTpcTofPion) { + if (mom <= ConfTrack.minMomPidTpcTofPion) { if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaPiRejectKaNsigma) { return true; } else if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaPiRejectPrNsigma) { @@ -432,7 +432,7 @@ struct FemtoUniversePairTaskTrackD0 { break; case 321: // Kaon+ case -321: // Kaon- - return isKaonNSigmaLF(mom, nsigmaTPCK, nsigmaTOFK); + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); break; default: return false; @@ -452,7 +452,7 @@ struct FemtoUniversePairTaskTrackD0 { break; case 321: // Kaon+ case -321: // Kaon- - return isKaonNSigmaLFRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCPr, nsigmaTOFPr); + return isKaonNSigmaRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCPr, nsigmaTOFPr); break; default: return false; @@ -527,9 +527,14 @@ struct FemtoUniversePairTaskTrackD0 { registry.add("D0D0bar_doubleMassHypo/hMassVsPtD0bar", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } // Histograms for BDT score classes' check - registry.add("DebugBdt/hBdtScore1VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); - registry.add("DebugBdt/hBdtScore2VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); - registry.add("DebugBdt/hBdtScore3VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hBdtScore1", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + registry.add("DebugBdt/hBdtScore2", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + registry.add("DebugBdt/hBdtScore3", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + if (fillBDTvsPt) { + registry.add("DebugBdtMcReco/hBdtScore1", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + registry.add("DebugBdtMcReco/hBdtScore2", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + registry.add("DebugBdtMcReco/hBdtScore3", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + } if (applyMLOpt) { registry.add("D0D0bar_MLSel/hMassVsPt1", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("D0D0bar_MLSel/hMassVsPt2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -805,9 +810,9 @@ struct FemtoUniversePairTaskTrackD0 { registry.fill(HIST("hPhiD0D0bar"), d0d0bar.phi()); registry.fill(HIST("hEtaD0D0bar"), d0d0bar.eta()); // BDT score classes - registry.fill(HIST("DebugBdt/hBdtScore1VsStatus"), d0d0bar.decayVtxX(), 1); - registry.fill(HIST("DebugBdt/hBdtScore2VsStatus"), d0d0bar.decayVtxY(), 1); - registry.fill(HIST("DebugBdt/hBdtScore3VsStatus"), d0d0bar.decayVtxZ(), 1); + registry.fill(HIST("DebugBdt/hBdtScore1"), d0d0bar.decayVtxX()); + registry.fill(HIST("DebugBdt/hBdtScore2"), d0d0bar.decayVtxY()); + registry.fill(HIST("DebugBdt/hBdtScore3"), d0d0bar.decayVtxZ()); weight = 1.0f; if (doEfficiencyCorr) { @@ -1460,6 +1465,11 @@ struct FemtoUniversePairTaskTrackD0 { } } } else if ((part.partType() == aod::femtouniverseparticle::ParticleType::kD0) && (part.pt() > ConfDmesons.confMinPtD0D0barReco) && (part.pt() < ConfDmesons.confMaxPtD0D0barReco)) { + if (fillBDTvsPt && std::abs(mcpart.pdgMCTruth()) == o2::constants::physics::Pdg::kD0) { + registry.fill(HIST("DebugBdtMcReco/hBdtScore1"), part.decayVtxX()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore2"), part.decayVtxY()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore3"), part.decayVtxZ()); + } if (mcpart.pdgMCTruth() == ConfDmesons.confPDGCodeD0) { mcRecoRegistry.fill(HIST("hMcRecD0"), part.pt(), part.eta()); mcRecoRegistry.fill(HIST("hMcRecD0Pt"), part.pt()); From fa0aac385f587c9779af0d5343a97d0fe4ebcf67 Mon Sep 17 00:00:00 2001 From: Kai Cui <129373281+kcui1@users.noreply.github.com> Date: Tue, 5 May 2026 04:35:29 +0200 Subject: [PATCH 041/449] [PWGLF] Axis Change of hTrigger in HScorrelation task (#16096) --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 0ac5e6f72e9..8eafed86a5e 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -1916,7 +1916,10 @@ struct HStrangeCorrelation { for (int i = 1; i <= histos.get(HIST("Prediction/hEventSelection"))->GetNbinsX(); i++) { histos.get(HIST("Prediction/hEventSelection"))->GetXaxis()->SetBinLabel(i, eventSelLabel[i - 1]); } - histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); + if (masterConfigurations.useCentralityinPrediction) + histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + else + histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); for (int i = 0; i < AssocParticleTypes; i++) { if (TESTBIT(doCorrelation, i)) histos.add(fmt::format("Prediction/h{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); From fa43ac1555190ef120453d9cca1ab4b89f5e62fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Tue, 5 May 2026 10:29:36 +0200 Subject: [PATCH 042/449] [PWGHF] Change default cutInvMassCascCharmNuclei threshold to 0 in the track skimming task (#16110) --- PWGHF/TableProducer/trackIndexSkimCreator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index f0bed523d9c..cc96d59c074 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -3348,7 +3348,7 @@ struct HfTrackIndexSkimCreatorCascades { // cascade cuts Configurable ptCascCandMin{"ptCascCandMin", -1., "min. pT of the cascade candidate"}; // PbPb 2018: use 1 Configurable cutInvMassCascLc{"cutInvMassCascLc", 1., "Lc candidate invariant mass difference wrt PDG"}; // for PbPb 2018: use 0.2 - Configurable cutInvMassCascCharmNuclei{"cutInvMassCascCharmNuclei", 1., "charm nuclei candidate invariant mass difference wrt mass threshold"}; + Configurable cutInvMassCascCharmNuclei{"cutInvMassCascCharmNuclei", 0., "charm nuclei candidate invariant mass difference wrt mass threshold"}; // Configurable cutCascDCADaughters{"cutCascDCADaughters", .1, "DCA between V0 and bachelor in cascade"}; // proton PID From ccc2408350930caf36023effdc7d73da3ac5627f Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Tue, 5 May 2026 19:06:02 +0800 Subject: [PATCH 043/449] [PWGCF] Update saving derived data (#16115) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 60 ++++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index 62544deb592..ed52213971c 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -91,7 +91,7 @@ using JoinedCollisionsWithMc = soa::Join; using JoinedTracksWithMc = soa::Join; using JoinedMcCollisions = soa::Join; -namespace derived_collision +namespace mini_collision { DECLARE_SOA_COLUMN(Vz, vz, std::int8_t); DECLARE_SOA_COLUMN(Centrality, centrality, std::uint16_t); @@ -99,28 +99,28 @@ DECLARE_SOA_COLUMN(NChargedParticlesAll, nChargedParticlesAll, std::uint16_t); DECLARE_SOA_COLUMN(NChargedParticlesIn, nChargedParticlesIn, std::uint16_t); DECLARE_SOA_COLUMN(NTracksAll, nTracksAll, std::uint16_t); DECLARE_SOA_COLUMN(NTracksIn, nTracksIn, std::uint16_t); -} // namespace derived_collision +} // namespace mini_collision -DECLARE_SOA_TABLE(DerivedCollisions, "AOD", "DERIVEDCOLLISION", o2::soa::Index<>, derived_collision::Vz, derived_collision::Centrality, derived_collision::NChargedParticlesAll, derived_collision::NChargedParticlesIn, derived_collision::NTracksAll, derived_collision::NTracksIn); -using DerivedCollision = DerivedCollisions::iterator; +DECLARE_SOA_TABLE(MiniCollisions, "AOD", "MINICOLLISION", soa::Index<>, mini_collision::Vz, mini_collision::Centrality, mini_collision::NChargedParticlesAll, mini_collision::NChargedParticlesIn, mini_collision::NTracksAll, mini_collision::NTracksIn); +using MiniCollision = MiniCollisions::iterator; -namespace derived_particle +namespace mini_particle { -DECLARE_SOA_INDEX_COLUMN(DerivedCollision, derivedCollision); +DECLARE_SOA_INDEX_COLUMN(MiniCollision, miniCollision); DECLARE_SOA_COLUMN(SignedEfficiency, signedEfficiency, std::int16_t); -} // namespace derived_particle +} // namespace mini_particle -DECLARE_SOA_TABLE(DerivedParticles, "AOD", "DERIVEDPARTICLE", o2::soa::Index<>, derived_particle::DerivedCollisionId, derived_particle::SignedEfficiency); -using DerivedParticle = DerivedParticles::iterator; +DECLARE_SOA_TABLE(MiniParticles, "AOD", "MINIPARTICLE", soa::Index<>, mini_particle::MiniCollisionId, mini_particle::SignedEfficiency); +using MiniParticle = MiniParticles::iterator; -namespace derived_track +namespace mini_track { -DECLARE_SOA_INDEX_COLUMN(DerivedCollision, derivedCollision); +DECLARE_SOA_INDEX_COLUMN(MiniCollision, miniCollision); DECLARE_SOA_COLUMN(SignedEfficiency, signedEfficiency, std::int16_t); -} // namespace derived_track +} // namespace mini_track -DECLARE_SOA_TABLE(DerivedTracks, "AOD", "DERIVEDTRACK", o2::soa::Index<>, derived_track::DerivedCollisionId, derived_track::SignedEfficiency); -using DerivedTrack = DerivedTracks::iterator; +DECLARE_SOA_TABLE(MiniTracks, "AOD", "MINITRACK", soa::Index<>, mini_track::MiniCollisionId, mini_track::SignedEfficiency); +using MiniTrack = MiniTracks::iterator; } // namespace o2::aod namespace @@ -811,12 +811,12 @@ struct PartNumFluc { return std::numeric_limits::min() <= value && value <= std::numeric_limits::max() ? std::round(value) : (std::is_signed_v ? std::numeric_limits::min() : std::numeric_limits::max()); } - aod::derived_collision::NChargedParticlesAll::type nChargedParticlesAll{}; - aod::derived_collision::NChargedParticlesIn::type nChargedParticlesIn{}; - aod::derived_collision::NTracksAll::type nTracksAll{}; - aod::derived_collision::NTracksIn::type nTracksIn{}; - std::vector signedEfficienciesParticle{[] {std::vector v{}; v.reserve(256); return v; }()}; - std::vector signedEfficienciesTrack{[] {std::vector v{}; v.reserve(256); return v; }()}; + aod::mini_collision::NChargedParticlesAll::type nChargedParticlesAll{}; + aod::mini_collision::NChargedParticlesIn::type nChargedParticlesIn{}; + aod::mini_collision::NTracksAll::type nTracksAll{}; + aod::mini_collision::NTracksIn::type nTracksIn{}; + std::vector signedEfficienciesParticle{[] {std::vector v{}; v.reserve(256); return v; }()}; + std::vector signedEfficienciesTrack{[] {std::vector v{}; v.reserve(256); return v; }()}; void clear() { @@ -916,9 +916,9 @@ struct PartNumFluc { Preslice presliceTracksPerCollision{aod::track::collisionId}; - Produces derivedCollision; - Produces derivedParticle; - Produces derivedTrack; + Produces miniCollision; + Produces miniParticle; + Produces miniTrack; void init(InitContext&) { @@ -1962,11 +1962,11 @@ struct PartNumFluc { ++holderMcEvent.numbersEff[toI(particleNumber)][toI(chargeSpecies)]; fill(); } - holderDerivedData.signedEfficienciesParticle.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); + holderDerivedData.signedEfficienciesParticle.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); } else { ++holderEvent.numbers[toI(particleNumber)][toI(chargeSpecies)]; fill(); - holderDerivedData.signedEfficienciesTrack.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); + holderDerivedData.signedEfficienciesTrack.push_back(HolderDerivedData::convertRound(std::copysign(std::numeric_limits::max(), chargeSign) * efficiency)); } }; // NOLINT(readability/braces) @@ -2388,9 +2388,9 @@ struct PartNumFluc { fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); - derivedCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); + miniCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesTrack) { - derivedTrack(derivedCollision.lastIndex(), signedEfficiency); + miniTrack(miniCollision.lastIndex(), signedEfficiency); } } } @@ -2529,12 +2529,12 @@ struct PartNumFluc { fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); fillCalculationFluctuationByParticleNumber(); - derivedCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); + miniCollision(HolderDerivedData::convertFloor(holderEvent.vz * 10.), HolderDerivedData::convertFloor(holderEvent.centrality * 500.), holderDerivedData.nChargedParticlesAll, holderDerivedData.nChargedParticlesIn, holderDerivedData.nTracksAll, holderDerivedData.nTracksIn); for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesParticle) { - derivedParticle(derivedCollision.lastIndex(), signedEfficiency); + miniParticle(miniCollision.lastIndex(), signedEfficiency); } for (auto const& signedEfficiency : holderDerivedData.signedEfficienciesTrack) { - derivedTrack(derivedCollision.lastIndex(), signedEfficiency); + miniTrack(miniCollision.lastIndex(), signedEfficiency); } } } From dde361542ad6d76166f283c5fc9e05d6fd99466c Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 5 May 2026 15:34:26 +0200 Subject: [PATCH 044/449] [PWGHF] HFInvMassFitter enhancement (#15860) --- PWGHF/D2H/Macros/HFInvMassFitter.cxx | 290 +++++++++++++++++----- PWGHF/D2H/Macros/HFInvMassFitter.h | 75 +++++- PWGHF/D2H/Macros/config_massfitter.json | 23 +- PWGHF/D2H/Macros/runMassFitter.C | 308 +++++++++++++++++++----- 4 files changed, 560 insertions(+), 136 deletions(-) diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.cxx b/PWGHF/D2H/Macros/HFInvMassFitter.cxx index e56c9b87a28..304f7b50d7a 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.cxx +++ b/PWGHF/D2H/Macros/HFInvMassFitter.cxx @@ -19,9 +19,12 @@ /// \author Oleksii Lubynets /// \author Phil Stahlhut +// o2-linter: disable=name/workflow-file (not an O2Physics workflow) + #include "HFInvMassFitter.h" #include +#include #include #include #include @@ -39,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +56,7 @@ #include #include #include +#include #include using namespace RooFit; @@ -60,7 +65,8 @@ HFInvMassFitter::HFInvMassFitter(TH1* histoToFit, double minValue, double maxValue, int fitTypeBkg, - int fitTypeSgn) : mHistoInvMass(nullptr), + int fitTypeSgn, + int randomSeed) : mHistoInvMass(nullptr), mFitOption("L,E"), mMinMass(minValue), mMaxMass(maxValue), @@ -86,6 +92,7 @@ HFInvMassFitter::HFInvMassFitter(TH1* histoToFit, mFixedSigma(false), mFixedSigmaDoubleGaus(false), mBoundSigma(false), + mFixedDscbTailParams(false), mSigmaValue(0.012), mParamSgn(0.1), mFracDoubleGaus(0.2), @@ -106,6 +113,18 @@ HFInvMassFitter::HFInvMassFitter(TH1* histoToFit, mChiSquareOverNdfTotal(0), mChiSquareOverNdfBkg(0), mFixReflOverSgn(false), + mDscbAlphaLInitialValue(1.5), + mDscbAlphaLLowLimit(0.1), + mDscbAlphaLUpLimit(5.0), + mDscbAlphaRInitialValue(1.5), + mDscbAlphaRLowLimit(0.1), + mDscbAlphaRUpLimit(5.0), + mDscbNLInitialValue(2.0), + mDscbNLLowLimit(0.5), + mDscbNLUpLimit(50.), + mDscbNRInitialValue(2.0), + mDscbNRLowLimit(0.5), + mDscbNRUpLimit(50.), mRooMeanSgn(nullptr), mRooSigmaSgn(nullptr), mRooSecSigmaSgn(nullptr), @@ -116,25 +135,35 @@ HFInvMassFitter::HFInvMassFitter(TH1* histoToFit, mRooNSgn(nullptr), mRooNBkg(nullptr), mRooNRefl(nullptr), + mRooDscbAlphaL(nullptr), + mRooDscbAlphaR(nullptr), + mRooDscbNL(nullptr), + mRooDscbNR(nullptr), mTotalPdf(nullptr), mInvMassFrame(nullptr), mReflFrame(nullptr), mReflOnlyFrame(nullptr), mResidualFrame(nullptr), + mResidualHist(nullptr), mRatioFrame(nullptr), - mResidualFrameForCalculation(nullptr), mWorkspace(nullptr), mIntegralHisto(0), mIntegralBkg(0), mIntegralSgn(0), mHistoTemplateRefl(nullptr), mDrawBgPrefit(false), - mHighlightPeakRegion(false) + mHighlightPeakRegion(false), + mRandomSeed(randomSeed), + mRandomGen(nullptr) { // standard constructor mHistoInvMass = histoToFit; mHistoInvMass->SetName("mHistoInvMass"); mHistoInvMass->SetDirectory(nullptr); + if (mRandomSeed >= 0) { + mRandomGen = new TRandom3(); + mRandomGen->SetSeed(mRandomSeed); + } } HFInvMassFitter::~HFInvMassFitter() @@ -176,40 +205,42 @@ void HFInvMassFitter::doFit() mass->setRange("SBL", mMinMass, mMass - mNSigmaForSidebands * mSigmaSgn); mass->setRange("SBR", mMass + mNSigmaForSidebands * mSigmaSgn, mSecMass - mNSigmaForSidebands * mSecSigma); mass->setRange("SEC", mSecMass + mNSigmaForSidebands * mSecSigma, mMaxMass); - mass->setRange("signal", mSecMass - mNSigmaForSidebands * mSecSigma, mSecMass + mNSigmaForSidebands * mSecSigma); + mass->setRange("signal", mSecMass - mNSigmaForSgn * mSecSigma, mSecMass + mNSigmaForSgn * mSecSigma); } else { // Single Peak fit range mass->setRange("SBL", mMinMass, mMass - mNSigmaForSidebands * mSigmaSgn); mass->setRange("SBR", mMass + mNSigmaForSidebands * mSigmaSgn, mMaxMass); mass->setRange("signal", mMass - mNSigmaForSgn * mSigmaSgn, mMass + mNSigmaForSgn * mSigmaSgn); } } - mass->setRange("bkg", mMass - 4 * mSigmaSgn, mMass + 4 * mSigmaSgn); + mass->setRange("bkg", mMass - mNSigmaForSgn * mSigmaSgn, mMass + mNSigmaForSgn * mSigmaSgn); mass->setRange("full", mMinMass, mMaxMass); mInvMassFrame = mass->frame(Title(Form("%s", mHistoInvMass->GetTitle()))); // define the frame to plot dataHistogram.plotOn(mInvMassFrame, Name("data_c")); // plot data histogram on the frame - // define number of background and background fit function - mRooNBkg = new RooRealVar("mRooNBkg", "number of background", 0.3 * mIntegralHisto, 0., 1.2 * mIntegralHisto); // background yield - RooAbsPdf* bkgPdf = createBackgroundFitFunction(mWorkspace); // Create background pdf - RooAbsPdf* sgnPdf = createSignalFitFunction(mWorkspace); // Create signal pdf + RooAbsPdf* bkgPdf = createBackgroundFitFunction(mWorkspace); // Create background pdf + RooAbsPdf* sgnPdf = createSignalFitFunction(mWorkspace); // Create signal pdf // fit MC or Data - if (mTypeOfBkgPdf == NoBkg) { // MC - mRooNSgn = new RooRealVar("mRooNSig", "number of signal", 0.3 * mIntegralHisto, 0., 1.2 * mIntegralHisto); // signal yield - mTotalPdf = new RooAddPdf("mMCFunc", "MC fit function", RooArgList(*sgnPdf), RooArgList(*mRooNSgn)); // create total pdf + if (mTypeOfBkgPdf == NoBkg) { // MC + const ParameterRanges rooNSgnParamRanges{0., 1.2 * mIntegralHisto, 0.3 * mIntegralHisto}; + mRooNSgn = new RooRealVar("mRooNSig", "number of signal", randomizeInitialParameter(rooNSgnParamRanges), rooNSgnParamRanges.lower, rooNSgnParamRanges.upper); // signal yield + mTotalPdf = new RooAddPdf("mMCFunc", "MC fit function", RooArgList(*sgnPdf), RooArgList(*mRooNSgn)); // create total pdf if (strcmp(mFitOption.c_str(), "Chi2") == 0) { - mTotalPdf->chi2FitTo(dataHistogram, Range("signal")); + mTotalPdf->chi2FitTo(dataHistogram, Range("full")); } else { - mTotalPdf->fitTo(dataHistogram, Range("signal")); + mTotalPdf->fitTo(dataHistogram, Range("full")); } RooAbsReal* signalIntegralMc = mTotalPdf->createIntegral(*mass, NormSet(*mass), Range("signal")); // sig yield from fit mIntegralSgn = signalIntegralMc->getValV(); - calculateSignal(mRawYield, mRawYieldErr); // calculate signal and signal error + calculateSignal(mRawYield, mRawYieldErr); // calculate signal and signal error + countSignal(mRawYieldCounted, mRawYieldCountedErr); mTotalPdf->plotOn(mInvMassFrame, Name("Tot_c")); // plot total function // Fit to data ratio mRatioFrame = mass->frame(Title(Form("%s", mHistoInvMass->GetTitle()))); calculateFitToDataRatio(); } else { // data + const ParameterRanges rooNBkgParamRanges{0., 1.2 * mIntegralHisto, 0.3 * mIntegralHisto}; + mRooNBkg = new RooRealVar("mRooNBkg", "number of background", randomizeInitialParameter(rooNBkgParamRanges), rooNBkgParamRanges.lower, rooNBkgParamRanges.upper); // background yield mBkgPdf = new RooAddPdf("mBkgPdf", "background fit function", RooArgList(*bkgPdf), RooArgList(*mRooNBkg)); if (mTypeOfSgnPdf == GausSec) { // two peak fit if (strcmp(mFitOption.c_str(), "Chi2") == 0) { @@ -243,7 +274,8 @@ void HFInvMassFitter::doFit() checkForSignal(estimatedSignal); // SIG's absolute integral in "bkg" range calculateBackground(mBkgYield, mBkgYieldErr); // BG's absolute integral in "bkg" range - mRooNSgn = new RooRealVar("mNSgn", "number of signal", 0.3 * estimatedSignal, 0., 1.2 * estimatedSignal); // estimated signal yield + const ParameterRanges rooNSgnParamRanges{0., 1.2 * estimatedSignal, 0.3 * estimatedSignal}; + mRooNSgn = new RooRealVar("mNSgn", "number of signal", randomizeInitialParameter(rooNSgnParamRanges), rooNSgnParamRanges.lower, rooNSgnParamRanges.upper); // estimated signal yield if (mFixedRawYield > 0) { mRooNSgn->setVal(mFixedRawYield); // fixed signal yield mRooNSgn->setConstant(true); @@ -256,7 +288,8 @@ void HFInvMassFitter::doFit() mReflFrame = mass->frame(); mReflOnlyFrame = mass->frame(Title(Form("%s", mHistoTemplateRefl->GetTitle()))); reflHistogram.plotOn(mReflOnlyFrame); - mRooNRefl = new RooRealVar("mNRefl", "number of reflection", 0.5 * mHistoTemplateRefl->Integral(), 0, mHistoTemplateRefl->Integral()); + const ParameterRanges rooNReflParamRanges{0., mHistoTemplateRefl->Integral(), 0.5 * mHistoTemplateRefl->Integral()}; + mRooNRefl = new RooRealVar("mNRefl", "number of reflection", randomizeInitialParameter(rooNReflParamRanges), rooNReflParamRanges.lower, rooNReflParamRanges.upper); RooAddPdf reflFuncTemp("reflFuncTemp", "template reflection fit function", RooArgList(*reflPdf), RooArgList(*mRooNRefl)); if (strcmp(mFitOption.c_str(), "Chi2") == 0) { reflFuncTemp.chi2FitTo(reflHistogram); @@ -283,9 +316,9 @@ void HFInvMassFitter::doFit() mChiSquareOverNdfTotal = mInvMassFrame->chiSquare("Tot_c", "data_c"); // calculate reduced chi2 / NDF // plot residual distribution - RooHist* residualHistogram = mInvMassFrame->residHist("data_c", "ReflBkg_c"); + mResidualHist = mInvMassFrame->residHist("data_c", "ReflBkg_c"); mResidualFrame = mass->frame(Title("Residual Distribution")); - mResidualFrame->addPlotable(residualHistogram, "p"); + mResidualFrame->addPlotable(mResidualHist, "p"); mSgnPdf->plotOn(mResidualFrame, Normalization(1.0, RooAbsReal::RelativeExpected), LineColor(kBlue)); } else { mTotalPdf = new RooAddPdf("mTotalPdf", "background + signal pdf", RooArgList(*bkgPdf, *sgnPdf), RooArgList(*mRooNBkg, *mRooNSgn)); @@ -301,8 +334,8 @@ void HFInvMassFitter::doFit() // plot residual distribution mResidualFrame = mass->frame(Title("Residual Distribution")); - RooHist* residualHistogram = mInvMassFrame->residHist("data_c", "Bkg_c"); - mResidualFrame->addPlotable(residualHistogram, "P"); + mResidualHist = mInvMassFrame->residHist("data_c", "Bkg_c"); + mResidualFrame->addPlotable(mResidualHist, "P"); mSgnPdf->plotOn(mResidualFrame, Normalization(1.0, RooAbsReal::RelativeExpected), LineColor(kBlue)); } mass->setRange("bkgForSignificance", mRooMeanSgn->getVal() - mNSigmaForSgn * mRooSecSigmaSgn->getVal(), mRooMeanSgn->getVal() + mNSigmaForSgn * mRooSecSigmaSgn->getVal()); @@ -326,35 +359,42 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const // Declare observable variable RooRealVar mass("mass", "mass", mMinMass, mMaxMass, "GeV/c^{2}"); // bkg expo - RooRealVar tau("tau", "tau", -1, -5., 5.); + const ParameterRanges tauParamRanges{-5., 5., -1., 0.1}; + RooRealVar tau("tau", "tau", randomizeInitialParameter(tauParamRanges), tauParamRanges.lower, tauParamRanges.upper); RooAbsPdf* bkgFuncExpo = new RooExponential("bkgFuncExpo", "background fit function", mass, tau); workspace.import(*bkgFuncExpo); delete bkgFuncExpo; // bkg poly1 - RooRealVar const polyParam0("polyParam0", "Parameter of Poly function", 0.5, -5., 5.); - RooRealVar const polyParam1("polyParam1", "Parameter of Poly function", 0.2, -5., 5.); + const ParameterRanges polyParam0ParamRanges{-5., 5., 0.5, 0.1}; + RooRealVar const polyParam0("polyParam0", "Parameter of Poly function", randomizeInitialParameter(polyParam0ParamRanges), polyParam0ParamRanges.lower, polyParam0ParamRanges.upper); + const ParameterRanges polyParam1ParamRanges{-5., 5., 0.2, 0.05}; + RooRealVar const polyParam1("polyParam1", "Parameter of Poly function", randomizeInitialParameter(polyParam1ParamRanges), polyParam1ParamRanges.lower, polyParam1ParamRanges.upper); RooAbsPdf* bkgFuncPoly1 = new RooPolynomial("bkgFuncPoly1", "background fit function", mass, RooArgSet(polyParam0, polyParam1)); workspace.import(*bkgFuncPoly1); delete bkgFuncPoly1; // bkg poly2 - RooRealVar const polyParam2("polyParam2", "Parameter of Poly function", 0.2, -5., 5.); + const ParameterRanges polyParam2ParamRanges{-5., 5., 0.2, 0.05}; + RooRealVar const polyParam2("polyParam2", "Parameter of Poly function", randomizeInitialParameter(polyParam2ParamRanges), polyParam2ParamRanges.lower, polyParam2ParamRanges.upper); RooAbsPdf* bkgFuncPoly2 = new RooPolynomial("bkgFuncPoly2", "background fit function", mass, RooArgSet(polyParam0, polyParam1, polyParam2)); workspace.import(*bkgFuncPoly2); delete bkgFuncPoly2; // bkg poly3 - RooRealVar const polyParam3("polyParam3", "Parameter of Poly function", 0.2, -1., 1.); + const ParameterRanges polyParam3ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyParam3("polyParam3", "Parameter of Poly function", randomizeInitialParameter(polyParam3ParamRanges), polyParam3ParamRanges.lower, polyParam3ParamRanges.upper); RooAbsPdf* bkgFuncPoly3 = new RooPolynomial("bkgFuncPoly3", "background pdf", mass, RooArgSet(polyParam0, polyParam1, polyParam2, polyParam3)); workspace.import(*bkgFuncPoly3); delete bkgFuncPoly3; // bkg power law RooRealVar const powParam1("powParam1", "Parameter of Pow function", TDatabasePDG::Instance()->GetParticle("pi+")->Mass()); - RooRealVar const powParam2("powParam2", "Parameter of Pow function", 1., -10, 10); + const ParameterRanges powParam2ParamRanges{-10., 10., 1., 0.2}; + RooRealVar const powParam2("powParam2", "Parameter of Pow function", randomizeInitialParameter(powParam2ParamRanges), powParam2ParamRanges.lower, powParam2ParamRanges.upper); RooAbsPdf* bkgFuncPow = new RooGenericPdf("bkgFuncPow", "bkgFuncPow", "(mass-powParam1)^powParam2", RooArgSet(mass, powParam1, powParam2)); workspace.import(*bkgFuncPow); delete bkgFuncPow; // pow * exp RooRealVar const powExpoParam1("powExpoParam1", "Parameter of PowExpo function", 1. / 2.); - RooRealVar const powExpoParam2("powExpoParam2", "Parameter of PowExpo function", 1, -10, 10); + const ParameterRanges powExpoParam2ParamRanges{-10., 10., 1., 0.2}; + RooRealVar const powExpoParam2("powExpoParam2", "Parameter of PowExpo function", randomizeInitialParameter(powExpoParam2ParamRanges), powExpoParam2ParamRanges.lower, powExpoParam2ParamRanges.upper); RooRealVar massPi("massPi", "mass of pion", TDatabasePDG::Instance()->GetParticle("pi+")->Mass()); RooFormulaVar powExpoParam3("powExpoParam3", "powExpoParam1 + 1", RooArgList(powExpoParam1)); RooFormulaVar powExpoParam4("powExpoParam4", "1./powExpoParam2", RooArgList(powExpoParam2)); @@ -482,18 +522,48 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const RooAbsPdf* reflFuncDoubleGaus = new RooAddPdf("reflFuncDoubleGaus", "reflection pdf", RooArgList(gausRefl1, gausRefl2), fracRefl); workspace.import(*reflFuncDoubleGaus); delete reflFuncDoubleGaus; + // signal DSCB pdf + const ParameterRanges dscbAlphaLParamRanges{mDscbAlphaLLowLimit, mDscbAlphaLUpLimit, mDscbAlphaLInitialValue}; + const ParameterRanges dscbNLParamRanges{mDscbNLLowLimit, mDscbNLUpLimit, mDscbNLInitialValue}; + const ParameterRanges dscbAlphaRParamRanges{mDscbAlphaRLowLimit, mDscbAlphaRUpLimit, mDscbAlphaRInitialValue}; + const ParameterRanges dscbNRParamRanges{mDscbNRLowLimit, mDscbNRUpLimit, mDscbNRInitialValue}; + RooRealVar alphaL("alphaL", "left tail alpha", randomizeInitialParameter(dscbAlphaLParamRanges), dscbAlphaLParamRanges.lower, dscbAlphaLParamRanges.upper); + RooRealVar nL("nL", "left tail n", randomizeInitialParameter(dscbNLParamRanges), dscbNLParamRanges.lower, dscbNLParamRanges.upper); + RooRealVar alphaR("alphaR", "right tail alpha", randomizeInitialParameter(dscbAlphaRParamRanges), dscbAlphaRParamRanges.lower, dscbAlphaRParamRanges.upper); + RooRealVar nR("nR", "right tail n", randomizeInitialParameter(dscbNRParamRanges), dscbNRParamRanges.lower, dscbNRParamRanges.upper); + if (mFixedDscbTailParams) { + printf("Fixing DSCB tail parameters to initial values.\n"); + alphaL.setVal(mDscbAlphaLInitialValue); + alphaL.setConstant(true); + alphaR.setVal(mDscbAlphaRInitialValue); + alphaR.setConstant(true); + nL.setVal(mDscbNLInitialValue); + nL.setConstant(true); + nR.setVal(mDscbNRInitialValue); + nR.setConstant(true); + } + RooAbsPdf* sgnFuncDSCB = new RooCrystalBall("sgnFuncDSCB", "double sided crystal ball signal", mass, mean, sigma, alphaL, nL, alphaR, nR); + workspace.import(*sgnFuncDSCB); + delete sgnFuncDSCB; // reflection poly3 - RooRealVar const polyReflParam0("polyReflParam0", "polyReflParam0", 0.5, -1., 1.); - RooRealVar const polyReflParam1("polyReflParam1", "polyReflParam1", 0.2, -1., 1.); - RooRealVar const polyReflParam2("polyReflParam2", "polyReflParam2", 0.2, -1., 1.); - RooRealVar const polyReflParam3("polyReflParam3", "polyReflParam3", 0.2, -1., 1.); + const ParameterRanges polyReflParam0ParamRanges{-1., 1., 0.5, 0.1}; + RooRealVar const polyReflParam0("polyReflParam0", "polyReflParam0", randomizeInitialParameter(polyReflParam0ParamRanges), polyReflParam0ParamRanges.lower, polyReflParam0ParamRanges.upper); + const ParameterRanges polyReflParam1ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam1("polyReflParam1", "polyReflParam1", randomizeInitialParameter(polyReflParam1ParamRanges), polyReflParam1ParamRanges.lower, polyReflParam1ParamRanges.upper); + const ParameterRanges polyReflParam2ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam2("polyReflParam2", "polyReflParam2", randomizeInitialParameter(polyReflParam2ParamRanges), polyReflParam2ParamRanges.lower, polyReflParam2ParamRanges.upper); + const ParameterRanges polyReflParam3ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam3("polyReflParam3", "polyReflParam3", randomizeInitialParameter(polyReflParam3ParamRanges), polyReflParam3ParamRanges.lower, polyReflParam3ParamRanges.upper); RooAbsPdf* reflFuncPoly3 = new RooPolynomial("reflFuncPoly3", "reflection PDF", mass, RooArgSet(polyReflParam0, polyReflParam1, polyReflParam2, polyReflParam3)); workspace.import(*reflFuncPoly3); delete reflFuncPoly3; // reflection poly6 - RooRealVar const polyReflParam4("polyReflParam4", "polyReflParam4", 0.2, -1., 1.); - RooRealVar const polyReflParam5("polyReflParam5", "polyReflParam5", 0.2, -1., 1.); - RooRealVar const polyReflParam6("polyReflParam6", "polyReflParam6", 0.2, -1., 1.); + const ParameterRanges polyReflParam4ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam4("polyReflParam4", "polyReflParam4", randomizeInitialParameter(polyReflParam4ParamRanges), polyReflParam4ParamRanges.lower, polyReflParam4ParamRanges.upper); + const ParameterRanges polyReflParam5ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam5("polyReflParam5", "polyReflParam5", randomizeInitialParameter(polyReflParam5ParamRanges), polyReflParam5ParamRanges.lower, polyReflParam5ParamRanges.upper); + const ParameterRanges polyReflParam6ParamRanges{-1., 1., 0.2, 0.05}; + RooRealVar const polyReflParam6("polyReflParam6", "polyReflParam6", randomizeInitialParameter(polyReflParam6ParamRanges), polyReflParam6ParamRanges.lower, polyReflParam6ParamRanges.upper); RooAbsPdf* reflFuncPoly6 = new RooPolynomial("reflFuncPoly6", "reflection pdf", mass, RooArgSet(polyReflParam0, polyReflParam1, polyReflParam2, polyReflParam3, polyReflParam4, polyReflParam5, polyReflParam6)); workspace.import(*reflFuncPoly6); delete reflFuncPoly6; @@ -515,9 +585,9 @@ void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& textFitMetrics->AddText(Form("S = %.0f #pm %.0f ", mRawYield, mRawYieldErr)); textFitMetrics->AddText(Form("S_{count} = %.0f #pm %.0f ", mRawYieldCounted, mRawYieldCountedErr)); if (mTypeOfBkgPdf != NoBkg) { - textFitMetrics->AddText(Form("B (%.1f#sigma) = %.0f #pm %.0f", mNSigmaForSidebands, mBkgYield, mBkgYieldErr)); - textFitMetrics->AddText(Form("S/B (%.1f#sigma) = %.4g ", mNSigmaForSidebands, mRawYield / mBkgYield)); - textFitMetrics->AddText(Form("Significance (%.1f#sigma) = %.1f #pm %.1f ", mNSigmaForSidebands, mSignificance, mSignificanceErr)); + textFitMetrics->AddText(Form("B (%.1f#sigma) = %.0f #pm %.0f", mNSigmaForSgn, mBkgYield, mBkgYieldErr)); + textFitMetrics->AddText(Form("S/B (%.1f#sigma) = %.4g ", mNSigmaForSgn, mRawYield / mBkgYield)); + textFitMetrics->AddText(Form("Significance (%.1f#sigma) = %.1f #pm %.1f ", mNSigmaForSgn, mSignificance, mSignificanceErr)); textFitMetrics->AddText(Form("#chi^{2} / ndf = %.3f", mChiSquareOverNdfTotal)); } if (mReflPdf != nullptr) { @@ -544,10 +614,10 @@ void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& const std::string fixMeanStatus = mFixedMean ? "fixed" : "free"; const std::string fixSigmaStatus = mFixedSigma ? "fixed" : "free"; const std::string fixSigmaDoubleGausStatus = mFixedSigmaDoubleGaus ? "fixed" : "free"; - textSignalPar->AddText(Form("mean(%s) = %.3f #pm %.3f", fixMeanStatus.c_str(), mRooMeanSgn->getVal(), mRooMeanSgn->getError())); - textSignalPar->AddText(Form("sigma(%s) = %.3f #pm %.3f", fixSigmaStatus.c_str(), mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + textSignalPar->AddText(Form("#mu(%s) = %.3f #pm %.3f", fixMeanStatus.c_str(), mRooMeanSgn->getVal(), mRooMeanSgn->getError())); + textSignalPar->AddText(Form("#sigma(%s) = %.3f #pm %.3f", fixSigmaStatus.c_str(), mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); if (mTypeOfSgnPdf == DoubleGaus) { - textSignalPar->AddText(Form("sigma 2(%s) = %.3f #pm %.3f", fixSigmaDoubleGausStatus.c_str(), mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); + textSignalPar->AddText(Form("#sigma_{2}(%s) = %.3f #pm %.3f", fixSigmaDoubleGausStatus.c_str(), mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); } mInvMassFrame->addObject(textSignalPar); } @@ -574,10 +644,10 @@ void HFInvMassFitter::drawResidual(TVirtualPad* pad) textInfo->SetTextColor(kBlue); textInfo->AddText(Form("S = %.0f #pm %.0f ", mRawYield, mRawYieldErr)); textInfo->AddText(Form("S_{count} = %.0f #pm %.0f ", mRawYieldCounted, mRawYieldCountedErr)); - textInfo->AddText(Form("mean = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); - textInfo->AddText(Form("sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + textInfo->AddText(Form("#mu = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); + textInfo->AddText(Form("#sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); if (mTypeOfSgnPdf == DoubleGaus) { - textInfo->AddText(Form("sigma 2 = %.3f #pm %.3f", mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); + textInfo->AddText(Form("#sigma_{2} = %.3f #pm %.3f", mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); } mResidualFrame->addObject(textInfo); mResidualFrame->Draw(); @@ -635,29 +705,32 @@ void HFInvMassFitter::drawReflection(TVirtualPad* pad) // calculate signal yield via bin counting void HFInvMassFitter::countSignal(double& signal, double& signalErr) const { - const double mean = mRooMeanSgn->getVal(); - const double sigma = mRooSecSigmaSgn->getVal(); - const double minForSgn = mean - mNSigmaForSidebands * sigma; - const double maxForSgn = mean + mNSigmaForSidebands * sigma; - const int binForMinSgn = mHistoInvMass->FindBin(minForSgn); - const int binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); - const double binForMinSgnUpperEdge = mHistoInvMass->GetBinLowEdge(binForMinSgn + 1); - const double binForMaxSgnLowerEdge = mHistoInvMass->GetBinLowEdge(binForMaxSgn); - const double binForMinSgnFraction = (binForMinSgnUpperEdge - minForSgn) / mHistoInvMass->GetBinWidth(binForMinSgn); - const double binForMaxSgnFraction = (maxForSgn - binForMaxSgnLowerEdge) / mHistoInvMass->GetBinWidth(binForMaxSgn); - - double sum = 0; - sum += mHistoInvMass->GetBinContent(binForMinSgn) * binForMinSgnFraction; + const auto& histoForCounting = mTypeOfBkgPdf == NoBkg ? mInvMassFrame->getHist("data_c") : mResidualHist; + + const double binWidth = histoForCounting->GetX()[1] - histoForCounting->GetX()[0]; + const double firstBinLowEdge = histoForCounting->GetX()[0] - binWidth / 2; + const auto [minForSgn, maxForSgn] = getRangesOfSignal(); + const int binForMinSgn = static_cast((minForSgn - firstBinLowEdge) / binWidth) + 1; + const int binForMaxSgn = static_cast((maxForSgn - firstBinLowEdge) / binWidth) + 1; + const double binForMinSgnUpperEdge = firstBinLowEdge + (binForMinSgn - 1) * binWidth + binWidth; + const double binForMaxSgnLowerEdge = firstBinLowEdge + (binForMaxSgn - 1) * binWidth; + const double binForMinSgnFraction = (binForMinSgnUpperEdge - minForSgn) / binWidth; + const double binForMaxSgnFraction = (maxForSgn - binForMaxSgnLowerEdge) / binWidth; + + auto square = [](double value) { return value * value; }; + + double sumValues{}, sumErrorsSquare{}; + sumValues += histoForCounting->GetY()[binForMinSgn - 1] * binForMinSgnFraction; + sumErrorsSquare += square(histoForCounting->GetErrorY(binForMinSgn - 1) * binForMinSgnFraction); for (int iBin = binForMinSgn + 1; iBin <= binForMaxSgn - 1; iBin++) { - sum += mHistoInvMass->GetBinContent(iBin); + sumValues += histoForCounting->GetY()[iBin - 1]; + sumErrorsSquare += square(histoForCounting->GetErrorY(iBin - 1)); } - sum += mHistoInvMass->GetBinContent(binForMaxSgn) * binForMaxSgnFraction; + sumValues += histoForCounting->GetY()[binForMaxSgn - 1] * binForMaxSgnFraction; + sumErrorsSquare += square(histoForCounting->GetErrorY(binForMaxSgn - 1) * binForMaxSgnFraction); - double bkg{}, errBkg{}; - calculateBackground(bkg, errBkg); - - signal = sum - bkg; - signalErr = std::sqrt(sum + errBkg * errBkg); // sum error squared is equal to sum + signal = sumValues; + signalErr = std::sqrt(sumErrorsSquare); } // calculate signal yield @@ -670,6 +743,11 @@ void HFInvMassFitter::calculateSignal(double& signal, double& errSignal) const // calculate background yield void HFInvMassFitter::calculateBackground(double& bkg, double& errBkg) const { + if (mTypeOfBkgPdf == NoBkg) { + bkg = 0.; + errBkg = 0.; + return; + } bkg = mRooNBkg->getVal() * mIntegralBkg; errBkg = mRooNBkg->getError() * mIntegralBkg; } @@ -691,8 +769,7 @@ void HFInvMassFitter::calculateSignificance(double& significance, double& errSig // estimate Signal void HFInvMassFitter::checkForSignal(double& estimatedSignal) { - double const minForSgn = mMass - 4 * mSigmaSgn; - double const maxForSgn = mMass + 4 * mSigmaSgn; + auto const [minForSgn, maxForSgn] = getRangesOfSignal(); int const binForMinSgn = mHistoInvMass->FindBin(minForSgn); int const binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); @@ -705,6 +782,19 @@ void HFInvMassFitter::checkForSignal(double& estimatedSignal) estimatedSignal = sum - bkg; } +// Estimate ranges where signal is located to be used in countSignal() and checkForSignal() +// It is mu +- n*sigma for Gaussian, and the entire mInv histogram for DoubleSidedCrystalBall (due to heavy tails) +std::pair HFInvMassFitter::getRangesOfSignal() const +{ + if (mTypeOfSgnPdf == DoubleSidedCrystalBall) { + return std::make_pair(mMinMass, mMaxMass); + } else { + const double mean = mRooMeanSgn->getVal(); + const double sigma = mRooSecSigmaSgn->getVal(); + return std::make_pair(mean - mNSigmaForSgn * sigma, mean + mNSigmaForSgn * sigma); + } +} + // Create Background Fit Function RooAbsPdf* HFInvMassFitter::createBackgroundFitFunction(RooWorkspace* workspace) const { @@ -751,6 +841,16 @@ RooAbsPdf* HFInvMassFitter::createSignalFitFunction(RooWorkspace* workspace) mRooSecSigmaSgn = workspace->var("sigmaSec"); mRooMeanSgn = workspace->var("meanSec"); } break; + case DoubleSidedCrystalBall: { + sgnPdf = workspace->pdf("sgnFuncDSCB"); + mRooSigmaSgn = workspace->var("sigma"); + mRooSecSigmaSgn = workspace->var("sigma"); + mRooMeanSgn = workspace->var("mean"); + mRooDscbAlphaL = workspace->var("alphaL"); + mRooDscbNL = workspace->var("nL"); + mRooDscbAlphaR = workspace->var("alphaR"); + mRooDscbNR = workspace->var("nR"); + } break; default: break; } @@ -991,3 +1091,61 @@ void HFInvMassFitter::setTemplateReflections(TH1* histoRefl) mHistoTemplateRefl = histoRefl; mHistoTemplateRefl->SetName("mHistoTemplateRefl"); } + +void HFInvMassFitter::setFixDscbAlphaL(double alphaL) +{ + if (mTypeOfSgnPdf != DoubleSidedCrystalBall) { + printf("Fit type should be DSCB!\n"); + } + mFixedDscbTailParams = kTRUE; + mDscbAlphaLInitialValue = alphaL; +} +void HFInvMassFitter::setFixDscbAlphaR(double alphaR) +{ + if (mTypeOfSgnPdf != DoubleSidedCrystalBall) { + printf("Fit type should be DSCB!\n"); + } + mFixedDscbTailParams = kTRUE; + mDscbAlphaRInitialValue = alphaR; +} +void HFInvMassFitter::setFixDscbNL(double nL) +{ + if (mTypeOfSgnPdf != DoubleSidedCrystalBall) { + printf("Fit type should be DSCB!\n"); + } + mFixedDscbTailParams = kTRUE; + mDscbNLInitialValue = nL; +} +void HFInvMassFitter::setFixDscbNR(double nR) +{ + if (mTypeOfSgnPdf != DoubleSidedCrystalBall) { + printf("Fit type should be DSCB!\n"); + } + mFixedDscbTailParams = kTRUE; + mDscbNRInitialValue = nR; +} + +double HFInvMassFitter::randomizeInitialParameter(const ParameterRanges& parameterRanges) const +{ + constexpr double DefaultSigmaFraction{10.}; + constexpr int MaximalNumberOfIterations{20}; + + if (mRandomSeed < 0) { + return parameterRanges.initial; + } + const auto sigma = parameterRanges.sigma < 0 ? (parameterRanges.upper - parameterRanges.lower) / DefaultSigmaFraction : parameterRanges.sigma; + + double result; + int nIter{0}; + do { + result = mRandomGen->Gaus(parameterRanges.initial, sigma); + ++nIter; + if (nIter > MaximalNumberOfIterations) { + char errorMessage[200]; + std::snprintf(errorMessage, sizeof(errorMessage), "randomizeInitialParameter() - long while loop with lower = %f upper = %f initial = %f sigma = %f\n", parameterRanges.lower, parameterRanges.upper, parameterRanges.initial, sigma); + throw std::runtime_error(errorMessage); + } + } while (result < parameterRanges.lower || result > parameterRanges.upper); + + return result; +} diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.h b/PWGHF/D2H/Macros/HFInvMassFitter.h index 28ee858bba6..6841cf15a55 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.h +++ b/PWGHF/D2H/Macros/HFInvMassFitter.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -35,10 +36,19 @@ #include #include +#include #include class HFInvMassFitter : public TNamed { + private: + struct ParameterRanges { + double lower{}; + double upper{}; + double initial{}; + double sigma{-999.}; + }; + public: enum TypeOfBkgPdf { Expo = 0, @@ -56,6 +66,7 @@ class HFInvMassFitter : public TNamed DoubleGaus = 1, DoubleGausSigmaRatioPar = 2, GausSec = 3, + DoubleSidedCrystalBall = 4, NTypesOfSgnPdf }; enum TypeOfReflPdf { @@ -67,7 +78,7 @@ class HFInvMassFitter : public TNamed }; std::array namesOfReflPdf{"reflFuncGaus", "reflFuncDoubleGaus", "reflFuncPoly3", "reflFuncPoly6"}; HFInvMassFitter() = delete; - HFInvMassFitter(TH1* histoToFit, double minValue, double maxValue, int fitTypeBkg = Expo, int fitTypeSgn = SingleGaus); + HFInvMassFitter(TH1* histoToFit, double minValue, double maxValue, int fitTypeBkg = Expo, int fitTypeSgn = SingleGaus, int randomSeed = -1); ~HFInvMassFitter() override; void setHistogramForFit(TH1* histoToFit); void setUseLikelihoodFit() { mFitOption = "L,E"; } @@ -97,6 +108,23 @@ class HFInvMassFitter : public TNamed void setFixRatioToGausSigma(double sigmaFrac); void setFixSignalYield(double yield) { mFixedRawYield = yield; } void setNumberOfSigmaForSidebands(double numberOfSigma) { mNSigmaForSidebands = numberOfSigma; } + void setNumberOfSigmaForSignal(double numberOfSigma) { mNSigmaForSgn = numberOfSigma; } + void setFixDscbAlphaL(double alphaL); + void setFixDscbAlphaR(double alphaR); + void setFixDscbNL(double nL); + void setFixDscbNR(double nR); + void setDscbAlphaLInitialValue(double value) { mDscbAlphaLInitialValue = value; } + void setDscbAlphaLLowLimit(double value) { mDscbAlphaLLowLimit = value; } + void setDscbAlphaLUpLimit(double value) { mDscbAlphaLUpLimit = value; } + void setDscbAlphaRInitialValue(double value) { mDscbAlphaRInitialValue = value; } + void setDscbAlphaRLowLimit(double value) { mDscbAlphaRLowLimit = value; } + void setDscbAlphaRUpLimit(double value) { mDscbAlphaRUpLimit = value; } + void setDscbNLInitialValue(double value) { mDscbNLInitialValue = value; } + void setDscbNLLowLimit(double value) { mDscbNLLowLimit = value; } + void setDscbNLUpLimit(double value) { mDscbNLUpLimit = value; } + void setDscbNRInitialValue(double value) { mDscbNRInitialValue = value; } + void setDscbNRLowLimit(double value) { mDscbNRLowLimit = value; } + void setDscbNRUpLimit(double value) { mDscbNRUpLimit = value; } void plotBkg(RooAbsPdf* mFunc, Color_t color = kRed); void plotRefl(RooAbsPdf* mFunc); void setReflFuncFixed(); @@ -120,6 +148,14 @@ class HFInvMassFitter : public TNamed [[nodiscard]] double getMeanUncertainty() const { return mRooMeanSgn->getError(); } [[nodiscard]] double getSigma() const { return mRooSigmaSgn->getVal(); } [[nodiscard]] double getSigmaUncertainty() const { return mRooSigmaSgn->getError(); } + [[nodiscard]] double getDscbAlphaL() const { return mRooDscbAlphaL ? mRooDscbAlphaL->getVal() : 0.; } + [[nodiscard]] double getDscbAlphaR() const { return mRooDscbAlphaR ? mRooDscbAlphaR->getVal() : 0.; } + [[nodiscard]] double getDscbNL() const { return mRooDscbNL ? mRooDscbNL->getVal() : 0.; } + [[nodiscard]] double getDscbNR() const { return mRooDscbNR ? mRooDscbNR->getVal() : 0.; } + [[nodiscard]] double getDscbAlphaLUncertainty() const { return mRooDscbAlphaL ? mRooDscbAlphaL->getError() : 0.; } + [[nodiscard]] double getDscbAlphaRUncertainty() const { return mRooDscbAlphaR ? mRooDscbAlphaR->getError() : 0.; } + [[nodiscard]] double getDscbNLUncertainty() const { return mRooDscbNL ? mRooDscbNL->getError() : 0.; } + [[nodiscard]] double getDscbNRUncertainty() const { return mRooDscbNR ? mRooDscbNR->getError() : 0.; } [[nodiscard]] double getSecSigma() const { return mRooSecSigmaSgn->getVal(); } [[nodiscard]] double getSecSigmaUncertainty() const { return mRooSecSigmaSgn->getError(); } [[nodiscard]] double getFracDoubleGaus() const { return mRooFracDoubleGaus->getVal(); } @@ -141,6 +177,8 @@ class HFInvMassFitter : public TNamed HFInvMassFitter& operator=(const HFInvMassFitter& source); void fillWorkspace(RooWorkspace& w) const; void highlightPeakRegion(const RooPlot* plot, Color_t color = kGray + 1, Width_t width = 1, Style_t style = 2) const; + [[nodiscard]] double randomizeInitialParameter(const ParameterRanges& parameterRanges) const; + [[nodiscard]] std::pair getRangesOfSignal() const; TH1* mHistoInvMass; // histogram to fit std::string mFitOption; @@ -168,6 +206,7 @@ class HFInvMassFitter : public TNamed bool mFixedSigma; /// fix sigma or not bool mFixedSigmaDoubleGaus; /// fix sigma of 2gaussian or not bool mBoundSigma; /// set bound sigma or not + bool mFixedDscbTailParams; /// switch for fix double sided Crystal Ball tail parameters double mSigmaValue; /// value of sigma double mParamSgn; /// +/- range variation of bound Sigma of gaussian in % double mFracDoubleGaus; /// initialization for fraction of 2nd gaussian in case of k2Gaus or k2GausSigmaRatioPar @@ -188,6 +227,18 @@ class HFInvMassFitter : public TNamed double mChiSquareOverNdfTotal; /// chi2/ndf of the total fit double mChiSquareOverNdfBkg; /// chi2/ndf of the background (sidebands) pre-fit bool mFixReflOverSgn; /// switch for fix refl/signal + double mDscbAlphaLInitialValue; /// double sided Crystal Ball alpha left initial value + double mDscbAlphaLLowLimit; /// double sided Crystal Ball alpha left lower limit + double mDscbAlphaLUpLimit; /// double sided Crystal Ball alpha left upper limit + double mDscbAlphaRInitialValue; /// double sided Crystal Ball alpha right initial value + double mDscbAlphaRLowLimit; /// double sided Crystal Ball alpha right lower limit + double mDscbAlphaRUpLimit; /// double sided Crystal Ball alpha right upper limit + double mDscbNLInitialValue; /// double sided Crystal Ball n left initial value + double mDscbNLLowLimit; /// double sided Crystal Ball n left lower limit + double mDscbNLUpLimit; /// double sided Crystal Ball n left upper limit + double mDscbNRInitialValue; /// double sided Crystal Ball n right initial value + double mDscbNRLowLimit; /// double sided Crystal Ball n right lower limit + double mDscbNRUpLimit; /// double sided Crystal Ball n right upper limit RooRealVar* mRooMeanSgn; /// mean for gaussian of signal RooRealVar* mRooSigmaSgn; /// sigma for gaussian of signal RooRealVar* mRooSecSigmaSgn; /// second sigma for composite gaussian of signal @@ -198,20 +249,26 @@ class HFInvMassFitter : public TNamed RooRealVar* mRooNSgn; /// total Signal fit function integral RooRealVar* mRooNBkg; /// total background fit function integral RooRealVar* mRooNRefl; /// total reflection fit function integral + RooRealVar* mRooDscbAlphaL; /// double sided Crystal Ball alpha left + RooRealVar* mRooDscbAlphaR; /// double sided Crystal Ball alpha right + RooRealVar* mRooDscbNL; /// double sided Crystal Ball n left + RooRealVar* mRooDscbNR; /// double sided Crystal Ball n right RooAbsPdf* mTotalPdf; /// total fit function RooPlot* mInvMassFrame; /// frame of mass RooPlot* mReflFrame; /// reflection frame RooPlot* mReflOnlyFrame; /// reflection frame plot on reflection only RooPlot* mResidualFrame; /// residual frame + RooHist* mResidualHist; /// residual histogram RooPlot* mRatioFrame; /// fit/data ratio frame - RooPlot* mResidualFrameForCalculation; - RooWorkspace* mWorkspace; /// workspace - double mIntegralHisto; /// integral of histogram to fit - double mIntegralBkg; /// integral of background fit function - double mIntegralSgn; /// integral of signal fit function - TH1* mHistoTemplateRefl; /// reflection histogram - bool mDrawBgPrefit; /// draw background after fitting the sidebands - bool mHighlightPeakRegion; /// draw vertical lines showing the peak region (usually +- 3 sigma) + RooWorkspace* mWorkspace; /// workspace + double mIntegralHisto; /// integral of histogram to fit + double mIntegralBkg; /// integral of background fit function + double mIntegralSgn; /// integral of signal fit function + TH1* mHistoTemplateRefl; /// reflection histogram + bool mDrawBgPrefit; /// draw background after fitting the sidebands + bool mHighlightPeakRegion; /// draw vertical lines showing the peak region (usually +- 3 sigma) + int mRandomSeed; /// seed for random engine for fit's initial parameters randomization + TRandom3* mRandomGen; /// engine for fit's initial parameters randomization ClassDefOverride(HFInvMassFitter, 1); }; diff --git a/PWGHF/D2H/Macros/config_massfitter.json b/PWGHF/D2H/Macros/config_massfitter.json index 25dc9d50bcc..0baf94cabad 100644 --- a/PWGHF/D2H/Macros/config_massfitter.json +++ b/PWGHF/D2H/Macros/config_massfitter.json @@ -101,21 +101,24 @@ 0.9, 1.6 ], - "MassMin": [ + "MassMin": 2.12, + "_MassMin": [ 2.12, 2.12, 2.12, 2.12, 2.12 ], - "MassMax": [ + "MassMax": 2.42, + "_MassMax": [ 2.42, 2.42, 2.42, 2.42, 2.42 ], - "Rebin": [ + "Rebin": 4, + "_Rebin": [ 4, 4, 4, @@ -128,7 +131,8 @@ "true: likelihood fit", "false: chi2 fit" ], - "BkgFunc": [ + "BkgFunc": 2, + "_BkgFunc": [ 2, 2, 2, @@ -144,7 +148,8 @@ "5 for Poly3", "6 for NoBkg" ], - "SgnFunc": [ + "SgnFunc": 0, + "_SgnFunc": [ 0, 0, 0, @@ -155,8 +160,12 @@ "0 for SingleGaus", "1 for DoubleGaus", "2 for DoubleGausSigmaRatioPar", - "3 for GausSec" + "3 for GausSec", + "4 for DoubleSidedCrystalBall" ], + "NSigmaForSideband": 3, + "NSigmaForSignal": 3, "DrawBgPrefit": true, - "HighlightPeakRegion": true + "HighlightPeakRegion": true, + "RandomSeed": -1 } diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 5937d12e0ba..3b05aa6f9ed 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,8 @@ using namespace rapidjson; +constexpr int UndefValueInt{-999}; + void runMassFitter(const std::string& configFileName = "config_massfitter.json"); TFile* openFileWithNullptrCheck(const std::string& fileName, const std::string& option = "read"); @@ -66,7 +69,12 @@ T readJsonField(const Document& config, const std::string& fieldName); template void readJsonVector(std::vector& vec, const Document& config, const std::string& fieldName, bool isRequired = false); -void divideCanvas(TCanvas* c, int nSliceVarBins); +template +void readJsonVectorFlexible(std::vector& vec, const Document& config, int nHistograms, const std::string& fieldName, bool isRequired = false); + +void readJsonVectorFromHisto(std::vector& vec, const Document& config, const std::string& fileNameFieldName, const std::string& histoNameFieldName); + +void divideCanvas(TCanvas* c, int nHistograms); void setHistoStyle(TH1* histo, Color_t color = kBlack, Size_t markerSize = 1); @@ -84,6 +92,10 @@ void runMassFitter(const std::string& configFileName) config.ParseStream(is); fclose(configFile); + if (config.HasParseError()) { + throw std::runtime_error("ERROR: Parsing the configuration json file failed. Check the config for correct formatting"); + } + bool const isMc = readJsonField(config, "IsMC"); bool const writeSignalPar = readJsonField(config, "WriteSignalPar", true); std::string const particleName = readJsonField(config, "Particle"); @@ -95,9 +107,11 @@ void runMassFitter(const std::string& configFileName) std::vector inputHistoName; std::vector promptHistoName; std::vector fdHistoName; + std::vector signalHistoName; std::vector reflHistoName; std::vector promptSecPeakHistoName; std::vector fdSecPeakHistoName; + std::vector signalSecPeakHistoName; std::vector sliceVarMin; std::vector sliceVarMax; std::vector massMin; @@ -109,29 +123,48 @@ void runMassFitter(const std::string& configFileName) std::vector nRebin; std::vector bkgFunc; std::vector sgnFunc; - - readJsonVector(inputHistoName, config, "InputHistoName", true); + std::vector dscbAlphaLInitial; + std::vector dscbAlphaLLower; + std::vector dscbAlphaLUpper; + std::vector dscbAlphaRInitial; + std::vector dscbAlphaRLower; + std::vector dscbAlphaRUpper; + std::vector dscbNLInitial; + std::vector dscbNLLower; + std::vector dscbNLUpper; + std::vector dscbNRInitial; + std::vector dscbNRLower; + std::vector dscbNRUpper; + + readJsonVector(inputHistoName, config, "InputHistoName"); readJsonVector(promptHistoName, config, "PromptHistoName"); readJsonVector(fdHistoName, config, "FDHistoName"); + readJsonVector(signalHistoName, config, "SignalHistoName"); + const std::array possibleInputHistogramSizes{inputHistoName.size(), promptHistoName.size(), fdHistoName.size(), signalHistoName.size()}; + const int nHistograms = static_cast(*std::max_element(possibleInputHistogramSizes.begin(), possibleInputHistogramSizes.end())); + readJsonVector(reflHistoName, config, "ReflHistoName"); readJsonVector(promptSecPeakHistoName, config, "PromptSecPeakHistoName"); readJsonVector(fdSecPeakHistoName, config, "FDSecPeakHistoName"); + readJsonVector(signalSecPeakHistoName, config, "SignalSecPeakHistoName"); const bool fixMean = readJsonField(config, "FixMean", false); const std::string meanFile = readJsonField(config, "MeanFile", ""); - readJsonVector(fixMeanManual, config, "FixMeanManual"); + readJsonVectorFlexible(fixMeanManual, config, nHistograms, "FixMeanManual"); const bool fixSigma = readJsonField(config, "FixSigma", false); const std::string sigmaFile = readJsonField(config, "SigmaFile", ""); - readJsonVector(fixSigmaManual, config, "FixSigmaManual"); + readJsonVectorFlexible(fixSigmaManual, config, nHistograms, "FixSigmaManual"); const bool fixSecondSigma = readJsonField(config, "FixSecondSigma", false); const std::string secondSigmaFile = readJsonField(config, "SecondSigmaFile", ""); - readJsonVector(fixSecondSigmaManual, config, "FixSecondSigmaManual"); + readJsonVectorFlexible(fixSecondSigmaManual, config, nHistograms, "FixSecondSigmaManual"); const bool fixFracDoubleGaus = readJsonField(config, "FixFracDoubleGaus", false); const std::string fracDoubleGausFile = readJsonField(config, "FracDoubleGausFile", ""); - readJsonVector(fixFracDoubleGausManual, config, "FixFracDoubleGausManual"); + readJsonVectorFlexible(fixFracDoubleGausManual, config, nHistograms, "FixFracDoubleGausManual"); + + const bool fixDscbTailParams = readJsonField(config, "FixDscbTailParams", false); const TString sliceVarName = readJsonField(config, "SliceVarName"); const TString sliceVarUnit = readJsonField(config, "SliceVarUnit"); @@ -139,26 +172,53 @@ void runMassFitter(const std::string& configFileName) readJsonVector(sliceVarMin, config, "SliceVarMin", true); readJsonVector(sliceVarMax, config, "SliceVarMax", true); - readJsonVector(massMin, config, "MassMin", true); - readJsonVector(massMax, config, "MassMax", true); + readJsonVectorFlexible(massMin, config, nHistograms, "MassMin", true); + readJsonVectorFlexible(massMax, config, nHistograms, "MassMax", true); - readJsonVector(nRebin, config, "Rebin", true); + readJsonVectorFlexible(nRebin, config, nHistograms, "Rebin", true); bool const includeSecPeak = readJsonField(config, "InclSecPeak", false); bool const useLikelihood = readJsonField(config, "UseLikelihood"); - readJsonVector(bkgFunc, config, "BkgFunc", true); - readJsonVector(sgnFunc, config, "SgnFunc", true); + readJsonVectorFlexible(bkgFunc, config, nHistograms, "BkgFunc", true); + readJsonVectorFlexible(sgnFunc, config, nHistograms, "SgnFunc", true); const bool enableRefl = readJsonField(config, "EnableRefl", false); const bool drawBgPrefit = readJsonField(config, "DrawBgPrefit", true); const bool highlightPeakRegion = readJsonField(config, "HighlightPeakRegion", true); - - const int nSliceVarBins = static_cast(sliceVarMin.size()); - std::vector sliceVarLimits(nSliceVarBins + 1); + const int randomSeed = readJsonField(config, "RandomSeed", -1); + const double nSigmaForSideband = readJsonField(config, "NSigmaForSideband", 3.); + const double nSigmaForSignal = readJsonField(config, "NSigmaForSignal", 3.); + + readJsonVector(dscbAlphaLInitial, config, "DscbAlphaLInitial"); + readJsonVector(dscbAlphaLLower, config, "DscbAlphaLLower"); + readJsonVector(dscbAlphaLUpper, config, "DscbAlphaLUpper"); + readJsonVector(dscbAlphaRInitial, config, "DscbAlphaRInitial"); + readJsonVector(dscbAlphaRLower, config, "DscbAlphaRLower"); + readJsonVector(dscbAlphaRUpper, config, "DscbAlphaRUpper"); + readJsonVector(dscbNLInitial, config, "DscbNLInitial"); + readJsonVector(dscbNLLower, config, "DscbNLLower"); + readJsonVector(dscbNLUpper, config, "DscbNLUpper"); + readJsonVector(dscbNRInitial, config, "DscbNRInitial"); + readJsonVector(dscbNRLower, config, "DscbNRLower"); + readJsonVector(dscbNRUpper, config, "DscbNRUpper"); + readJsonVectorFromHisto(dscbAlphaLInitial, config, "DscbParametersFile", "DscbAlphaLInitialHisto"); + readJsonVectorFromHisto(dscbAlphaLLower, config, "DscbParametersFile", "DscbAlphaLLowerHisto"); + readJsonVectorFromHisto(dscbAlphaLUpper, config, "DscbParametersFile", "DscbAlphaLUpperHisto"); + readJsonVectorFromHisto(dscbAlphaRInitial, config, "DscbParametersFile", "DscbAlphaRInitialHisto"); + readJsonVectorFromHisto(dscbAlphaRLower, config, "DscbParametersFile", "DscbAlphaRLowerHisto"); + readJsonVectorFromHisto(dscbAlphaRUpper, config, "DscbParametersFile", "DscbAlphaRUpperHisto"); + readJsonVectorFromHisto(dscbNLInitial, config, "DscbParametersFile", "DscbNLInitialHisto"); + readJsonVectorFromHisto(dscbNLLower, config, "DscbParametersFile", "DscbNLLowerHisto"); + readJsonVectorFromHisto(dscbNLUpper, config, "DscbParametersFile", "DscbNLUpperHisto"); + readJsonVectorFromHisto(dscbNRInitial, config, "DscbParametersFile", "DscbNRInitialHisto"); + readJsonVectorFromHisto(dscbNRLower, config, "DscbParametersFile", "DscbNRLowerHisto"); + readJsonVectorFromHisto(dscbNRUpper, config, "DscbParametersFile", "DscbNRUpperHisto"); + + std::vector sliceVarLimits(nHistograms + 1); auto checkVectorSize = [&](const auto& vec, const std::string& name = "", const bool isEmptyOk = false) { - if (vec.size() != static_cast(nSliceVarBins)) { + if (vec.size() != static_cast(nHistograms)) { if (isEmptyOk && vec.empty()) { return; } @@ -169,9 +229,11 @@ void runMassFitter(const std::string& configFileName) checkVectorSize(inputHistoName, "inputHistoName", true); checkVectorSize(promptHistoName, "promptHistoName", true); checkVectorSize(fdHistoName, "fdHistoName", true); + checkVectorSize(signalHistoName, "signalHistoName", true); checkVectorSize(reflHistoName, "reflHistoName", true); checkVectorSize(promptSecPeakHistoName, "promptSecPeakHistoName", true); checkVectorSize(fdSecPeakHistoName, "fdSecPeakHistoName", true); + checkVectorSize(signalSecPeakHistoName, "signalSecPeakHistoName", true); checkVectorSize(sliceVarMin, "sliceVarMin"); checkVectorSize(sliceVarMax, "sliceVarMax"); checkVectorSize(massMin, "massMin"); @@ -183,8 +245,36 @@ void runMassFitter(const std::string& configFileName) checkVectorSize(nRebin, "nRebin"); checkVectorSize(bkgFunc, "bkgFunc"); checkVectorSize(sgnFunc, "sgnFunc"); + checkVectorSize(dscbAlphaLInitial, "dscbAlphaLInitial", true); + checkVectorSize(dscbAlphaLLower, "dscbAlphaLLower", true); + checkVectorSize(dscbAlphaLUpper, "dscbAlphaLUpper", true); + checkVectorSize(dscbAlphaRInitial, "dscbAlphaRInitial", true); + checkVectorSize(dscbAlphaRLower, "dscbAlphaRLower", true); + checkVectorSize(dscbAlphaRUpper, "dscbAlphaRUpper", true); + checkVectorSize(dscbNLInitial, "dscbNLInitial", true); + checkVectorSize(dscbNLLower, "dscbNLLower", true); + checkVectorSize(dscbNLUpper, "dscbNLUpper", true); + checkVectorSize(dscbNRInitial, "dscbNRInitial", true); + checkVectorSize(dscbNRLower, "dscbNRLower", true); + checkVectorSize(dscbNRUpper, "dscbNRUpper", true); + + auto checkVectorSizeMcHistograms = [](const auto& vecSignal, const auto& vecPrompt, const auto& vecFd) { + const auto signalSize = vecSignal.size(); + const auto promptSize = vecPrompt.size(); + const auto fdSize = vecFd.size(); + if (!((signalSize > 0 && promptSize == 0 && fdSize == 0) || (signalSize == 0 && promptSize > 0 && fdSize > 0))) { + throw std::runtime_error("ERROR: either signal histogram must be provided or both prompt and fd, but not all three. Exit"); + } + }; + + if ((!isMc && enableRefl) || isMc) { + checkVectorSizeMcHistograms(signalHistoName, promptHistoName, fdHistoName); + } + if (isMc && includeSecPeak) { + checkVectorSizeMcHistograms(signalSecPeakHistoName, promptSecPeakHistoName, fdSecPeakHistoName); + } - for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nHistograms; iSliceVar++) { sliceVarLimits[iSliceVar] = sliceVarMin[iSliceVar]; if (bkgFunc[iSliceVar] < 0 || bkgFunc[iSliceVar] >= HFInvMassFitter::NTypesOfBkgPdf) { @@ -197,7 +287,7 @@ void runMassFitter(const std::string& configFileName) throw std::runtime_error("ERROR: only SingleGaus, DoubleGaus and DoubleGausSigmaRatioPar signal functions supported! Exit"); } } - sliceVarLimits[nSliceVarBins] = sliceVarMax[nSliceVarBins - 1]; + sliceVarLimits[nHistograms] = sliceVarMax[nHistograms - 1]; struct DecayInfo { std::string decayProducts; @@ -227,24 +317,36 @@ void runMassFitter(const std::string& configFileName) TFile* inputFileRefl = enableRefl ? openFileWithNullptrCheck(reflFileName) : nullptr; - std::vector hMassSgn(nSliceVarBins); - std::vector hMassRefl(nSliceVarBins); - std::vector hMass(nSliceVarBins); + std::vector hMassSgn(nHistograms); + std::vector hMassRefl(nHistograms); + std::vector hMass(nHistograms); - for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nHistograms; iSliceVar++) { if (!isMc) { hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, inputHistoName[iSliceVar]); if (enableRefl) { hMassRefl[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, reflHistoName[iSliceVar]); - hMassSgn[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, fdHistoName[iSliceVar]); - hMassSgn[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFileRefl, promptHistoName[iSliceVar])); + if (!signalHistoName.empty()) { + hMassSgn[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, signalHistoName[iSliceVar]); + } else { + hMassSgn[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, fdHistoName[iSliceVar]); + hMassSgn[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFileRefl, promptHistoName[iSliceVar])); + } } } else { - hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, promptHistoName[iSliceVar]); - hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdHistoName[iSliceVar])); + if (!signalHistoName.empty()) { + hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, signalHistoName[iSliceVar]); + } else { + hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, promptHistoName[iSliceVar]); + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdHistoName[iSliceVar])); + } if (includeSecPeak) { - hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, promptSecPeakHistoName[iSliceVar])); - hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdSecPeakHistoName[iSliceVar])); + if (!signalHistoName.empty()) { + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, signalSecPeakHistoName[iSliceVar])); + } else { + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, promptSecPeakHistoName[iSliceVar])); + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdSecPeakHistoName[iSliceVar])); + } } } hMass[iSliceVar]->SetDirectory(nullptr); @@ -255,18 +357,22 @@ void runMassFitter(const std::string& configFileName) } // define output histos - auto* hRawYieldsSignal = new TH1D("hRawYieldsSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsSignalCounted = new TH1D("hRawYieldsSignalCounted", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield via bin count", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsBkg = new TH1D("hRawYieldsBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");Background (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsSgnOverBkg = new TH1D("hRawYieldsSgnOverBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");S/B (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsSignificance = new TH1D("hRawYieldsSignificance", ";" + sliceVarName + "(" + sliceVarUnit + ");significance (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsChiSquareBkg = new TH1D("hRawYieldsChiSquareBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsChiSquareTotal = new TH1D("hRawYieldsChiSquareTotal", ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nSliceVarBins, sliceVarLimits.data()); - auto* hReflectionOverSignal = new TH1D("hReflectionOverSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");Refl/Signal", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsMean = new TH1D("hRawYieldsMean", ";" + sliceVarName + "(" + sliceVarUnit + ");mean (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsSigma = new TH1D("hRawYieldsSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsSecSigma = new TH1D("hRawYieldsSecSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); - auto* hRawYieldsFracDoubleGaus = new TH1D("hRawYieldsFracDoubleGaus", ";" + sliceVarName + "(" + sliceVarUnit + ");fraction of double gaussian", nSliceVarBins, sliceVarLimits.data()); + auto* hRawYieldsSignal = new TH1D("hRawYieldsSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsSignalCounted = new TH1D("hRawYieldsSignalCounted", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield via bin count", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsBkg = new TH1D("hRawYieldsBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");Background (3#sigma)", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsSgnOverBkg = new TH1D("hRawYieldsSgnOverBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");S/B (3#sigma)", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsSignificance = new TH1D("hRawYieldsSignificance", ";" + sliceVarName + "(" + sliceVarUnit + ");significance (3#sigma)", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsChiSquareBkg = new TH1D("hRawYieldsChiSquareBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsChiSquareTotal = new TH1D("hRawYieldsChiSquareTotal", ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nHistograms, sliceVarLimits.data()); + auto* hReflectionOverSignal = new TH1D("hReflectionOverSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");Refl/Signal", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsMean = new TH1D("hRawYieldsMean", ";" + sliceVarName + "(" + sliceVarUnit + ");mean (GeV/#it{c}^{2})", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsSigma = new TH1D("hRawYieldsSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsSecSigma = new TH1D("hRawYieldsSecSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsFracDoubleGaus = new TH1D("hRawYieldsFracDoubleGaus", ";" + sliceVarName + "(" + sliceVarUnit + ");fraction of double gaussian", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsDscbAlphaL = new TH1D("hRawYieldsDscbAlphaL", ";" + sliceVarName + "(" + sliceVarUnit + ");#alpha_{L}", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsDscbAlphaR = new TH1D("hRawYieldsDscbAlphaR", ";" + sliceVarName + "(" + sliceVarUnit + ");#alpha_{R}", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsDscbNL = new TH1D("hRawYieldsDscbNL", ";" + sliceVarName + "(" + sliceVarUnit + ");n_{L}", nHistograms, sliceVarLimits.data()); + auto* hRawYieldsDscbNR = new TH1D("hRawYieldsDscbNR", ";" + sliceVarName + "(" + sliceVarUnit + ");n_{R}", nHistograms, sliceVarLimits.data()); enum { ConfigMassMin = 1, @@ -275,10 +381,11 @@ void runMassFitter(const std::string& configFileName) ConfigFixSigma, ConfigBkgFunc, ConfigSgnFunc, + ConfigRandomSeed, NConfigsToSave }; - auto* hFitConfig = new TH2F("hfitConfig", "Fit Configurations", NConfigsToSave - 1, 0, NConfigsToSave - 1, nSliceVarBins, sliceVarLimits.data()); - const char* hFitConfigXLabel[NConfigsToSave - 1] = {"mass min", "mass max", "rebin num", "fix sigma", "bkg func", "sgn func"}; + auto* hFitConfig = new TH2F("hfitConfig", "Fit Configurations", NConfigsToSave - 1, 0, NConfigsToSave - 1, nHistograms, sliceVarLimits.data()); + const char* hFitConfigXLabel[NConfigsToSave - 1] = {"mass min", "mass max", "rebin num", "fix sigma", "bkg func", "sgn func", "rnd seed"}; hFitConfig->SetStats(false); for (int i = 0; i < NConfigsToSave - 1; i++) { hFitConfig->GetXaxis()->SetBinLabel(i + 1, hFitConfigXLabel[i]); @@ -299,8 +406,12 @@ void runMassFitter(const std::string& configFileName) setHistoStyle(hRawYieldsSigma); setHistoStyle(hRawYieldsSecSigma); setHistoStyle(hRawYieldsFracDoubleGaus); + setHistoStyle(hRawYieldsDscbAlphaL); + setHistoStyle(hRawYieldsDscbAlphaR); + setHistoStyle(hRawYieldsDscbNL); + setHistoStyle(hRawYieldsDscbNR); - auto getHistToFix = [&nSliceVarBins](bool const& isFix, std::vector const& fixManual, std::string const& fixFileName, std::string const& var) -> TH1* { + auto getHistToFix = [&nHistograms](bool const& isFix, std::vector const& fixManual, std::string const& fixFileName, std::string const& var) -> TH1* { TH1* histToFix = nullptr; if (isFix) { if (fixManual.empty()) { @@ -308,7 +419,7 @@ void runMassFitter(const std::string& configFileName) const std::string histName = "hRawYields" + var; histToFix = getObjectWithNullPtrCheck(fixInputFile, histName); histToFix->SetDirectory(nullptr); - if (histToFix->GetNbinsX() != nSliceVarBins) { + if (histToFix->GetNbinsX() != nHistograms) { throw std::runtime_error("Different number of bins for this analysis and histo for fixed " + var); } fixInputFile->Close(); @@ -323,19 +434,19 @@ void runMassFitter(const std::string& configFileName) TH1* hFracDoubleGausToFix = getHistToFix(fixFracDoubleGaus, fixFracDoubleGausManual, fracDoubleGausFile, "FracDoubleGaus"); int canvasSize[2] = {1920, 1080}; - if (nSliceVarBins == 1) { + if (nHistograms == 1) { canvasSize[0] = 500; canvasSize[1] = 500; } int constexpr NCanvasesMax = 20; // do not put more than 20 bins per canvas to make them visible - const int nCanvases = std::ceil(static_cast(nSliceVarBins) / NCanvasesMax); + const int nCanvases = std::ceil(static_cast(nHistograms) / NCanvasesMax); std::vector canvasMass(nCanvases); std::vector canvasResiduals(nCanvases); std::vector canvasRatio(nCanvases); std::vector canvasRefl(nCanvases); for (int iCanvas = 0; iCanvas < nCanvases; iCanvas++) { - const int nPads = (nCanvases == 1) ? nSliceVarBins : NCanvasesMax; + const int nPads = (nCanvases == 1) ? nHistograms : NCanvasesMax; canvasMass[iCanvas] = new TCanvas(Form("canvasMass%d", iCanvas), Form("canvasMass%d", iCanvas), canvasSize[0], canvasSize[1]); divideCanvas(canvasMass[iCanvas], nPads); @@ -351,7 +462,7 @@ void runMassFitter(const std::string& configFileName) } } - for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nHistograms; iSliceVar++) { const int iCanvas = std::floor(static_cast(iSliceVar) / NCanvasesMax); hMass[iSliceVar]->Rebin(nRebin[iSliceVar]); @@ -369,8 +480,10 @@ void runMassFitter(const std::string& configFileName) double reflOverSgn = 0; - HFInvMassFitter* massFitter = new HFInvMassFitter(hMass[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], bkgFunc[iSliceVar], sgnFunc[iSliceVar]); + HFInvMassFitter* massFitter = new HFInvMassFitter(hMass[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], bkgFunc[iSliceVar], sgnFunc[iSliceVar], randomSeed); massFitter->setDrawBgPrefit(drawBgPrefit); + massFitter->setNumberOfSigmaForSidebands(nSigmaForSideband); + massFitter->setNumberOfSigmaForSignal(nSigmaForSignal); massFitter->setHighlightPeakRegion(highlightPeakRegion); massFitter->setInitialGaussianMean(massPDG); massFitter->setParticlePdgMass(massPDG); @@ -398,6 +511,10 @@ void runMassFitter(const std::string& configFileName) setFixedValue(fixSigma, fixSigmaManual, hSigmaToFix, std::bind(&HFInvMassFitter::setFixGaussianSigma, massFitter, std::placeholders::_1), "SIGMA"); setFixedValue(fixSecondSigma, fixSecondSigmaManual, hSecondSigmaToFix, std::bind(&HFInvMassFitter::setFixSecondGaussianSigma, massFitter, std::placeholders::_1), "SECOND SIGMA"); setFixedValue(fixFracDoubleGaus, fixFracDoubleGausManual, hFracDoubleGausToFix, std::bind(&HFInvMassFitter::setFixFrac2Gaus, massFitter, std::placeholders::_1), "FRAC DOUBLE GAUS"); + setFixedValue(fixDscbTailParams, dscbAlphaLInitial, nullptr, std::bind(&HFInvMassFitter::setFixDscbAlphaL, massFitter, std::placeholders::_1), "DSCB ALPHA LEFT"); + setFixedValue(fixDscbTailParams, dscbAlphaRInitial, nullptr, std::bind(&HFInvMassFitter::setFixDscbAlphaR, massFitter, std::placeholders::_1), "DSCB ALPHA RIGHT"); + setFixedValue(fixDscbTailParams, dscbNLInitial, nullptr, std::bind(&HFInvMassFitter::setFixDscbNL, massFitter, std::placeholders::_1), "DSCB N LEFT"); + setFixedValue(fixDscbTailParams, dscbNRInitial, nullptr, std::bind(&HFInvMassFitter::setFixDscbNR, massFitter, std::placeholders::_1), "DSCB N RIGHT"); if (!isMc && enableRefl) { reflOverSgn = hMassSgn[iSliceVar]->Integral(hMassSgn[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassSgn[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)); @@ -406,10 +523,28 @@ void runMassFitter(const std::string& configFileName) massFitter->setTemplateReflections(hMassRefl[iSliceVar]); } + auto setDscbParameter = [&](const std::vector& vec, void (HFInvMassFitter::*setter)(double)) { + if (static_cast(vec.size()) == nHistograms) { + (massFitter->*setter)(vec[iSliceVar]); + } + }; + setDscbParameter(dscbAlphaLInitial, &HFInvMassFitter::setDscbAlphaLInitialValue); + setDscbParameter(dscbAlphaLLower, &HFInvMassFitter::setDscbAlphaLLowLimit); + setDscbParameter(dscbAlphaLUpper, &HFInvMassFitter::setDscbAlphaLUpLimit); + setDscbParameter(dscbAlphaRInitial, &HFInvMassFitter::setDscbAlphaRInitialValue); + setDscbParameter(dscbAlphaRLower, &HFInvMassFitter::setDscbAlphaRLowLimit); + setDscbParameter(dscbAlphaRUpper, &HFInvMassFitter::setDscbAlphaRUpLimit); + setDscbParameter(dscbNLInitial, &HFInvMassFitter::setDscbNLInitialValue); + setDscbParameter(dscbNLLower, &HFInvMassFitter::setDscbNLLowLimit); + setDscbParameter(dscbNLUpper, &HFInvMassFitter::setDscbNLUpLimit); + setDscbParameter(dscbNRInitial, &HFInvMassFitter::setDscbNRInitialValue); + setDscbParameter(dscbNRLower, &HFInvMassFitter::setDscbNRLowLimit); + setDscbParameter(dscbNRUpper, &HFInvMassFitter::setDscbNRUpLimit); + massFitter->doFit(); auto drawOnCanvas = [&](std::vector& canvas, std::function drawer) { - if (nSliceVarBins > 1) { + if (nHistograms > 1) { canvas[iCanvas]->cd(iSliceVar - NCanvasesMax * iCanvas + 1); } else { canvas[iCanvas]->cd(); @@ -442,6 +577,14 @@ void runMassFitter(const std::string& configFileName) const double meanErr = massFitter->getMeanUncertainty(); const double sigma = massFitter->getSigma(); const double sigmaErr = massFitter->getSigmaUncertainty(); + const double dscbAlphaL = massFitter->getDscbAlphaL(); + const double dscbAlphaR = massFitter->getDscbAlphaR(); + const double dscbNL = massFitter->getDscbNL(); + const double dscbNR = massFitter->getDscbNR(); + const double dscbAlphaLErr = massFitter->getDscbAlphaLUncertainty(); + const double dscbAlphaRErr = massFitter->getDscbAlphaRUncertainty(); + const double dscbNErrL = massFitter->getDscbNLUncertainty(); + const double dscbNErrR = massFitter->getDscbNRUncertainty(); hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); @@ -462,6 +605,14 @@ void runMassFitter(const std::string& configFileName) hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); hReflectionOverSignal->SetBinContent(iSliceVar + 1, reflOverSgn); + hRawYieldsDscbAlphaL->SetBinContent(iSliceVar + 1, dscbAlphaL); + hRawYieldsDscbAlphaL->SetBinError(iSliceVar + 1, dscbAlphaLErr); + hRawYieldsDscbAlphaR->SetBinContent(iSliceVar + 1, dscbAlphaR); + hRawYieldsDscbAlphaR->SetBinError(iSliceVar + 1, dscbAlphaRErr); + hRawYieldsDscbNL->SetBinContent(iSliceVar + 1, dscbNL); + hRawYieldsDscbNL->SetBinError(iSliceVar + 1, dscbNErrL); + hRawYieldsDscbNR->SetBinContent(iSliceVar + 1, dscbNR); + hRawYieldsDscbNR->SetBinError(iSliceVar + 1, dscbNErrR); if (sgnFunc[iSliceVar] != HFInvMassFitter::SingleGaus) { // TODO foresee DSCB and Voigt cases const double secSigma = massFitter->getSecSigma(); @@ -485,6 +636,7 @@ void runMassFitter(const std::string& configFileName) } hFitConfig->SetBinContent(ConfigBkgFunc, iSliceVar + 1, bkgFunc[iSliceVar]); hFitConfig->SetBinContent(ConfigSgnFunc, iSliceVar + 1, sgnFunc[iSliceVar]); + hFitConfig->SetBinContent(ConfigRandomSeed, iSliceVar + 1, randomSeed); } // save output histograms @@ -500,7 +652,7 @@ void runMassFitter(const std::string& configFileName) } } - for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nHistograms; iSliceVar++) { hMass[iSliceVar]->Write(); } hRawYieldsSignal->Write(); @@ -517,6 +669,12 @@ void runMassFitter(const std::string& configFileName) if (enableRefl) { hReflectionOverSignal->Write(); } + if (std::find(sgnFunc.begin(), sgnFunc.end(), HFInvMassFitter::DoubleSidedCrystalBall) != sgnFunc.end()) { + hRawYieldsDscbAlphaL->Write(); + hRawYieldsDscbAlphaR->Write(); + hRawYieldsDscbNL->Write(); + hRawYieldsDscbNR->Write(); + } hFitConfig->Write(); outputFile.Close(); @@ -548,10 +706,10 @@ void setHistoStyle(TH1* histo, Color_t color, Size_t markerSize) histo->SetLineColor(color); } -void divideCanvas(TCanvas* canvas, int nSliceVarBins) +void divideCanvas(TCanvas* canvas, int nHistograms) { - int nCols = std::ceil(std::sqrt(nSliceVarBins)); - int nRows = std::ceil(static_cast(nSliceVarBins) / nCols); + int nCols = std::ceil(std::sqrt(nHistograms)); + int nRows = std::ceil(static_cast(nHistograms) / nCols); canvas->Divide(nCols, nRows); } @@ -629,6 +787,48 @@ void readJsonVector(std::vector& vec, const Document& config, const std::stri } } +template +void readJsonVectorFlexible(std::vector& vec, const Document& config, int nHistograms, const std::string& fieldName, bool isRequired) +{ + if constexpr (!(std::is_same_v, int> || std::is_same_v, double>)) { + static_assert(AlwaysFalse, "readJsonVectorFlexible(): unsupported type!"); + } + if (!vec.empty()) { + throw std::runtime_error("readJsonVectorFlexible(): vector is not empty!"); + } + if (!config.HasMember(fieldName.c_str())) { + if (isRequired) { + throw std::runtime_error("readJsonVectorFlexible(): missing required field " + fieldName); + } else { + return; + } + } + if (config[fieldName.c_str()].IsArray()) { + readJsonVector(vec, config, fieldName); + } else { + const T value = readJsonField(config, fieldName); + vec.assign(nHistograms, value); + } +} + +void readJsonVectorFromHisto(std::vector& vec, const Document& config, const std::string& fileNameFieldName, const std::string& histoNameFieldName) +{ + if (!vec.empty()) { + throw std::runtime_error("readJsonVectorFromHisto(): vector is not empty!"); + } + const auto fileName = readJsonField(config, fileNameFieldName, ""); + const auto histoName = readJsonField(config, histoNameFieldName, ""); + if (fileName.empty() || histoName.empty()) { + return; + } + TFile* inputFile = openFileWithNullptrCheck(fileName); + TH1* histo = getObjectWithNullPtrCheck(inputFile, histoName); + for (int iBin = 1; iBin <= histo->GetNbinsX(); iBin++) { + vec.push_back(histo->GetBinContent(iBin)); + } + inputFile->Close(); +} + int main(int argc, const char* argv[]) { if (argc == 1) { From 8ed016442f410c51f51ceaf571fbfc3a14f0f46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 5 May 2026 15:35:57 +0200 Subject: [PATCH 045/449] [PWGHF] Fix includes (#16091) --- PWGHF/D2H/Tasks/taskNetCharmFluctuations.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskNetCharmFluctuations.cxx b/PWGHF/D2H/Tasks/taskNetCharmFluctuations.cxx index c6a980eda51..972dc2b6e5c 100644 --- a/PWGHF/D2H/Tasks/taskNetCharmFluctuations.cxx +++ b/PWGHF/D2H/Tasks/taskNetCharmFluctuations.cxx @@ -22,12 +22,11 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include -#include #include #include +#include #include #include #include @@ -35,10 +34,13 @@ #include #include +#include + #include #include #include #include +#include #include using namespace o2; From 1381075d173f3319531385b239fea1682636e166 Mon Sep 17 00:00:00 2001 From: Stefano Cannito <143754257+scannito@users.noreply.github.com> Date: Tue, 5 May 2026 15:59:56 +0200 Subject: [PATCH 046/449] [PWGLF] Propagate uncertainty from efficiency if required (#16116) --- .../Strangeness/phiStrangeCorrelation.cxx | 348 ++++++++++-------- 1 file changed, 202 insertions(+), 146 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index e9aa45fd7c8..36726e80d5d 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -80,73 +80,8 @@ enum AssociatedParticleType { kAssocPartSize }; -/*enum ParticleOfInterest { - Phi = 0, - K0S, - Pion, - ParticleOfInterestSize -};*/ - -/* -#define LIST_OF_PARTICLES_OF_INTEREST \ - X(Phi) \ - X(K0S) \ - X(Pion) \ - //X(PionTPC) \ - //X(PionTPCTOF) - -enum ParticleOfInterest { -#define X(name) name, - LIST_OF_PARTICLES_OF_INTEREST -#undef X - ParticleOfInterestSize -}; - -static constexpr std::array particleOfInterestLabels{ -#define X(name) #name, - LIST_OF_PARTICLES_OF_INTEREST -#undef X -}; - -static constexpr auto particleOfInterestLabels = std::to_array({ -#define X(name) #name, - LIST_OF_PARTICLES_OF_INTEREST -#undef X -}); -*/ - using EffMapPtr = std::variant, std::shared_ptr>; -/*struct BoundEfficiencyMap { - using CoordsTuple = std::tuple; - - const TH3* effMap; - CoordsTuple coords; - - BoundEfficiencyMap(const std::shared_ptr& effMap, float x, float y, float z) : effMap(effMap.get()), coords(x, y, z) {} - BoundEfficiencyMap(const std::shared_ptr& effMap, const CoordsTuple& coords) : effMap(effMap.get()), coords(coords) {} - - float getBinEfficiency() const - { - if (!effMap) { - return 1.0f; - } - - const auto& [x, y, z] = coords; - return effMap->GetBinContent(effMap->FindFixBin(x, y, z)); - } - - float interpolateEfficiency() const - { - if (!effMap) { - return 1.0f; - } - - const auto& [x, y, z] = coords; - return effMap->Interpolate(x, y, z); - } -};*/ - struct BoundEfficiencyMap { using CoordsTuple = std::tuple; @@ -156,12 +91,12 @@ struct BoundEfficiencyMap { BoundEfficiencyMap(const EffMapPtr& effMap, float x, float y, float z) : effMap(effMap), coords(x, y, z) {} BoundEfficiencyMap(const EffMapPtr& effMap, const CoordsTuple& coords) : effMap(effMap), coords(coords) {} - float getBinEfficiency() const + std::pair getBinEfficiencyAndError() const { return std::visit( - [this](auto&& mapPtr) -> float { + [this](auto&& mapPtr) -> std::pair { if (!mapPtr) - return 1.0f; + return {1.0f, 0.0f}; const auto& [x, y, z] = coords; @@ -170,9 +105,11 @@ struct BoundEfficiencyMap { // Compile-time branching: generates the exact correct function call if constexpr (std::is_same_v) { - return mapPtr->GetBinContent(mapPtr->FindFixBin(y, z)); // 2D case only + int bin = mapPtr->FindFixBin(y, z); // 2D case only + return {mapPtr->GetBinContent(bin), mapPtr->GetBinError(bin)}; } else { - return mapPtr->GetBinContent(mapPtr->FindFixBin(x, y, z)); // Full 3D case + int bin = mapPtr->FindFixBin(x, y, z); // Full 3D case + return {mapPtr->GetBinContent(bin), mapPtr->GetBinError(bin)}; } }, effMap); @@ -264,7 +201,8 @@ struct PhiStrangenessCorrelation { struct : ConfigurableGroup { Configurable applyEfficiency{"applyEfficiency", false, "Use efficiency for filling histograms"}; Configurable useEffInterpolation{"useEffInterpolation", false, "If true, interpolates efficiency map, else uses bin center"}; - Configurable applyPhiEfficiency{"applyPhiEfficiency", true, "Apply efficiency for Phi candidates"}; + Configurable applyPhiEfficiency{"applyPhiEfficiency", false, "Apply efficiency for Phi candidates"}; + Configurable propagateEffError{"propagateEffError", false, "Propagate efficiency error"}; } efficiencyConfigs; // Configurable for event mixing @@ -324,9 +262,8 @@ struct PhiStrangenessCorrelation { using BinningTypeVertexCent = ColumnBinningPolicy; BinningTypeVertexCent binningOnVertexAndCent{{axisVertexMixing, axisCentralityMixing}, true}; - static constexpr std::array phiMassRegionLabels{"Signal", "Sideband"}; - // static constexpr std::array particleOfInterestLabels{"Phi", "K0S", "Pion" /*"PionTPC", "PionTPCTOF"*/}; - static constexpr std::array assocParticleLabels{"K0S", "Xi", "Pi"}; + static constexpr std::array PhiMassRegionLabels{"Signal", "Sideband"}; + static constexpr std::array AssocParticleLabels{"K0S", "Xi", "Pi"}; // Light structures to store only the necessary information for the correlation analysis at MCGen level struct MiniParticle { @@ -377,7 +314,7 @@ struct PhiStrangenessCorrelation { histos.add("phiPi/h6PhiPiTPCDataME", "Invariant mass of Phi vs nSigmaTPC Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); histos.add("phiPi/h6PhiPiTOFDataME", "Invariant mass of Phi vs nSigmaTOF Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); - for (const auto& label : phiMassRegionLabels) { + for (const auto& label : PhiMassRegionLabels) { histos.add(fmt::format("phiK0S/h5PhiK0SData{}", label).c_str(), "Deltay vs deltaphi for Phi and K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, deltaphiAxis}); histos.add(fmt::format("phiPi/h5PhiPiData{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); @@ -459,7 +396,7 @@ struct PhiStrangenessCorrelation { // Only load the associated maps that are explicitly enabled for (size_t i = 0; i < kAssocPartSize; ++i) { if (doAssocCorrelations[i]) - fetchSingleEfficiencyMapFromCCDB(effMapsAssoc[i], assocParticleLabels[i]); + fetchSingleEfficiencyMapFromCCDB(effMapsAssoc[i], AssocParticleLabels[i]); } } @@ -473,14 +410,39 @@ struct PhiStrangenessCorrelation { // Compute weight based on efficiencies template - float computeWeight(const BoundEffMaps&... boundEffMaps) + std::pair computeWeightAndError(const BoundEffMaps&... boundEffMaps) { if (!efficiencyConfigs.applyEfficiency) - return 1.0f; + return {1.0f, 0.0f}; + + float effTot = 1.0f; + float relErrSqSum = 0.0f; + + auto processMap = [&](const auto& boundMap) { + auto [eff, err] = boundMap.getBinEfficiencyAndError(); // Unpack efficiency and error from the map + + if (efficiencyConfigs.useEffInterpolation) { + eff = boundMap.interpolateEfficiency(); + // For simplicity, we keep the error from the bin content even when interpolating, but this can be refined if needed + } + + effTot *= eff; - float totalEfficiency = ((efficiencyConfigs.useEffInterpolation ? boundEffMaps.interpolateEfficiency() : boundEffMaps.getBinEfficiency()) * ...); + if (eff > 0.0f) { + float mapErr = efficiencyConfigs.propagateEffError ? err : 0.0f; // Optionally propagate error, otherwise treat as zero + relErrSqSum += (mapErr / eff) * (mapErr / eff); + } + }; + + (processMap(boundEffMaps), ...); // Fold expression to process all bound efficiency maps + + if (effTot <= 0.0f) + return {1.0f, 0.0f}; - return totalEfficiency <= 0.0f ? 1.0f : 1.0f / totalEfficiency; + float weight = 1.0f / effTot; + float weightErr = weight * std::sqrt(relErrSqSum); // Propagate relative error to the weight + + return {weight, weightErr}; } float getDeltaPhi(float phiTrigger, float phiAssociated) @@ -497,6 +459,72 @@ struct PhiStrangenessCorrelation { return std::distance(binsMult->begin(), it) - 1; } + template + void customFillHist(auto histId, const std::pair& weightPair, Args... coords) + { + auto hist = histos.get(histId); + if (!hist) { + return; + } + + // Extract the weight and its propagated uncertainty + auto [w, wErr] = weightPair; + + // Find the global bin number for the given physical coordinates + int bin = hist->FindFixBin(coords...); + + // Retrieve the previous bin content and its absolute error + double prevContent = hist->GetBinContent(bin); + double prevErr = hist->GetBinError(bin); + + // Calculate the new content by adding the current weight + double newContent = prevContent + w; + + // Error propagation in quadrature: + // prevErr^2 : previous accumulated variance + // (w * w) : statistical fluctuation added by this specific particle count + // (wErr * wErr) : systematic uncertainty added by the efficiency map inaccuracy + double newErr = std::sqrt(prevErr * prevErr + (w * w) + (wErr * wErr)); + + // Update the histogram bin + hist->SetBinContent(bin, newContent); + hist->SetBinError(bin, newErr); + } + + template + void customFillTHn(auto histId, const std::pair& weightPair, Args... coords) + { + auto hist = histos.get(histId); + if (!hist) { + return; + } + + // Extract the weight and its propagated uncertainty + auto [w, wErr] = weightPair; + + // Create an array of floats for the coordinates to pass to GetBin and SetBinContent + double coordArray[] = {static_cast(coords)...}; + + // Find the bin number. + // The 'true' flag is mandatory: it allocates the bin in memory if it doesn't exist yet. + auto bin = hist->GetBin(coordArray, true); + + // Retrieve the previous content and the squared error (variance) + double prevContent = hist->GetBinContent(bin); + double prevErr2 = hist->GetBinError2(bin); + + // Calculate the new content + double newContent = prevContent + w; + + // Add the new variances to the accumulated variance + // (w * w) is the statistical term, (wErr * wErr) is the map uncertainty term + double newErr2 = prevErr2 + (w * w) + (wErr * wErr); + + // Update the THnSparse bin + hist->SetBinContent(bin, newContent); + hist->SetBinError2(bin, newErr2); // Note: SetBinError2 takes the squared error directly + } + template void processPhiK0SPionSE(TCollision const& collision, TPhiCands const& phiCandidates, TK0SCands const& k0sReduced, TPionCands const& pionTracks) { @@ -527,9 +555,11 @@ struct PhiStrangenessCorrelation { if (efficiencyConfigs.applyEfficiency && efficiencyConfigs.applyPhiEfficiency && phiCand.pt() >= binspTPhi->back()) continue; - float weightPhi = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); + // float weightPhi = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); + auto weightPhi = computeWeightAndError(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); - histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); + // histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); + customFillHist(HIST("phi/h3PhiData"), weightPhi, multiplicity, phiCand.pt(), phiCand.m()); auto processCorrelations = [&](auto fillK0S, auto fillPion) { if (doAssocCorrelations[kK0S]) { @@ -538,8 +568,10 @@ struct PhiStrangenessCorrelation { if (!isK0sValid(k0s)) continue; - float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); + // float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + // BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); + auto weightPhiK0S = computeWeightAndError(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); fillK0S(k0s, weightPhiK0S); } } @@ -550,8 +582,10 @@ struct PhiStrangenessCorrelation { if (!isPionValid(pionTrack)) continue; - float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, pionTrack.pt(), pionTrack.y())); + // float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + // BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, pionTrack.pt(), pionTrack.y())); + auto weightPhiPion = computeWeightAndError(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, pionTrack.pt(), pionTrack.y())); fillPion(pionTrack, weightPhiPion); } } @@ -563,41 +597,50 @@ struct PhiStrangenessCorrelation { auto piTOFHistID = HIST("phiPi/h6PhiPiTOFData"); processCorrelations( - [&](const auto& k0s, float w) { - histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + //[&](const auto& k0s, float w) { + // histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + [&](const auto& k0s, const std::pair& w) { + customFillTHn(k0sHistID, w, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m()); }, - [&](const auto& pion, float w) { - histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); - histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + //[&](const auto& pion, float w) { + // histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + // histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + [&](const auto& pion, const std::pair& w) { + customFillTHn(piTPCHistID, w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC()); + customFillTHn(piTOFHistID, w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF()); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { auto k0sHistID = std::make_tuple(HIST("phiK0S/h5PhiK0SDataSignal"), HIST("phiK0S/h5PhiK0SDataSideband")); auto piHistID = std::make_tuple(HIST("phiPi/h5PhiPiDataSignal"), HIST("phiPi/h5PhiPiDataSideband")); - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; - // auto k0sHistID = HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]); - // auto piHistID = HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]); + // auto k0sHistID = HIST("phiK0S/h5PhiK0SData") + HIST(PhiMassRegionLabels[Idx]); + // auto piHistID = HIST("phiPi/h5PhiPiData") + HIST(PhiMassRegionLabels[Idx]); processCorrelations( - [&](const auto& k0s, float w) { - histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + //[&](const auto& k0s, float w) { + // histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + [&](const auto& k0s, const std::pair& w) { + customFillTHn(std::get(k0sHistID), w, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi())); }, - [&](const auto& pion, float w) { - histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + //[&](const auto& pion, float w) { + // histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + [&](const auto& pion, const std::pair& w) { + customFillTHn(std::get(piHistID), w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi())); }); }); } - /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + /*static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; @@ -612,7 +655,7 @@ struct PhiStrangenessCorrelation { float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); - histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); + histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(PhiMassRegionLabels[Idx]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); } // Loop over all primary pion candidates @@ -620,7 +663,7 @@ struct PhiStrangenessCorrelation { float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); - histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pionTrack.pt(), phiCand.y() - pionTrack.y(), getDeltaPhi(phiCand.phi(), pionTrack.phi()), weightPhiPion); + histos.fill(HIST("phiPi/h5PhiPiData") + HIST(PhiMassRegionLabels[Idx]), multiplicity, phiCand.pt(), pionTrack.pt(), phiCand.y() - pionTrack.y(), getDeltaPhi(phiCand.phi(), pionTrack.phi()), weightPhiPion); } });*/ } @@ -668,8 +711,10 @@ struct PhiStrangenessCorrelation { continue; auto processCorrelations = [&](auto fillK0S) { - float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); + // float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + // BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); + auto weightPhiK0S = computeWeightAndError(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMapsAssoc[kK0S], multiplicity, k0s.pt(), k0s.y())); fillK0S(k0s, weightPhiK0S); }; @@ -677,30 +722,34 @@ struct PhiStrangenessCorrelation { auto k0sHistID = HIST("phiK0S/h6PhiK0SDataME"); processCorrelations( - [&](const auto& k0s, float w) { - histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + //[&](const auto& k0s, float w) { + // histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + [&](const auto& k0s, const std::pair& w) { + customFillTHn(k0sHistID, w, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m()); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { auto k0sHistID = std::make_tuple(HIST("phiK0S/h5PhiK0SDataMESignal"), HIST("phiK0S/h5PhiK0SDataMESideband")); - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; processCorrelations( - [&](const auto& k0s, float w) { - histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + //[&](const auto& k0s, float w) { + // histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + [&](const auto& k0s, const std::pair& w) { + customFillTHn(std::get(k0sHistID), w, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi())); }); }); } - /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + /*static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; @@ -713,7 +762,7 @@ struct PhiStrangenessCorrelation { float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); - histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); + histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(PhiMassRegionLabels[Idx]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); });*/ } } @@ -763,8 +812,10 @@ struct PhiStrangenessCorrelation { continue; auto processCorrelations = [&](auto fillPion) { - float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, piTrack.pt(), piTrack.y())); + // float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + // BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, piTrack.pt(), piTrack.y())); + auto weightPhiPion = computeWeightAndError(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMapsAssoc[kPion], multiplicity, piTrack.pt(), piTrack.y())); fillPion(piTrack, weightPhiPion); }; @@ -773,38 +824,43 @@ struct PhiStrangenessCorrelation { auto piTOFHistID = HIST("phiPi/h6PhiPiTOFDataME"); processCorrelations( - [&](const auto& pion, float w) { - histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); - histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + //[&](const auto& pion, float w) { + // histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + // histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + [&](const auto& pion, const std::pair& w) { + customFillTHn(piTPCHistID, w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC()); + customFillTHn(piTOFHistID, w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF()); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { auto piHistID = std::make_tuple(HIST("phiPi/h5PhiPiDataMESignal"), HIST("phiPi/h5PhiPiDataMESideband")); - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; processCorrelations( - [&](const auto& pion, float w) { - histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + //[&](const auto& pion, float w) { + // histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + [&](const auto& pion, const std::pair& w) { + customFillTHn(std::get(piHistID), w, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi())); }); }); } - /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + /*static_for<0, PhiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; - const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[Idx]; if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); - histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), piTrack.pt(), phiCand.y() - piTrack.y(), getDeltaPhi(phiCand.phi(), piTrack.phi()), weightPhiPion); + histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(PhiMassRegionLabels[Idx]), multiplicity, phiCand.pt(), piTrack.pt(), phiCand.y() - piTrack.y(), getDeltaPhi(phiCand.phi(), piTrack.phi()), weightPhiPion); });*/ } } @@ -999,12 +1055,12 @@ struct PhiStrangenessCorrelation { auto& phiParticle = mcParticles.rawIteratorAt(phiIndices[iTrigg]); static_for<0, assocIndices.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + constexpr unsigned int Idx = i_idx.value; - for (std::size_t iAssoc{0}; iAssoc < assocIndices[i].size(); ++iAssoc) { - auto& assocParticle = mcParticles.rawIteratorAt(assocIndices[i][iAssoc]); + for (std::size_t iAssoc{0}; iAssoc < assocIndices[Idx].size(); ++iAssoc) { + auto& assocParticle = mcParticles.rawIteratorAt(assocIndices[Idx][iAssoc]); - histos.fill(HIST("mcGenClosure/h5Phi") + HIST(assocParticleLabels[i]) + HIST("ClosureGenSE"), multiplicity, phiParticle.pt(), assocParticle.pt(), phiParticle.y() - assocParticle.y(), getDeltaPhi(phiParticle.phi(), assocParticle.phi())); + histos.fill(HIST("mcGenClosure/h5Phi") + HIST(AssocParticleLabels[Idx]) + HIST("ClosureGenSE"), multiplicity, phiParticle.pt(), assocParticle.pt(), phiParticle.y() - assocParticle.y(), getDeltaPhi(phiParticle.phi(), assocParticle.phi())); } }); } @@ -1130,13 +1186,13 @@ struct PhiStrangenessCorrelation { for (const auto& phiParticle : phiParticles) { histos.fill(HIST("phi/h3PhiMCClosureGen"), multiplicity, phiParticle.pt, phiParticle.y); - static_for<0, assocParticleLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; - if (!doAssocCorrelations[i]) + static_for<0, AssocParticleLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; + if (!doAssocCorrelations[Idx]) return; - for (const auto& assocParticle : *(currentAssocParticles[i])) { - histos.fill(HIST("phi") + HIST(assocParticleLabels[i]) + HIST("/h5Phi") + HIST(assocParticleLabels[i]) + HIST("ClosureMCGen"), + for (const auto& assocParticle : *(currentAssocParticles[Idx])) { + histos.fill(HIST("phi") + HIST(AssocParticleLabels[Idx]) + HIST("/h5Phi") + HIST(AssocParticleLabels[Idx]) + HIST("ClosureMCGen"), multiplicity, phiParticle.pt, assocParticle.pt, phiParticle.y - assocParticle.y, getDeltaPhi(phiParticle.phi, assocParticle.phi)); @@ -1150,13 +1206,13 @@ struct PhiStrangenessCorrelation { // Loop over past events in the same multiplicity bin and fill histograms with all combinations of current phi particles and past associated particles for (const auto& phiParticle : phiParticles) { - static_for<0, assocParticleLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; - if (!doAssocCorrelations[i]) + static_for<0, AssocParticleLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int Idx = i_idx.value; + if (!doAssocCorrelations[Idx]) return; - for (const auto& assocParticle : *(pastAssocParticles[i])) { - histos.fill(HIST("phi") + HIST(assocParticleLabels[i]) + HIST("/h5Phi") + HIST(assocParticleLabels[i]) + HIST("ClosureMCGenME"), + for (const auto& assocParticle : *(pastAssocParticles[Idx])) { + histos.fill(HIST("phi") + HIST(AssocParticleLabels[Idx]) + HIST("/h5Phi") + HIST(AssocParticleLabels[Idx]) + HIST("ClosureMCGenME"), multiplicity, phiParticle.pt, assocParticle.pt, phiParticle.y - assocParticle.y, getDeltaPhi(phiParticle.phi, assocParticle.phi)); From 1ebabcf817c536a52214468ce562cdd945ee39bc Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 5 May 2026 16:41:50 +0200 Subject: [PATCH 047/449] [PWGEM/Dilepton] reduce ML data in taggingHFE.cxx (#16113) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 6 +- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 140 +++++++++++++++++++++--- 2 files changed, 130 insertions(+), 16 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 5cfdd002928..4f6e03441e0 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -201,15 +201,15 @@ DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of } // namespace emmlevent namespace emmltrack { -DECLARE_SOA_COLUMN(IsMotherFromHF, isMotherFromHF, bool); //! is HF included in decay history -DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); //! pdg code of mother of lepton +DECLARE_SOA_COLUMN(IsMotherFromBeauty, isMotherFromBeauty, bool); //! is b quark included in decay history +DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); //! pdg code of mother of lepton } // namespace emmltrack DECLARE_SOA_TABLE(EMMLLeptons, "AOD", "EMMLLEPTON", //! o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmlevent::SubGeneratorId, track::Signed1Pt, track::Eta, track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, - emmltrack::IsMotherFromHF, emmltrack::PdgCodeMother); + emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother); // iterators using EMMLLepton = EMMLLeptons::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 6f1f36e6fb1..3a2ea08cab4 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -776,6 +776,36 @@ struct taggingHFE { } } + template + bool isSemiLeptonic(TMCParticle const& mcParticle, TMCParticles const& mcParticles, const int pdgLepton, const int pdgNeutrino) + { + if (!mcParticle.has_daughters()) { + return false; + } + bool is_lepton_involved = false; + bool is_neutrino_involved = false; + for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { + if (d < mcParticles.size()) { // protect against bad daughter indices + auto daughter = mcParticles.rawIteratorAt(d); + if (daughter.pdgCode() == pdgLepton) { + is_lepton_involved = true; + } else if (daughter.pdgCode() == pdgNeutrino) { + is_neutrino_involved = true; + } + } else { + std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcParticles.size() << ")" << std::endl; + std::cout << " Check the MC generator" << std::endl; + return false; + } + } + + if (is_lepton_involved && is_neutrino_involved) { + return true; + } else { + return false; + } + } + template bool isSemiLeptonic(TMCParticle const& mcParticle, TMCParticles const& mcParticles, const int pdgLepton, const int pdgNeutrino, const int pdgStrHad) { @@ -1098,12 +1128,6 @@ struct taggingHFE { } } // end of cascade loop - // // if (electronIds.size() > 0 || positronIds.size() > 0) { - // if ((electronIds.size() > 0 || positronIds.size() > 0) && (xiMinusIds.size() > 0 || xiPlusIds.size() > 0)) { - // LOGF(info, "collision.globalIndex() = %d, electronIds.size() = %d, positronIds.size() = %d, kaonMinusIds.size() = %d, kaonPlusIds.size() = %d, k0Ids.size() = %d, lambdaIds.size() = %d, antilambdaIds.size() = %d, xiMinusIds.size() = %d, xiPlusIds.size() = %d, omegaMinusIds.size() = %d, omegaPlusIds.size() = %d", - // collision.globalIndex(), electronIds.size(), positronIds.size(), kaonMinusIds.size(), kaonPlusIds.size(), k0Ids.size(), lambdaIds.size(), antilambdaIds.size(), xiMinusIds.size(), xiPlusIds.size(), omegaMinusIds.size(), omegaPlusIds.size()); - // } - for (const auto& positronId : positronIds) { auto pos = tracks.rawIteratorAt(positronId); mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -1114,13 +1138,21 @@ struct taggingHFE { float dcaZ_lepton = mDcaInfoCov.getZ(); auto mcpos = pos.template mcParticle_as(); - auto mcmother = mcpos.template mothers_as()[0]; - bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > 0) || (IsFromBeauty(mcmother, mcParticles) > 0); + auto mcMother = mcpos.template mothers_as()[0]; + bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; auto mcCollision = mcpos.template mcCollision_as(); + bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. + bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; + bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); + bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); + if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { + continue; + } + leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromHF, mcmother.pdgCode()); + isMotherFromB, mcMother.pdgCode()); // D0 -> e+ nu_e K-, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonMinusIds) { @@ -1158,6 +1190,22 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + // I want 3 types. + // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. + // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. + // 3. truely found DY->ee with misidentified ee. (SV may be found at the same position of PV.) For bkg sample in ML. + continue; + } + + // if (std::abs(mckaon.pdgCode()) == 11) { + // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); + // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { + // auto daughter = mcParticles.rawIteratorAt(d); + // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); + // } + // } + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1232,6 +1280,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllv0pair(leptonTable.lastIndex(), v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1288,6 +1340,10 @@ struct taggingHFE { foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcLambda) > 0; } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllv0pair(leptonTable.lastIndex(), v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1349,6 +1405,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllcascpair(leptonTable.lastIndex(), cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -1410,6 +1470,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllcascpair(leptonTable.lastIndex(), cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -1435,13 +1499,21 @@ struct taggingHFE { float dcaZ_lepton = mDcaInfoCov.getZ(); auto mcele = ele.template mcParticle_as(); - auto mcmother = mcele.template mothers_as()[0]; - bool isMotherFromHF = (IsFromCharm(mcmother, mcParticles) > 0) || (IsFromBeauty(mcmother, mcParticles) > 0); + auto mcMother = mcele.template mothers_as()[0]; + bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; auto mcCollision = mcele.template mcCollision_as(); + bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. + bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; + bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); + bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); + if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { + continue; + } + leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromHF, mcmother.pdgCode()); + isMotherFromB, mcMother.pdgCode()); // D0bar -> e- anti-nu_e K+, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonPlusIds) { @@ -1478,6 +1550,22 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + // I want 3 types. + // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. + // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. + // 3. truely found DY->ee with misidentified ee. (SV may be found at the same position of PV.) For bkg sample in ML. + continue; + } + + // if (std::abs(mckaon.pdgCode()) == 11) { + // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); + // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { + // auto daughter = mcParticles.rawIteratorAt(d); + // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); + // } + // } + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1551,6 +1639,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllv0pair(leptonTable.lastIndex(), v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1607,6 +1699,10 @@ struct taggingHFE { foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcLambda) > 0; } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllv0pair(leptonTable.lastIndex(), v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1668,6 +1764,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllcascpair(leptonTable.lastIndex(), cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -1729,6 +1829,10 @@ struct taggingHFE { } } + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + continue; + } + emmllcascpair(leptonTable.lastIndex(), cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -1857,7 +1961,16 @@ struct taggingHFE { fRegistry.fill(HIST("Generated/Lc/hsAcc"), ptLepton, ptHadron, etaLepton, etaHadron); } - } // end of D0 loop per mcCollision + } // end of Lc loop per mcCollision + + // auto mcB0s_per_mccollision = mcB0s.sliceBy(perMcCollision, mcCollision.globalIndex()); + // for (const auto& mcParticle : mcB0s_per_mccollision) { + // LOGF(info, "B0: mcParticle.pdgCode() = %d", mcParticle.pdgCode()); + // for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { + // auto daughter = mcParticles.rawIteratorAt(d); + // LOGF(info, "B0: daughter.pdgCode() = %d", daughter.pdgCode()); + // } + // } // end of B0 loop per mcCollision } } @@ -1867,6 +1980,7 @@ struct taggingHFE { Partition mcLcs = nabs(o2::aod::mcparticle::pdgCode) == 4122; // Partition mcXic0s = nabs(o2::aod::mcparticle::pdgCode) == 4232; // Partition mcOmegac0s = nabs(o2::aod::mcparticle::pdgCode) == 4332; + // Partition mcB0s = nabs(o2::aod::mcparticle::pdgCode) == 511; SliceCache cache; Preslice perCol = o2::aod::track::collisionId; From c0b2fcffb19cd107037e445d9f54ed612c29388c Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Tue, 5 May 2026 21:28:18 +0530 Subject: [PATCH 048/449] [PWGLF] Added eta particle in the reflection process function (#16118) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 133 ++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index 951bfdd1440..d1bba8d223d 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -161,6 +161,9 @@ struct Kstar892LightIon { Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; Configurable selINELgt0MC{"selINELgt0MC", true, "Select INEL > 0?"}; + + Configurable invMassMinMID{"invMassMinMID", 0.6, "Minimum invariant mass for MID"}; + Configurable invMassMaxMID{"invMassMaxMID", 0.82, "Maximum invariant mass for MID"}; } selectionConfig; Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; @@ -378,6 +381,8 @@ struct Kstar892LightIon { hMC.add("Reflections/hOmegaToKpi", "Refelction template of Omega", kTH3F, {ptAxis, centralityAxis, invmassAxis}); hMC.add("Reflections/hPhiToKpi", "Refelction template of Phi", kTH3F, {ptAxis, centralityAxis, invmassAxis}); hMC.add("Reflections/hKstarSelf", "Refelction template of Kstar", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hEtaToKpi", "Refelction template of Eta", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hEtaPrimeToKpi", "Refelction template of Eta'", kTH3F, {ptAxis, centralityAxis, invmassAxis}); } if (doprocessMCCheck) { @@ -1998,6 +2003,50 @@ struct Kstar892LightIon { hMC.fill(HIST("Reflections/hOmegaToKpi"), fake2.Pt(), centrality, fake2.M()); } + // ===================================================== + // Eta -> pi pi(pi0) -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kEta && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { + + // track 1 -> K + ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); + auto fake1 = p1K + p2Pi; + + if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hEtaToKpi"), fake1.Pt(), centrality, fake1.M()); + + // track 2 -> K + ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); + auto fake2 = p1Pi + p2K; + + if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hEtaToKpi"), fake2.Pt(), centrality, fake2.M()); + } + + // ===================================================== + // Eta' (958) -> pi pi(eta) -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kEtaPrime && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { + + // track 1 -> K + ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); + auto fake1 = p1K + p2Pi; + + if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hEtaPrimeToKpi"), fake1.Pt(), centrality, fake1.M()); + + // track 2 -> K + ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); + auto fake2 = p1Pi + p2K; + + if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hEtaPrimeToKpi"), fake2.Pt(), centrality, fake2.M()); + } + // ===================================================== // Phi (1020) -> KK -> K pi // ===================================================== @@ -2261,6 +2310,90 @@ struct Kstar892LightIon { hMC.fill(HIST("MCCheck/NchMC_AllGen"), nChMCEta08); } PROCESS_SWITCH(Kstar892LightIon, processMCCheck, "Cross-check MC analysis", false); + + void processSEMassMID(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) + { + if (!selectionEvent(collision, true)) { // fill data event cut histogram + return; + } + + centrality = -1; + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); // default + } + + /* else if (selectCentEstimator == 4) { + centrality = collision.centMFT(); + } */ + /* else if (selectCentEstimator == 5) { + centrality = collision.centNGlobal(); + } */ + /* else if (selectCentEstimator == 6) { + centrality = collision.centNTPV(); + } */ + + if (cQAevents) { + hEventSelection.fill(HIST("hVertexZ"), collision.posZ()); + hEventSelection.fill(HIST("hCentrality"), centrality); + } + + for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + if (!selectionTrack(track1) || !selectionTrack(track2)) { + continue; + } + + if (track1.globalIndex() == track2.globalIndex()) + continue; + + if (!selectionPair(track1, track2)) { + continue; + } + + // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + continue; + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track2, 0)) // Track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track2, 0)) // Track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track2, 0)) // Track 2 is checked with Pion + continue; + + /* if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) + continue; + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) + continue; */ + + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + mother = daughter1 + daughter2; // Kstar meson + + if (mother.M() < selectionConfig.invMassMaxMID && mother.M() > selectionConfig.invMassMinMID) { + if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) + continue; + } + + isMix = false; + fillInvMass(daughter1, daughter2, mother, centrality, isMix, track1, track2); + } + } + PROCESS_SWITCH(Kstar892LightIon, processSEMassMID, "Process Same event", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 1e149ce304bac680b93a62192037079c18b303a6 Mon Sep 17 00:00:00 2001 From: a-m-andrushko <96832230+a-m-andrushko@users.noreply.github.com> Date: Tue, 5 May 2026 18:18:08 +0200 Subject: [PATCH 049/449] [PWGCF] FemtoUniverse -- Add extra histograms for K0S and Lambda. (#16117) --- .../femtoUniversePairTaskTrackV0Helicity.cxx | 124 ++++++++++++------ 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx index a32bf8392d6..d832430f99d 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -182,14 +182,21 @@ struct FemtoUniversePairTaskTrackV0Helicity { } twotracksconfigs; /// Helicity ranges and configurables - Configurable cfgProcessHel{"cfgProcessHel", true, "Process particle pairs from all helicity ranges"}; - Configurable cfgProcessHel1{"cfgProcessHel1", false, "Process particle pairs from the helicity range 1"}; // 1.0 >= cosineTheta >= 0.1 - Configurable cfgProcessHel2{"cfgProcessHel2", false, "Process particle pairs from the helicity range 2"}; // 0.1 > cosineTheta >= -0.1 - Configurable cfgProcessHel3{"cfgProcessHel3", false, "Process particle pairs from the helicity range 3"}; // -0.1 > cosineTheta >= -0.5 - Configurable cfgProcessHel4{"cfgProcessHel4", false, "Process particle pairs from the helicity range 4"}; // -0.5 > cosineTheta >= -1.0 - ConfigurableAxis confInvMassMotherpTBinsHel{"confInvMassMotherpTBinsHel", {5, 0, 5}, "pT binning in the pT vs. InvMassMother plot for helicity"}; - ConfigurableAxis confInvMassMotherBinsHel{"confInvMassMotherBinsHel", {1000, 0.8, 1.4}, "InvMassMother binning in the pT vs. InvMassMother plot for helicity"}; - ConfigurableAxis confInvMassK0Short{"confInvMassK0s", {1000, 0.2, 0.8}, "Invariant mass binning for K0 Short"}; + struct : o2::framework::ConfigurableGroup { + Configurable cfgProcessHel{"cfgProcessHel", true, "Process particle pairs from all helicity ranges"}; + Configurable cfgProcessHel1{"cfgProcessHel1", false, "Process particle pairs from the helicity range 1"}; // 1.0 >= cosineTheta >= 0.1 + Configurable cfgProcessHel2{"cfgProcessHel2", false, "Process particle pairs from the helicity range 2"}; // 0.1 > cosineTheta >= -0.1 + Configurable cfgProcessHel3{"cfgProcessHel3", false, "Process particle pairs from the helicity range 3"}; // -0.1 > cosineTheta >= -0.5 + Configurable cfgProcessHel4{"cfgProcessHel4", false, "Process particle pairs from the helicity range 4"}; // -0.5 > cosineTheta >= -1.0 + Configurable confLimitHel0{"confLimitHel0", 1.0, "Highest value of the helicity angle"}; + Configurable confLimitHel1{"confLimitHel1", 0.1, "Border value between ranges 1 and 2"}; + Configurable confLimitHel2{"confLimitHel2", -0.1, "Border value between ranges 2 and 3"}; + Configurable confLimitHel3{"confLimitHel3", -0.5, "Border value between ranges 3 and 4"}; + Configurable confLimitHel4{"confLimitHel4", -1.0, "Lowest value of the helicity angle"}; + ConfigurableAxis confInvMassMotherpTBinsHel{"confInvMassMotherpTBinsHel", {5, 0, 5}, "pT binning in the pT vs. InvMassMother plot for helicity"}; + ConfigurableAxis confInvMassMotherBinsHel{"confInvMassMotherBinsHel", {1000, 0.8, 1.4}, "InvMassMother binning in the pT vs. InvMassMother plot for helicity"}; + ConfigurableAxis confInvMassK0Short{"confInvMassK0Short", {1000, 0.2, 0.8}, "Invariant mass binning for K0 Short"}; // o2-linter: disable=lowerCamelCase (consistency with generally accepted particle name) + } helicityconfigs; /// Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; @@ -319,11 +326,20 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.add("Theta/NegativeChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel1", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassK0Short", " ; M_{K^{0}_{S}}; ;", kTH1F, {confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel1", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassLambdaMC", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel1", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel2", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel3", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel4", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassK0ShortMC", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel1", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel2", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel3", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel4", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); /// MC Truth registryMCtruth.add("plus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); @@ -387,7 +403,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { registryMCreco.add("ThetaMCReco/NegativeChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); /// Correlations - if (cfgProcessHel) { + if (helicityconfigs.cfgProcessHel) { sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventCont.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); @@ -395,7 +411,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { mixedEventCont.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); } - if (cfgProcessHel1) { + if (helicityconfigs.cfgProcessHel1) { sameEventContHel1.init(&resultRegistryHel1, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventContHel1.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); @@ -403,7 +419,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { mixedEventContHel1.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); } - if (cfgProcessHel2) { + if (helicityconfigs.cfgProcessHel2) { sameEventContHel2.init(&resultRegistryHel2, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventContHel2.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); @@ -411,7 +427,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { mixedEventContHel2.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); } - if (cfgProcessHel3) { + if (helicityconfigs.cfgProcessHel3) { sameEventContHel3.init(&resultRegistryHel3, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventContHel3.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); @@ -419,7 +435,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { mixedEventContHel3.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); } - if (cfgProcessHel4) { + if (helicityconfigs.cfgProcessHel4) { sameEventContHel4.init(&resultRegistryHel4, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventContHel4.setPDGCodes(trackconfigs.confTrkPDGCodePartOne, V0configs.confV0PDGCodePartTwo); @@ -491,19 +507,43 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negChild.eta(), cosineTheta); thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); - if (cosineTheta <= 1.0 && cosineTheta >= 0.1) + if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel1"), part.pt(), part.mLambda()); - else if (cosineTheta < 0.1 && cosineTheta >= -0.1) + else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel2"), part.pt(), part.mLambda()); - else if (cosineTheta < -0.1 && cosineTheta >= -0.5) + else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel3"), part.pt(), part.mLambda()); - else if (cosineTheta < -0.5 && cosineTheta >= -1) + else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel4"), part.pt(), part.mLambda()); + /// Histogramming for MC Reco to calculate fraction of K0S in the Lambda sample for each helicity bin if constexpr (confIsMC) { if (part.has_fdMCParticle()) { - if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0Short"), part.mKaon()); + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMC"), part.mLambda()); + else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMC"), part.mKaon()); + + if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) { + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel1"), part.mLambda()); + else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel1"), part.mKaon()); + } else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) { + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel2"), part.mLambda()); + else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel2"), part.mKaon()); + } else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) { + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel3"), part.mLambda()); + else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel3"), part.mKaon()); + } else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) { + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel4"), part.mLambda()); + else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel4"), part.mKaon()); } } } @@ -571,28 +611,28 @@ struct FemtoUniversePairTaskTrackV0Helicity { } case 1: { - if (cosineTheta <= 1.0 && cosineTheta >= 0.1) + if (cosineTheta < helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) sameEventContHel1.setPair(p1, p2, multCol, confUse3D, weight); break; } case 2: { - if (cosineTheta < 0.1 && cosineTheta >= -0.1) + if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) sameEventContHel2.setPair(p1, p2, multCol, confUse3D, weight); break; } case 3: { - if (cosineTheta < -0.1 && cosineTheta >= -0.5) + if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) sameEventContHel3.setPair(p1, p2, multCol, confUse3D, weight); break; } case 4: { - if (cosineTheta < -0.5 && cosineTheta >= -1.0) + if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) sameEventContHel4.setPair(p1, p2, multCol, confUse3D, weight); break; @@ -609,19 +649,19 @@ struct FemtoUniversePairTaskTrackV0Helicity { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - if (cfgProcessHel) + if (helicityconfigs.cfgProcessHel) doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 0); - if (cfgProcessHel1) + if (helicityconfigs.cfgProcessHel1) doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 1); - if (cfgProcessHel2) + if (helicityconfigs.cfgProcessHel2) doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 2); - if (cfgProcessHel3) + if (helicityconfigs.cfgProcessHel3) doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 3); - if (cfgProcessHel4) + if (helicityconfigs.cfgProcessHel4) doSameEvent(col, parts, groupPartsOne, groupPartsTwo, 4); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEvent, "Enable processing same event for track - V0", false); @@ -869,28 +909,28 @@ struct FemtoUniversePairTaskTrackV0Helicity { } case 1: { - if (cosineTheta <= 1.0 && cosineTheta >= 0.1) + if (cosineTheta < helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) mixedEventContHel1.setPair(p1, p2, multCol, confUse3D, weight); break; } case 2: { - if (cosineTheta < 0.1 && cosineTheta >= -0.1) + if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) mixedEventContHel2.setPair(p1, p2, multCol, confUse3D, weight); break; } case 3: { - if (cosineTheta < -0.1 && cosineTheta >= -0.5) + if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) mixedEventContHel3.setPair(p1, p2, multCol, confUse3D, weight); break; } case 4: { - if (cosineTheta < -0.5 && cosineTheta >= -1.0) + if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) mixedEventContHel4.setPair(p1, p2, multCol, confUse3D, weight); break; @@ -917,19 +957,19 @@ struct FemtoUniversePairTaskTrackV0Helicity { void processMixedEvent(FilteredFDCollisions const& cols, FemtoFullParticles const& parts) { - if (cfgProcessHel) + if (helicityconfigs.cfgProcessHel) doMixedEvent(cols, parts, partsOne, partsTwo, 0); - if (cfgProcessHel1) + if (helicityconfigs.cfgProcessHel1) doMixedEvent(cols, parts, partsOne, partsTwo, 1); - if (cfgProcessHel2) + if (helicityconfigs.cfgProcessHel2) doMixedEvent(cols, parts, partsOne, partsTwo, 2); - if (cfgProcessHel3) + if (helicityconfigs.cfgProcessHel3) doMixedEvent(cols, parts, partsOne, partsTwo, 3); - if (cfgProcessHel4) + if (helicityconfigs.cfgProcessHel4) doMixedEvent(cols, parts, partsOne, partsTwo, 4); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMixedEvent, "Enable processing mixed event for track - V0", false); From 2e5bc7289affe966afcb13a910c1722bad8f60b8 Mon Sep 17 00:00:00 2001 From: Chiara De Martin <39315597+ChiaraDeMartin95@users.noreply.github.com> Date: Tue, 5 May 2026 18:18:41 +0200 Subject: [PATCH 050/449] [PWGLF] Add histos of inv mass for true cascades (#16119) Co-authored-by: Chiara De Martin --- PWGLF/TableProducer/Strangeness/cascadeflow.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index d6e51874fb8..98d86a0c471 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -2622,6 +2622,19 @@ struct cascadeFlow { BDTresponse[0] = bdtScore[0][1]; BDTresponse[1] = bdtScore[1][1]; } + int chargeIndex = 0; + if (casc.sign() > 0) + chargeIndex = 1; + if (std::abs(casc.eta()) < CandidateConfigs.etaCasc) { + if (fillingConfigs.isFillTHNXi && fillingConfigs.isFillTHN_Pz) { + if (std::abs(pdgCode) == PDG_t::kXiMinus) + histos.get(HIST("hXiPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], 0); + } + if (fillingConfigs.isFillTHNOmega && fillingConfigs.isFillTHN_Pz) { + if (std::abs(pdgCode) == PDG_t::kOmegaMinus) + histos.get(HIST("hOmegaPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], 0); + } + } if (isStoreTrueCascOnly) { if (pdgCode == 0) continue; From 9fae8adbbb2a55d8ceae26b73b4b3a5fa5ceb3b8 Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Tue, 5 May 2026 21:15:54 +0200 Subject: [PATCH 051/449] [PWGCF] code for mixing mixedphi with hadrons (#16103) Co-authored-by: Prottay Das --- PWGCF/Tasks/correlations.cxx | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 279765c3ae1..f8dce2e6257 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,7 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgEfficiencyAssociated, std::string, "", "CCDB path to efficiency object for associated particles") O2_DEFINE_CONFIGURABLE(cfgNoMixedEvents, int, 5, "Number of mixed events per event") + O2_DEFINE_CONFIGURABLE(cfgRejectMixedPhiProngEvents, bool, true, "Reject associated hadrons from either mixed-phi prong event") O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") @@ -127,6 +129,8 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgPtCentDepMLbkgSel, std::vector, {}, "Bkg ML selection") O2_DEFINE_CONFIGURABLE(cfgPtCentDepMLpromptSel, std::vector, {}, "Prompt ML selection") + std::unordered_map cfTrackToCFCollision; + ConfigurableAxis axisVertex{"axisVertex", {7, -7, 7}, "vertex axis for histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"}; @@ -511,6 +515,8 @@ struct CorrelationTask { using HasPartDaugh0Id = decltype(std::declval().cfParticleDaugh0Id()); template using HasPartDaugh1Id = decltype(std::declval().cfParticleDaugh1Id()); + template + using HasCFCollisionId = decltype(std::declval().cfCollisionId()); template bool passOutlier(CollType const& collision) @@ -654,6 +660,29 @@ struct CorrelationTask { continue; } } + + if ((&target == &mixed) && doprocessMixed2ProngDerivedMixedPhi && cfgRejectMixedPhiProngEvents) { + if constexpr (std::experimental::is_detected::value && + std::experimental::is_detected::value && + std::experimental::is_detected::value && + std::experimental::is_detected::value) { + + if (track1.decay() == aod::cf2prongtrack::PhiToKKPID3Mixed) { + auto pr0 = cfTrackToCFCollision.find(track1.cfTrackProng0Id()); + auto pr1 = cfTrackToCFCollision.find(track1.cfTrackProng1Id()); + + if (pr0 != cfTrackToCFCollision.end() && + pr1 != cfTrackToCFCollision.end()) { + const auto assocColl = track2.cfCollisionId(); + + if (assocColl == pr0->second || assocColl == pr1->second) { + continue; + } + } + } + } + } + if constexpr (std::experimental::is_detected::value) { // skip those that are specifically chosen to be triggers if (!cfgMcTriggerPDGs->empty() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track2.pdgCode()) != cfgMcTriggerPDGs->end()) continue; // TODO: fix cases like MC D0-D0 @@ -783,16 +812,15 @@ struct CorrelationTask { } // ML selection // last param is the weight - if (cfgMassAxis && (doprocessSame2Prong2Prong || doprocessMixed2Prong2Prong || doprocessSame2Prong2ProngML || doprocessMixed2Prong2ProngML) && !(doprocessSame2ProngDerived || doprocessSame2ProngDerivedML || doprocessMixed2ProngDerived || doprocessMixed2ProngDerivedML)) { + if (cfgMassAxis && (doprocessSame2Prong2Prong || doprocessMixed2Prong2Prong || doprocessSame2Prong2ProngML || doprocessMixed2Prong2ProngML) && !(doprocessSame2ProngDerived || doprocessSame2ProngDerivedML || doprocessMixed2ProngDerived || doprocessMixed2ProngDerivedML || doprocessMixed2ProngDerivedMixedPhi)) { if constexpr (std::experimental::is_detected::value && std::experimental::is_detected::value) target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, track2.invMass(), track1.invMass(), associatedWeight); else LOGF(fatal, "Can not fill mass axis without invMass column. \n no mass for two particles"); } else if (cfgMassAxis) { - if constexpr (std::experimental::is_detected::value) + if constexpr (std::experimental::is_detected::value) { target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, track1.invMass(), associatedWeight); - else if constexpr (std::experimental::is_detected::value) { - // TParticlePDG *p = pdg->GetParticle(track1.pdgCode()); //TODO: get the mass for the PDG properly + } else if constexpr (std::experimental::is_detected::value) { target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, 1.8, associatedWeight); // p->Mass() } else { LOGF(fatal, "Can not fill mass axis without invMass column. Disable cfgMassAxis."); @@ -1071,6 +1099,21 @@ struct CorrelationTask { processMixedDerivedT(collisions, p2tracks, tracks); } PROCESS_SWITCH(CorrelationTask, processMixed2ProngDerived, "Process mixed events on derived data", false); + void processMixed2ProngDerivedMixedPhi(DerivedCollisions const& collisions, + DerivedTracks const& tracks, + soa::Filtered const& p2tracks) + { + cfTrackToCFCollision.clear(); + cfTrackToCFCollision.reserve(tracks.size()); + + for (const auto& trk : tracks) { + cfTrackToCFCollision.emplace(trk.globalIndex(), trk.cfCollisionId()); + } + + processMixedDerivedT(collisions, p2tracks, tracks); + } + + PROCESS_SWITCH(CorrelationTask, processMixed2ProngDerivedMixedPhi, "Process mixed events for mixed-phi triggers", false); void processMixed2ProngDerivedML(DerivedCollisions const& collisions, DerivedTracks const& tracks, soa::Filtered> const& p2tracks) { From e438752c268928b2bd1ea1b6a6c7391d0cdaf5f4 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Tue, 5 May 2026 21:40:39 +0200 Subject: [PATCH 052/449] [Common,PWGHF] Add reduced q vectors for Event-shape Engineering (#15636) Co-authored-by: ALICE Action Bot Co-authored-by: Marcello Di Costanzo --- Common/DataModel/Qvectors.h | 89 +++ Common/TableProducer/qVectorsTable.cxx | 811 +++++++++++++---------- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 169 +++-- PWGHF/D2H/Utils/utilsFlow.h | 50 ++ 4 files changed, 742 insertions(+), 377 deletions(-) diff --git a/Common/DataModel/Qvectors.h b/Common/DataModel/Qvectors.h index d723d659bc5..f62e8851a2b 100644 --- a/Common/DataModel/Qvectors.h +++ b/Common/DataModel/Qvectors.h @@ -155,6 +155,95 @@ using QvectorBNegVec = QvectorBNegVecs::iterator; using QvectorBTotVec = QvectorBTotVecs::iterator; ///////////////////////////////////////////////////////////////// +namespace ese_qvec +{ +DECLARE_SOA_COLUMN(IsCalibrated, isCalibrated, bool); + +DECLARE_SOA_COLUMN(EseQvecRe, eseQvecRe, std::vector); +DECLARE_SOA_COLUMN(EseQvecIm, eseQvecIm, std::vector); +DECLARE_SOA_COLUMN(EseQvecAmp, eseQvecAmp, std::vector); + +DECLARE_SOA_COLUMN(EseQvecFT0CReVec, eseQvecFT0CReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFT0CImVec, eseQvecFT0CImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFT0AReVec, eseQvecFT0AReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFT0AImVec, eseQvecFT0AImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFT0MReVec, eseQvecFT0MReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFT0MImVec, eseQvecFT0MImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFV0AReVec, eseQvecFV0AReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecFV0AImVec, eseQvecFV0AImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCposReVec, eseQvecTPCposReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCposImVec, eseQvecTPCposImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCnegReVec, eseQvecTPCnegReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCnegImVec, eseQvecTPCnegImVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCallReVec, eseQvecTPCallReVec, std::vector); +DECLARE_SOA_COLUMN(EseQvecTPCallImVec, eseQvecTPCallImVec, std::vector); + +DECLARE_SOA_COLUMN(EseQvecFT0CRe, eseQvecFT0CRe, float); +DECLARE_SOA_COLUMN(EseQvecFT0CIm, eseQvecFT0CIm, float); +DECLARE_SOA_COLUMN(EseQvecFT0ARe, eseQvecFT0ARe, float); +DECLARE_SOA_COLUMN(EseQvecFT0AIm, eseQvecFT0AIm, float); +DECLARE_SOA_COLUMN(EseQvecFT0MRe, eseQvecFT0MRe, float); +DECLARE_SOA_COLUMN(EseQvecFT0MIm, eseQvecFT0MIm, float); +DECLARE_SOA_COLUMN(EseQvecFV0ARe, eseQvecFV0ARe, float); +DECLARE_SOA_COLUMN(EseQvecFV0AIm, eseQvecFV0AIm, float); +DECLARE_SOA_COLUMN(EseQvecTPCposRe, eseQvecTPCposRe, float); +DECLARE_SOA_COLUMN(EseQvecTPCposIm, eseQvecTPCposIm, float); +DECLARE_SOA_COLUMN(EseQvecTPCnegRe, eseQvecTPCnegRe, float); +DECLARE_SOA_COLUMN(EseQvecTPCnegIm, eseQvecTPCnegIm, float); +DECLARE_SOA_COLUMN(EseQvecTPCallRe, eseQvecTPCallRe, float); +DECLARE_SOA_COLUMN(EseQvecTPCallIm, eseQvecTPCallIm, float); + +DECLARE_SOA_COLUMN(EseRedQFT0C, eseRedQFT0C, float); +DECLARE_SOA_COLUMN(EseRedQFT0A, eseRedQFT0A, float); +DECLARE_SOA_COLUMN(EseRedQFT0M, eseRedQFT0M, float); +DECLARE_SOA_COLUMN(EseRedQFV0A, eseRedQFV0A, float); +///////////////////////////////////////////////////////////////// +} // namespace ese_qvec + +DECLARE_SOA_TABLE(EseQvectors, "AOD", "ESEQVECTORDEVS", //! Table with all Qvectors. + qvec::Cent, ese_qvec::IsCalibrated, ese_qvec::EseQvecRe, ese_qvec::EseQvecIm, ese_qvec::EseQvecAmp); +using Qvector = Qvectors::iterator; + +DECLARE_SOA_TABLE(EseQvecFT0Cs, "AOD", "ESEQVECFT0C", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0CRe, ese_qvec::EseQvecFT0CIm, qvec::SumAmplFT0C); +DECLARE_SOA_TABLE(EseQvecFT0As, "AOD", "ESEQVECFT0A", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0ARe, ese_qvec::EseQvecFT0AIm, qvec::SumAmplFT0A); +DECLARE_SOA_TABLE(EseQvecFT0Ms, "AOD", "ESEQVECFT0M", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0MRe, ese_qvec::EseQvecFT0MIm, qvec::SumAmplFT0M); +DECLARE_SOA_TABLE(EseQvecFV0As, "AOD", "ESEQVECFV0A", ese_qvec::IsCalibrated, ese_qvec::EseQvecFV0ARe, ese_qvec::EseQvecFV0AIm, qvec::SumAmplFV0A); +DECLARE_SOA_TABLE(EseQvecTPCposs, "AOD", "ESEQVECTPCPOS", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCposRe, ese_qvec::EseQvecTPCposIm, qvec::NTrkTPCpos, qvec::LabelsTPCpos); +DECLARE_SOA_TABLE(EseQvecTPCnegs, "AOD", "ESEQVECTPCNEG", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCnegRe, ese_qvec::EseQvecTPCnegIm, qvec::NTrkTPCneg, qvec::LabelsTPCneg); +DECLARE_SOA_TABLE(EseQvecTPCalls, "AOD", "ESEQVECTPCALL", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCallRe, ese_qvec::EseQvecTPCallIm, qvec::NTrkTPCall, qvec::LabelsTPCall); + +DECLARE_SOA_TABLE(EseQvecFT0CVecs, "AOD", "ESEQVECFT0CVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0CReVec, ese_qvec::EseQvecFT0CImVec, qvec::SumAmplFT0C); +DECLARE_SOA_TABLE(EseQvecFT0AVecs, "AOD", "ESEQVECFT0AVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0AReVec, ese_qvec::EseQvecFT0AImVec, qvec::SumAmplFT0A); +DECLARE_SOA_TABLE(EseQvecFT0MVecs, "AOD", "ESEQVECFT0MVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0MReVec, ese_qvec::EseQvecFT0MImVec, qvec::SumAmplFT0M); +DECLARE_SOA_TABLE(EseQvecFV0AVecs, "AOD", "ESEQVECFV0AVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecFV0AReVec, ese_qvec::EseQvecFV0AImVec, qvec::SumAmplFV0A); +DECLARE_SOA_TABLE(EseQvecTPCposVecs, "AOD", "ESEQVECTPCPVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCposReVec, ese_qvec::EseQvecTPCposImVec, qvec::NTrkTPCpos, qvec::LabelsTPCpos); +DECLARE_SOA_TABLE(EseQvecTPCnegVecs, "AOD", "ESEQVECTPCNVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCnegReVec, ese_qvec::EseQvecTPCnegImVec, qvec::NTrkTPCneg, qvec::LabelsTPCneg); +DECLARE_SOA_TABLE(EseQvecTPCallVecs, "AOD", "ESEQVECTPCAVEC", ese_qvec::IsCalibrated, ese_qvec::EseQvecTPCallReVec, ese_qvec::EseQvecTPCallImVec, qvec::NTrkTPCall, qvec::LabelsTPCall); + +DECLARE_SOA_TABLE(EseQvecPercs, "AOD", "ESEQVECPERC", ese_qvec::EseQvecFT0CRe, ese_qvec::EseQvecFT0CIm, qvec::SumAmplFT0C, + ese_qvec::EseQvecFT0ARe, ese_qvec::EseQvecFT0AIm, qvec::SumAmplFT0A, + ese_qvec::EseQvecFT0MRe, ese_qvec::EseQvecFT0MIm, qvec::SumAmplFT0M, + ese_qvec::EseQvecFV0ARe, ese_qvec::EseQvecFV0AIm, qvec::SumAmplFV0A, + ese_qvec::EseQvecTPCposRe, ese_qvec::EseQvecTPCposIm, qvec::NTrkTPCpos, + ese_qvec::EseQvecTPCnegRe, ese_qvec::EseQvecTPCnegIm, qvec::NTrkTPCneg, + ese_qvec::EseQvecTPCallRe, ese_qvec::EseQvecTPCallIm, qvec::NTrkTPCall); + +using EseQvectorFT0C = EseQvecFT0Cs::iterator; +using EseQvectorFT0A = EseQvecFT0As::iterator; +using EseQvectorFT0M = EseQvecFT0Ms::iterator; +using EseQvectorFV0A = EseQvecFV0As::iterator; +using EseQvectorTPCpos = EseQvecTPCposs::iterator; +using EseQvectorTPCneg = EseQvecTPCnegs::iterator; +using EseQvectorTPCall = EseQvecTPCalls::iterator; + +using EseQvectorFT0CVec = EseQvecFT0CVecs::iterator; +using EseQvectorFT0AVec = EseQvecFT0AVecs::iterator; +using EseQvectorFT0MVec = EseQvecFT0MVecs::iterator; +using EseQvectorFV0AVec = EseQvecFV0AVecs::iterator; +using EseQvectorTPCposVec = EseQvecTPCposVecs::iterator; +using EseQvectorTPCnegVec = EseQvecTPCnegVecs::iterator; +using EseQvectorTPCallVec = EseQvecTPCallVecs::iterator; +///////////////////////////////////////////////////////////////// } // namespace o2::aod #endif // COMMON_DATAMODEL_QVECTORS_H_ diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index 273394a8e67..574c370a16a 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -65,14 +66,28 @@ using MyCollisions = soa::Join; struct qVectorsTable { - enum { + enum Detectors { kFT0C = 0, kFT0A = 1, kFT0M, kFV0A, - kTPCpos, - kTPCneg, - kTPCall + kTPCPos, + kTPCNeg, + kTPCAll, + kNDetectors + }; + enum Corrections { + kNoCorr = 0, + kRecenter, + kTwist, + kRescale, + kNCorrections + }; + enum MultNorms { + kNoNorm = 0, + kScalarProd, + kEsE, + kMultNormTypes }; // Configurables. @@ -98,7 +113,7 @@ struct qVectorsTable { Configurable useCorrectionForRun{"useCorrectionForRun", true, "Get Qvector corrections based on run number instead of timestamp"}; Configurable cfgGainEqPath{"cfgGainEqPath", "Users/j/junlee/Qvector/GainEq", "CCDB path for gain equalization constants"}; - Configurable cfgQvecCalibPath{"cfgQvecCalibPath", "Analysis/EventPlane/QVecCorrections", "CCDB pasth for Q-vecteor calibration constants"}; + Configurable cfgQvecCalibPath{"cfgQvecCalibPath", "Analysis/EventPlane/QVecCorrections", "CCDB path for Q-vector calibration constants"}; Configurable cfgShiftCorr{"cfgShiftCorr", false, "configurable flag for shift correction"}; Configurable cfgShiftPath{"cfgShiftPath", "", "CCDB path for shift correction"}; @@ -109,9 +124,10 @@ struct qVectorsTable { Configurable cfgUseFT0A{"cfgUseFT0A", false, "Initial value for using FT0A. By default obtained from DataModel."}; Configurable cfgUseFT0M{"cfgUseFT0M", false, "Initial value for using FT0M. By default obtained from DataModel."}; Configurable cfgUseFV0A{"cfgUseFV0A", false, "Initial value for using FV0A. By default obtained from DataModel."}; - Configurable cfgUseTPCpos{"cfgUseTPCpos", false, "Initial value for using TPCpos. By default obtained from DataModel."}; - Configurable cfgUseTPCneg{"cfgUseTPCneg", false, "Initial value for using TPCneg. By default obtained from DataModel."}; - Configurable cfgUseTPCall{"cfgUseTPCall", false, "Initial value for using TPCall. By default obtained from DataModel."}; + Configurable cfgUseTPCpos{"cfgUseTPCpos", false, "Initial value for using TPCPos. By default obtained from DataModel."}; + Configurable cfgUseTPCneg{"cfgUseTPCneg", false, "Initial value for using TPCNeg. By default obtained from DataModel."}; + Configurable cfgUseTPCall{"cfgUseTPCall", false, "Initial value for using TPCAll. By default obtained from DataModel."}; + Configurable cfgProduceRedQVecs{"cfgProduceRedQVecs", false, "Produce reduced Q-vectors for Event-Shape Engineering"}; // Table. Produces qVector; @@ -119,17 +135,35 @@ struct qVectorsTable { Produces qVectorFT0A; Produces qVectorFT0M; Produces qVectorFV0A; - Produces qVectorTPCpos; - Produces qVectorTPCneg; - Produces qVectorTPCall; + Produces qVectorTPCPos; + Produces qVectorTPCNeg; + Produces qVectorTPCAll; Produces qVectorFT0CVec; Produces qVectorFT0AVec; Produces qVectorFT0MVec; Produces qVectorFV0AVec; - Produces qVectorTPCposVec; - Produces qVectorTPCnegVec; - Produces qVectorTPCallVec; + Produces qVectorTPCPosVec; + Produces qVectorTPCNegVec; + Produces qVectorTPCAllVec; + + Produces eseQVector; + Produces eseQVectorFT0C; + Produces eseQVectorFT0A; + Produces eseQVectorFT0M; + Produces eseQVectorFV0A; + Produces eseQVectorTPCPos; + Produces eseQVectorTPCNeg; + Produces eseQVectorTPCAll; + + Produces eseQVectorFT0CVec; + Produces eseQVectorFT0AVec; + Produces eseQVectorFT0MVec; + Produces eseQVectorFV0AVec; + Produces eseQVectorTPCPosVec; + Produces eseQVectorTPCNegVec; + Produces eseQVectorTPCAllVec; + Produces eseQVectorPerc; std::vector FT0RelGainConst{}; std::vector FV0RelGainConst{}; @@ -147,11 +181,14 @@ struct qVectorsTable { HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + const float minAmplitude = 1.0e-8f; int runNumber{-1}; float cent; - std::vector objQvec{}; - std::vector shiftprofile{}; + std::vector corrsQvecSp{}; + std::vector corrsQvecEse{}; + std::vector shiftProfileSp{}; + std::vector shiftProfileEse{}; // Deprecated, will be removed in future after transition time // Configurable cfgUseBPos{"cfgUseBPos", false, "Initial value for using BPos. By default obtained from DataModel."}; @@ -193,8 +230,8 @@ struct qVectorsTable { goto allDetectorsInUse; // Added to break from nested loop if all detectors are in use. } for (auto const& det : useDetector) { - std::string table_name_with_vector = det.first; // for replacing s with Vecs at the end. - if (input.matcher.binding == det.first || input.matcher.binding == table_name_with_vector.replace(table_name_with_vector.size() - 1, 1, "Vecs")) { + std::string tableNameWithVector = det.first; // for replacing s with Vecs at the end. + if (input.matcher.binding == det.first || input.matcher.binding == tableNameWithVector.replace(tableNameWithVector.size() - 1, 1, "Vecs")) { useDetector[det.first.data()] = true; LOGF(info, Form("Using detector: %s.", det.first.data())); } @@ -257,38 +294,66 @@ struct qVectorsTable { LOGF(fatal, "Could not get the alignment parameters for FV0."); } - objQvec.clear(); + corrsQvecSp.clear(); for (std::size_t i = 0; i < cfgnMods->size(); i++) { int ind = cfgnMods->at(i); fullPath = cfgQvecCalibPath; fullPath += "/v"; fullPath += std::to_string(ind); - auto objqvec = getForTsOrRun(fullPath, timestamp, runnumber); - if (!objqvec) { + auto modeCorrQvecSp = getForTsOrRun(fullPath, timestamp, runnumber); + if (!modeCorrQvecSp) { fullPath = cfgQvecCalibPath; fullPath += "/v2"; - objqvec = getForTsOrRun(fullPath, timestamp, runnumber); + modeCorrQvecSp = getForTsOrRun(fullPath, timestamp, runnumber); } - objQvec.push_back(objqvec); + corrsQvecSp.push_back(modeCorrQvecSp); + } + + corrsQvecEse.clear(); + for (std::size_t i = 0; i < cfgnMods->size(); i++) { + int ind = cfgnMods->at(i); + fullPath = cfgQvecCalibPath; + fullPath += "/eseq"; + fullPath += std::to_string(ind); + auto modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); + if (!modeCorrQvecEse) { + fullPath = cfgQvecCalibPath; + fullPath += "/eseq2"; + modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); + } + corrsQvecEse.push_back(modeCorrQvecEse); } if (cfgShiftCorr) { - shiftprofile.clear(); + shiftProfileSp.clear(); for (std::size_t i = 0; i < cfgnMods->size(); i++) { int ind = cfgnMods->at(i); fullPath = cfgShiftPath; fullPath += "/v"; fullPath += std::to_string(ind); auto objshift = getForTsOrRun(fullPath, timestamp, runnumber); - shiftprofile.push_back(objshift); + shiftProfileSp.push_back(objshift); + } + + if (cfgProduceRedQVecs) { + shiftProfileEse.clear(); + for (std::size_t i = 0; i < cfgnMods->size(); i++) { + int ind = cfgnMods->at(i); + fullPath = cfgShiftPath; + fullPath += "/eseq"; + fullPath += std::to_string(ind); + auto objshift = getForTsOrRun(fullPath, timestamp, runnumber); + shiftProfileEse.push_back(objshift); + } } } fullPath = cfgGainEqPath; fullPath += "/FT0"; + const int nPixelsFT0 = 208; const auto objft0Gain = getForTsOrRun>(fullPath, timestamp, runnumber); if (!objft0Gain || cfgCorrLevel == 0) { - for (auto i{0u}; i < 208; i++) { + for (auto i{0u}; i < nPixelsFT0; i++) { FT0RelGainConst.push_back(1.); } } else { @@ -297,9 +362,10 @@ struct qVectorsTable { fullPath = cfgGainEqPath; fullPath += "/FV0"; + const int nChannelsFV0 = 48; const auto objfv0Gain = getForTsOrRun>(fullPath, timestamp, runnumber); if (!objfv0Gain || cfgCorrLevel == 0) { - for (auto i{0u}; i < 48; i++) { + for (auto i{0u}; i < nChannelsFV0; i++) { FV0RelGainConst.push_back(1.); } } else { @@ -308,7 +374,7 @@ struct qVectorsTable { } template - bool SelTrack(const TrackType track) + bool selTrack(const TrackType track) { if (track.pt() < cfgMinPtOnTPC) return false; @@ -347,19 +413,177 @@ struct qVectorsTable { } } + /// Function to normalize the q-vectors + /// \param qVecReNorm is the vector with the normalized real part of the q-vector for each detector and correction step + /// \param qVecImNorm is the vector with the normalized imaginary part of the q-vector for each detector and correction step + /// \param qVecReRaw is the vector with the raw real part of the q-vector for each detector and correction step + /// \param qVecImRaw is the vector with the raw imaginary part of the q-vector for each detector and correction step + /// \param qVecAmp is the vector with the amplitude of the q-vector for each detector and correction step + /// \param normType is the type of normalization to apply to the q-vectors + void normalizeQVec(std::vector& qVecReNorm, + std::vector& qVecImNorm, + std::vector const& qVecReRaw, + std::vector const& qVecImRaw, + std::vector const& qVecAmp, + MultNorms normType) + { + for (std::size_t i = 0; i < kNDetectors; i++) { + float qVecDetReNorm{-999.}, qVecDetImNorm{-999.}; + if (qVecAmp[i] > minAmplitude) { + switch (normType) { + case MultNorms::kScalarProd: + qVecDetReNorm = qVecReRaw[i] / qVecAmp[i]; + qVecDetImNorm = qVecImRaw[i] / qVecAmp[i]; + break; + case MultNorms::kEsE: + qVecDetReNorm = qVecReRaw[i] / std::sqrt(qVecAmp[i]); + qVecDetImNorm = qVecImRaw[i] / std::sqrt(qVecAmp[i]); + break; + default: + LOGP(fatal, "Undefined normalization type for Q-vector amplitude. Check the configuration."); + break; + } + } + for (int iCorr = 0; iCorr < kNCorrections; iCorr++) { + qVecReNorm.push_back(qVecDetReNorm); + qVecImNorm.push_back(qVecDetImNorm); + } + } + } + + /// Function to calculate the un-normalized q-vectors + /// \param cent is the collision centrality + /// \param qVecRe is the vector with the real part of the q-vector for each detector and correction step + /// \param qVecIm is the vector with the imaginary part of the q-vector for each detector and correction step + /// \param histsCorrs is the vector with the histograms with the correction constants for each detector and correction step + /// \param nMode is the modulation of interest + void correctQVec(float cent, std::vector& qVecRe, std::vector& qVecIm, TH3F* histsCorrs, std::vector& shiftProfile, int nMode) + { + int nCorrections = static_cast(kNCorrections); + if (cent < cfgMaxCentrality) { + for (auto i{0u}; i < kTPCAll + 1; i++) { + int idxDet = i * kNCorrections; + helperEP.DoRecenter(qVecRe[idxDet + kRecenter], qVecIm[idxDet + kRecenter], + histsCorrs->GetBinContent(static_cast(cent) + 1, 1, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 2, i + 1)); + + helperEP.DoRecenter(qVecRe[idxDet + kTwist], qVecIm[idxDet + kTwist], + histsCorrs->GetBinContent(static_cast(cent) + 1, 1, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 2, i + 1)); + helperEP.DoTwist(qVecRe[idxDet + kTwist], qVecIm[idxDet + kTwist], + histsCorrs->GetBinContent(static_cast(cent) + 1, 3, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 4, i + 1)); + + helperEP.DoRecenter(qVecRe[idxDet + kRescale], qVecIm[idxDet + kRescale], + histsCorrs->GetBinContent(static_cast(cent) + 1, 1, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 2, i + 1)); + helperEP.DoTwist(qVecRe[idxDet + kRescale], qVecIm[idxDet + kRescale], + histsCorrs->GetBinContent(static_cast(cent) + 1, 3, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 4, i + 1)); + helperEP.DoRescale(qVecRe[idxDet + kRescale], qVecIm[idxDet + kRescale], + histsCorrs->GetBinContent(static_cast(cent) + 1, 5, i + 1), histsCorrs->GetBinContent(static_cast(cent) + 1, 6, i + 1)); + } + if (cfgShiftCorr) { + auto deltaPsiFT0C = 0.0; + auto deltaPsiFT0A = 0.0; + auto deltaPsiFT0M = 0.0; + auto deltaPsiFV0A = 0.0; + auto deltaPsiTPCPos = 0.0; + auto deltaPsiTPCNeg = 0.0; + auto deltaPsiTPCAll = 0.0; + + auto psiDefFT0C = std::atan2(qVecIm[kFT0C * nCorrections + kRescale], qVecRe[kFT0C * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefFT0A = std::atan2(qVecIm[kFT0A * nCorrections + kRescale], qVecRe[kFT0A * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefFT0M = std::atan2(qVecIm[kFT0M * nCorrections + kRescale], qVecRe[kFT0M * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefFV0A = std::atan2(qVecIm[kFV0A * nCorrections + kRescale], qVecRe[kFV0A * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefTPCPos = std::atan2(qVecIm[kTPCPos * nCorrections + kRescale], qVecRe[kTPCPos * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefTPCNeg = std::atan2(qVecIm[kTPCNeg * nCorrections + kRescale], qVecRe[kTPCNeg * nCorrections + kRescale]) / static_cast(nMode); + auto psiDefTPCAll = std::atan2(qVecIm[kTPCAll * nCorrections + kRescale], qVecRe[kTPCAll * nCorrections + kRescale]) / static_cast(nMode); + + for (int iShift = 1; iShift <= 10; iShift++) { + auto coeffShiftXFT0C = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0C, iShift - 0.5)); + auto coeffShiftYFT0C = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0C + 1, iShift - 0.5)); + auto coeffShiftXFT0A = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0A, iShift - 0.5)); + auto coeffShiftYFT0A = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0A + 1, iShift - 0.5)); + auto coeffShiftXFT0M = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0M, iShift - 0.5)); + auto coeffShiftYFT0M = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFT0M + 1, iShift - 0.5)); + auto coeffShiftXFV0A = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFV0A, iShift - 0.5)); + auto coeffShiftYFV0A = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kFV0A + 1, iShift - 0.5)); + auto coeffShiftXTPCPos = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCPos, iShift - 0.5)); + auto coeffShiftYTPCPos = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCPos + 1, iShift - 0.5)); + auto coeffShiftXTPCNeg = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCNeg, iShift - 0.5)); + auto coeffShiftYTPCNeg = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCNeg + 1, iShift - 0.5)); + auto coeffShiftXTPCAll = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCAll, iShift - 0.5)); + auto coeffShiftYTPCAll = shiftProfile.at(nMode - 2)->GetBinContent(shiftProfile.at(nMode - 2)->FindBin(cent, 2 * kTPCAll + 1, iShift - 0.5)); + + deltaPsiFT0C += ((2. / (1.0 * iShift)) * (-coeffShiftXFT0C * std::cos(iShift * static_cast(nMode) * psiDefFT0C) + coeffShiftYFT0C * std::sin(iShift * static_cast(nMode) * psiDefFT0C))) / static_cast(nMode); + deltaPsiFT0A += ((2. / (1.0 * iShift)) * (-coeffShiftXFT0A * std::cos(iShift * static_cast(nMode) * psiDefFT0A) + coeffShiftYFT0A * std::sin(iShift * static_cast(nMode) * psiDefFT0A))) / static_cast(nMode); + deltaPsiFT0M += ((2. / (1.0 * iShift)) * (-coeffShiftXFT0M * std::cos(iShift * static_cast(nMode) * psiDefFT0M) + coeffShiftYFT0M * std::sin(iShift * static_cast(nMode) * psiDefFT0M))) / static_cast(nMode); + deltaPsiFV0A += ((2. / (1.0 * iShift)) * (-coeffShiftXFV0A * std::cos(iShift * static_cast(nMode) * psiDefFV0A) + coeffShiftYFV0A * std::sin(iShift * static_cast(nMode) * psiDefFV0A))) / static_cast(nMode); + deltaPsiTPCPos += ((2. / (1.0 * iShift)) * (-coeffShiftXTPCPos * std::cos(iShift * static_cast(nMode) * psiDefTPCPos) + coeffShiftYTPCPos * std::sin(iShift * static_cast(nMode) * psiDefTPCPos))) / static_cast(nMode); + deltaPsiTPCNeg += ((2. / (1.0 * iShift)) * (-coeffShiftXTPCNeg * std::cos(iShift * static_cast(nMode) * psiDefTPCNeg) + coeffShiftYTPCNeg * std::sin(iShift * static_cast(nMode) * psiDefTPCNeg))) / static_cast(nMode); + deltaPsiTPCAll += ((2. / (1.0 * iShift)) * (-coeffShiftXTPCAll * std::cos(iShift * static_cast(nMode) * psiDefTPCAll) + coeffShiftYTPCAll * std::sin(iShift * static_cast(nMode) * psiDefTPCAll))) / static_cast(nMode); + } + + deltaPsiFT0C *= static_cast(nMode); + deltaPsiFT0A *= static_cast(nMode); + deltaPsiFT0M *= static_cast(nMode); + deltaPsiFV0A *= static_cast(nMode); + deltaPsiTPCPos *= static_cast(nMode); + deltaPsiTPCNeg *= static_cast(nMode); + deltaPsiTPCAll *= static_cast(nMode); + + float qVecReShiftedFT0C = qVecRe[kFT0C * nCorrections + kRescale] * std::cos(deltaPsiFT0C) - qVecIm[kFT0C * nCorrections + kRescale] * std::sin(deltaPsiFT0C); + float qVecImShiftedFT0C = qVecRe[kFT0C * nCorrections + kRescale] * std::sin(deltaPsiFT0C) + qVecIm[kFT0C * nCorrections + kRescale] * std::cos(deltaPsiFT0C); + float qVecReShiftedFT0A = qVecRe[kFT0A * nCorrections + kRescale] * std::cos(deltaPsiFT0A) - qVecIm[kFT0A * nCorrections + kRescale] * std::sin(deltaPsiFT0A); + float qVecImShiftedFT0A = qVecRe[kFT0A * nCorrections + kRescale] * std::sin(deltaPsiFT0A) + qVecIm[kFT0A * nCorrections + kRescale] * std::cos(deltaPsiFT0A); + float qVecReShiftedFT0M = qVecRe[kFT0M * nCorrections + kRescale] * std::cos(deltaPsiFT0M) - qVecIm[kFT0M * nCorrections + kRescale] * std::sin(deltaPsiFT0M); + float qVecImShiftedFT0M = qVecRe[kFT0M * nCorrections + kRescale] * std::sin(deltaPsiFT0M) + qVecIm[kFT0M * nCorrections + kRescale] * std::cos(deltaPsiFT0M); + float qVecReShiftedFV0A = qVecRe[kFV0A * nCorrections + kRescale] * std::cos(deltaPsiFV0A) - qVecIm[kFV0A * nCorrections + kRescale] * std::sin(deltaPsiFV0A); + float qVecImShiftedFV0A = qVecRe[kFV0A * nCorrections + kRescale] * std::sin(deltaPsiFV0A) + qVecIm[kFV0A * nCorrections + kRescale] * std::cos(deltaPsiFV0A); + float qVecReShiftedTPCPos = qVecRe[kTPCPos * nCorrections + kRescale] * std::cos(deltaPsiTPCPos) - qVecIm[kTPCPos * nCorrections + kRescale] * std::sin(deltaPsiTPCPos); + float qVecImShiftedTPCPos = qVecRe[kTPCPos * nCorrections + kRescale] * std::sin(deltaPsiTPCPos) + qVecIm[kTPCPos * nCorrections + kRescale] * std::cos(deltaPsiTPCPos); + float qVecReShiftedTPCNeg = qVecRe[kTPCNeg * nCorrections + kRescale] * std::cos(deltaPsiTPCNeg) - qVecIm[kTPCNeg * nCorrections + kRescale] * std::sin(deltaPsiTPCNeg); + float qVecImShiftedTPCNeg = qVecRe[kTPCNeg * nCorrections + kRescale] * std::sin(deltaPsiTPCNeg) + qVecIm[kTPCNeg * nCorrections + kRescale] * std::cos(deltaPsiTPCNeg); + float qVecReShiftedTPCAll = qVecRe[kTPCAll * nCorrections + kRescale] * std::cos(deltaPsiTPCAll) - qVecIm[kTPCAll * nCorrections + kRescale] * std::sin(deltaPsiTPCAll); + float qVecImShiftedTPCAll = qVecRe[kTPCAll * nCorrections + kRescale] * std::sin(deltaPsiTPCAll) + qVecIm[kTPCAll * nCorrections + kRescale] * std::cos(deltaPsiTPCAll); + + qVecRe[kFT0C * nCorrections + kRescale] = qVecReShiftedFT0C; + qVecIm[kFT0C * nCorrections + kRescale] = qVecImShiftedFT0C; + qVecRe[kFT0A * nCorrections + kRescale] = qVecReShiftedFT0A; + qVecIm[kFT0A * nCorrections + kRescale] = qVecImShiftedFT0A; + qVecRe[kFT0M * nCorrections + kRescale] = qVecReShiftedFT0M; + qVecIm[kFT0M * nCorrections + kRescale] = qVecImShiftedFT0M; + qVecRe[kFV0A * nCorrections + kRescale] = qVecReShiftedFV0A; + qVecIm[kFV0A * nCorrections + kRescale] = qVecImShiftedFV0A; + qVecRe[kTPCPos * nCorrections + kRescale] = qVecReShiftedTPCPos; + qVecIm[kTPCPos * nCorrections + kRescale] = qVecImShiftedTPCPos; + qVecRe[kTPCNeg * nCorrections + kRescale] = qVecReShiftedTPCNeg; + qVecIm[kTPCNeg * nCorrections + kRescale] = qVecImShiftedTPCNeg; + qVecRe[kTPCAll * nCorrections + kRescale] = qVecReShiftedTPCAll; + qVecIm[kTPCAll * nCorrections + kRescale] = qVecImShiftedTPCAll; + } + } + } + + /// Function to calculate the un-normalized q-vectors + /// \param nMode is the harmonic number of the q-vector + /// \param coll is the collision object + /// \param tracks are the tracks associated to the collision + /// \param qVecRe is the vector with the real part of the q-vector for each detector + /// \param qVecIm is the vector with the imaginary part of the q-vector for each detector + /// \param qVecAmp is the vector with the amplitude of the signal in each detector + /// \param trkTPCPosLabel is the vector with the number of TPC tracks with positive eta + /// \param trkTPCNegLabel is the vector with the number of TPC tracks with negative eta + /// \param trkTPCAllLabel is the vector with the number of TPC tracks with any eta template - void CalQvec(const Nmode nmode, const CollType& coll, const TrackType& track, std::vector& QvecRe, std::vector& QvecIm, std::vector& QvecAmp, std::vector& TrkTPCposLabel, std::vector& TrkTPCnegLabel, std::vector& TrkTPCallLabel) + void calcQVec(const Nmode nMode, const CollType& coll, const TrackType& tracks, std::vector& qVecRe, std::vector& qVecIm, std::vector& qVecAmp, std::vector& trkTPCPosLabel, std::vector& trkTPCNegLabel, std::vector& trkTPCAllLabel) { - float qVectFT0A[2] = {0.}; - float qVectFT0C[2] = {0.}; - float qVectFT0M[2] = {0.}; - float qVectFV0A[2] = {0.}; - float qVectTPCpos[2] = {0.}; - float qVectTPCneg[2] = {0.}; - float qVectTPCall[2] = {0.}; - - TComplex QvecDet(0); - TComplex QvecFT0M(0); + float qVectFT0A[2] = {-999., -999.}; + float qVectFT0C[2] = {-999., -999.}; + float qVectFT0M[2] = {-999., -999.}; + float qVectFV0A[2] = {-999., -999.}; + float qVectTPCPos[2] = {0., 0.}; // Always computed + float qVectTPCNeg[2] = {0., 0.}; // Always computed + float qVectTPCAll[2] = {0., 0.}; // Always computed + + TComplex qVecDet(0); + TComplex qVecFT0M(0); float sumAmplFT0A = 0.; float sumAmplFT0C = 0.; float sumAmplFT0M = 0.; @@ -376,21 +600,17 @@ struct qVectorsTable { histosQA.fill(HIST("FT0Amp"), ampl, FT0AchId); histosQA.fill(HIST("FT0AmpCor"), ampl / FT0RelGainConst[FT0AchId], FT0AchId); - helperEP.SumQvectors(0, FT0AchId, ampl / FT0RelGainConst[FT0AchId], nmode, QvecDet, sumAmplFT0A, ft0geom, fv0geom); - helperEP.SumQvectors(0, FT0AchId, ampl / FT0RelGainConst[FT0AchId], nmode, QvecFT0M, sumAmplFT0M, ft0geom, fv0geom); + helperEP.SumQvectors(0, FT0AchId, ampl / FT0RelGainConst[FT0AchId], nMode, qVecDet, sumAmplFT0A, ft0geom, fv0geom); + helperEP.SumQvectors(0, FT0AchId, ampl / FT0RelGainConst[FT0AchId], nMode, qVecFT0M, sumAmplFT0M, ft0geom, fv0geom); } - if (sumAmplFT0A > 1e-8) { - QvecDet /= sumAmplFT0A; - qVectFT0A[0] = QvecDet.Re(); - qVectFT0A[1] = QvecDet.Im(); + if (sumAmplFT0A > minAmplitude) { + qVectFT0A[0] = qVecDet.Re(); + qVectFT0A[1] = qVecDet.Im(); } - } else { - qVectFT0A[0] = 999.; - qVectFT0A[1] = 999.; } if (useDetector["QvectorFT0Cs"]) { - QvecDet = TComplex(0., 0.); + qVecDet = TComplex(0., 0.); for (std::size_t iChC = 0; iChC < ft0.channelC().size(); iChC++) { float ampl = ft0.amplitudeC()[iChC]; int FT0CchId = ft0.channelC()[iChC] + 96; @@ -398,73 +618,47 @@ struct qVectorsTable { histosQA.fill(HIST("FT0Amp"), ampl, FT0CchId); histosQA.fill(HIST("FT0AmpCor"), ampl / FT0RelGainConst[FT0CchId], FT0CchId); - helperEP.SumQvectors(0, FT0CchId, ampl / FT0RelGainConst[FT0CchId], nmode, QvecDet, sumAmplFT0C, ft0geom, fv0geom); - helperEP.SumQvectors(0, FT0CchId, ampl / FT0RelGainConst[FT0CchId], nmode, QvecFT0M, sumAmplFT0M, ft0geom, fv0geom); + helperEP.SumQvectors(0, FT0CchId, ampl / FT0RelGainConst[FT0CchId], nMode, qVecDet, sumAmplFT0C, ft0geom, fv0geom); + helperEP.SumQvectors(0, FT0CchId, ampl / FT0RelGainConst[FT0CchId], nMode, qVecFT0M, sumAmplFT0M, ft0geom, fv0geom); } - if (sumAmplFT0C > 1e-8) { - QvecDet /= sumAmplFT0C; - qVectFT0C[0] = QvecDet.Re(); - qVectFT0C[1] = QvecDet.Im(); - } else { - qVectFT0C[0] = 999.; - qVectFT0C[1] = 999.; + if (sumAmplFT0C > minAmplitude) { + qVectFT0C[0] = qVecDet.Re(); + qVectFT0C[1] = qVecDet.Im(); + } + if (sumAmplFT0M > minAmplitude && useDetector["QvectorFT0Ms"]) { + qVectFT0M[0] = qVecFT0M.Re(); + qVectFT0M[1] = qVecFT0M.Im(); } - } else { - qVectFT0C[0] = -999.; - qVectFT0C[1] = -999.; - } - - if (sumAmplFT0M > 1e-8 && useDetector["QvectorFT0Ms"]) { - QvecFT0M /= sumAmplFT0M; - qVectFT0M[0] = QvecFT0M.Re(); - qVectFT0M[1] = QvecFT0M.Im(); - } else { - qVectFT0M[0] = 999.; - qVectFT0M[1] = 999.; } - } else { - qVectFT0A[0] = -999.; - qVectFT0A[1] = -999.; - qVectFT0C[0] = -999.; - qVectFT0C[1] = -999.; - qVectFT0M[0] = -999.; - qVectFT0M[1] = -999.; - } - QvecDet = TComplex(0., 0.); - sumAmplFV0A = 0; - if (coll.has_foundFV0() && useDetector["QvectorFV0As"]) { - auto fv0 = coll.foundFV0(); + qVecDet = TComplex(0., 0.); + sumAmplFV0A = 0; + if (coll.has_foundFV0() && useDetector["QvectorFV0As"]) { + auto fv0 = coll.foundFV0(); - for (std::size_t iCh = 0; iCh < fv0.channel().size(); iCh++) { - float ampl = fv0.amplitude()[iCh]; - int FV0AchId = fv0.channel()[iCh]; - histosQA.fill(HIST("FV0Amp"), ampl, FV0AchId); - histosQA.fill(HIST("FV0AmpCor"), ampl / FV0RelGainConst[FV0AchId], FV0AchId); + for (std::size_t iCh = 0; iCh < fv0.channel().size(); iCh++) { + float ampl = fv0.amplitude()[iCh]; + int FV0AchId = fv0.channel()[iCh]; + histosQA.fill(HIST("FV0Amp"), ampl, FV0AchId); + histosQA.fill(HIST("FV0AmpCor"), ampl / FV0RelGainConst[FV0AchId], FV0AchId); - helperEP.SumQvectors(1, FV0AchId, ampl / FV0RelGainConst[FV0AchId], nmode, QvecDet, sumAmplFV0A, ft0geom, fv0geom); - } + helperEP.SumQvectors(1, FV0AchId, ampl / FV0RelGainConst[FV0AchId], nMode, qVecDet, sumAmplFV0A, ft0geom, fv0geom); + } - if (sumAmplFV0A > 1e-8) { - QvecDet /= sumAmplFV0A; - qVectFV0A[0] = QvecDet.Re(); - qVectFV0A[1] = QvecDet.Im(); - } else { - qVectFV0A[0] = 999.; - qVectFV0A[1] = 999.; + if (sumAmplFV0A > minAmplitude) { + qVectFV0A[0] = qVecDet.Re(); + qVectFV0A[1] = qVecDet.Im(); + } } - } else { - qVectFV0A[0] = -999.; - qVectFV0A[1] = -999.; } - int nTrkTPCpos = 0; - int nTrkTPCneg = 0; - int nTrkTPCall = 0; + int nTrkTPCPos = 0; + int nTrkTPCNeg = 0; + int nTrkTPCAll = 0; - for (auto const& trk : track) { - if (!SelTrack(trk)) { + for (auto const& trk : tracks) { + if (!selTrack(trk)) { continue; } histosQA.fill(HIST("ChTracks"), trk.pt(), trk.eta(), trk.phi(), cent); @@ -474,110 +668,90 @@ struct qVectorsTable { if (trk.eta() < cfgEtaMin) { continue; } - qVectTPCall[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectTPCall[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkTPCallLabel.push_back(trk.globalIndex()); - nTrkTPCall++; + qVectTPCAll[0] += trk.pt() * std::cos(trk.phi() * nMode); + qVectTPCAll[1] += trk.pt() * std::sin(trk.phi() * nMode); + trkTPCAllLabel.push_back(trk.globalIndex()); + nTrkTPCAll++; if (std::abs(trk.eta()) < 0.1) { continue; } if (trk.eta() > 0 && (useDetector["QvectorTPCposs"] || useDetector["QvectorBPoss"])) { - qVectTPCpos[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectTPCpos[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkTPCposLabel.push_back(trk.globalIndex()); - nTrkTPCpos++; + qVectTPCPos[0] += trk.pt() * std::cos(trk.phi() * nMode); + qVectTPCPos[1] += trk.pt() * std::sin(trk.phi() * nMode); + trkTPCPosLabel.push_back(trk.globalIndex()); + nTrkTPCPos++; } else if (trk.eta() < 0 && (useDetector["QvectorTPCnegs"] || useDetector["QvectorBNegs"])) { - qVectTPCneg[0] += trk.pt() * std::cos(trk.phi() * nmode); - qVectTPCneg[1] += trk.pt() * std::sin(trk.phi() * nmode); - TrkTPCnegLabel.push_back(trk.globalIndex()); - nTrkTPCneg++; + qVectTPCNeg[0] += trk.pt() * std::cos(trk.phi() * nMode); + qVectTPCNeg[1] += trk.pt() * std::sin(trk.phi() * nMode); + trkTPCNegLabel.push_back(trk.globalIndex()); + nTrkTPCNeg++; } } - if (nTrkTPCpos > 0) { - qVectTPCpos[0] /= nTrkTPCpos; - qVectTPCpos[1] /= nTrkTPCpos; - } else { - qVectTPCpos[0] = 999.; - qVectTPCpos[1] = 999.; - } - - if (nTrkTPCneg > 0) { - qVectTPCneg[0] /= nTrkTPCneg; - qVectTPCneg[1] /= nTrkTPCneg; - } else { - qVectTPCneg[0] = 999.; - qVectTPCneg[1] = 999.; - } - - if (nTrkTPCall > 0) { - qVectTPCall[0] /= nTrkTPCall; - qVectTPCall[1] /= nTrkTPCall; - } else { - qVectTPCall[0] = 999.; - qVectTPCall[1] = 999.; - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectFT0C[0]); - QvecIm.push_back(qVectFT0C[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectFT0A[0]); - QvecIm.push_back(qVectFT0A[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectFT0M[0]); - QvecIm.push_back(qVectFT0M[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectFV0A[0]); - QvecIm.push_back(qVectFV0A[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectTPCpos[0]); - QvecIm.push_back(qVectTPCpos[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectTPCneg[0]); - QvecIm.push_back(qVectTPCneg[1]); - } - for (auto i{0u}; i < 4; i++) { - QvecRe.push_back(qVectTPCall[0]); - QvecIm.push_back(qVectTPCall[1]); - } - - QvecAmp.push_back(sumAmplFT0C); - QvecAmp.push_back(sumAmplFT0A); - QvecAmp.push_back(sumAmplFT0M); - QvecAmp.push_back(sumAmplFV0A); - QvecAmp.push_back(static_cast(nTrkTPCpos)); - QvecAmp.push_back(static_cast(nTrkTPCneg)); - QvecAmp.push_back(static_cast(nTrkTPCall)); + qVecRe.push_back(qVectFT0C[0]); + qVecIm.push_back(qVectFT0C[1]); + qVecRe.push_back(qVectFT0A[0]); + qVecIm.push_back(qVectFT0A[1]); + qVecRe.push_back(qVectFT0M[0]); + qVecIm.push_back(qVectFT0M[1]); + qVecRe.push_back(qVectFV0A[0]); + qVecIm.push_back(qVectFV0A[1]); + qVecRe.push_back(qVectTPCPos[0]); + qVecIm.push_back(qVectTPCPos[1]); + qVecRe.push_back(qVectTPCNeg[0]); + qVecIm.push_back(qVectTPCNeg[1]); + qVecRe.push_back(qVectTPCAll[0]); + qVecIm.push_back(qVectTPCAll[1]); + + qVecAmp.push_back(sumAmplFT0C); + qVecAmp.push_back(sumAmplFT0A); + qVecAmp.push_back(sumAmplFT0M); + qVecAmp.push_back(sumAmplFV0A); + qVecAmp.push_back(static_cast(nTrkTPCPos)); + qVecAmp.push_back(static_cast(nTrkTPCNeg)); + qVecAmp.push_back(static_cast(nTrkTPCAll)); } void process(MyCollisions::iterator const& coll, aod::BCsWithTimestamps const&, aod::FT0s const&, aod::FV0As const&, MyTracks const& tracks) { - std::vector TrkTPCposLabel{}; - std::vector TrkTPCnegLabel{}; - std::vector TrkTPCallLabel{}; - std::vector qvecRe{}; - std::vector qvecIm{}; - std::vector qvecAmp{}; - - std::vector qvecReFT0C{}; - std::vector qvecImFT0C{}; - std::vector qvecReFT0A{}; - std::vector qvecImFT0A{}; - std::vector qvecReFT0M{}; - std::vector qvecImFT0M{}; - std::vector qvecReFV0A{}; - std::vector qvecImFV0A{}; - std::vector qvecReTPCpos{}; - std::vector qvecImTPCpos{}; - std::vector qvecReTPCneg{}; - std::vector qvecImTPCneg{}; - std::vector qvecReTPCall{}; - std::vector qvecImTPCall{}; + std::vector trkTPCPosLabel{}; + std::vector trkTPCNegLabel{}; + std::vector trkTPCAllLabel{}; + std::vector qVecAmp{}; + + std::vector qVecReSp{}; + std::vector qVecImSp{}; + std::vector qVecReFT0CSp{}; + std::vector qVecImFT0CSp{}; + std::vector qVecReFT0ASp{}; + std::vector qVecImFT0ASp{}; + std::vector qVecReFT0MSp{}; + std::vector qVecImFT0MSp{}; + std::vector qVecReFV0ASp{}; + std::vector qVecImFV0ASp{}; + std::vector qVecReTPCPosSp{}; + std::vector qVecImTPCPosSp{}; + std::vector qVecReTPCNegSp{}; + std::vector qVecImTPCNegSp{}; + std::vector qVecReTPCAllSp{}; + std::vector qVecImTPCAllSp{}; + + std::vector qVecReEse{}; + std::vector qVecImEse{}; + std::vector qVecReFT0CEse{}; + std::vector qVecImFT0CEse{}; + std::vector qVecReFT0AEse{}; + std::vector qVecImFT0AEse{}; + std::vector qVecReFT0MEse{}; + std::vector qVecImFT0MEse{}; + std::vector qVecReFV0AEse{}; + std::vector qVecImFV0AEse{}; + std::vector qVecReTPCPosEse{}; + std::vector qVecImTPCPosEse{}; + std::vector qVecReTPCNegEse{}; + std::vector qVecImTPCNegEse{}; + std::vector qVecReTPCAllEse{}; + std::vector qVecImTPCAllEse{}; auto bc = coll.bc_as(); int currentRun = bc.runNumber(); @@ -590,167 +764,138 @@ struct qVectorsTable { coll.centFT0M(), coll.centFT0A(), coll.centFT0C(), coll.centFV0A()}; cent = centAllEstim[cfgCentEsti]; - bool IsCalibrated = true; + bool isCalibrated = true; if (cent < 0. || cent > cfgMaxCentrality) { cent = 110.; - IsCalibrated = false; + isCalibrated = false; } - for (std::size_t id = 0; id < cfgnMods->size(); id++) { - int nmode = cfgnMods->at(id); - CalQvec(nmode, coll, tracks, qvecRe, qvecIm, qvecAmp, TrkTPCposLabel, TrkTPCnegLabel, TrkTPCallLabel); - if (cent < cfgMaxCentrality) { - for (auto i{0u}; i < kTPCall + 1; i++) { - helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 1], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 1], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - - helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 2], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 2], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - helperEP.DoTwist(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 2], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 2], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 3, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 4, i + 1)); - - helperEP.DoRecenter(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 1, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 2, i + 1)); - helperEP.DoTwist(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 3, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 4, i + 1)); - helperEP.DoRescale(qvecRe[(kTPCall + 1) * 4 * id + i * 4 + 3], qvecIm[(kTPCall + 1) * 4 * id + i * 4 + 3], - objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 5, i + 1), objQvec.at(id)->GetBinContent(static_cast(cent) + 1, 6, i + 1)); - } - if (cfgShiftCorr) { - auto deltapsiFT0C = 0.0; - auto deltapsiFT0A = 0.0; - auto deltapsiFT0M = 0.0; - auto deltapsiFV0A = 0.0; - auto deltapsiTPCpos = 0.0; - auto deltapsiTPCneg = 0.0; - auto deltapsiTPCall = 0.0; - - auto psidefFT0C = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3]) / static_cast(nmode); - auto psidefFT0A = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3]) / static_cast(nmode); - auto psidefFT0M = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3]) / static_cast(nmode); - auto psidefFV0A = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3]) / static_cast(nmode); - auto psidefTPCpos = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3]) / static_cast(nmode); - auto psidefTPCneg = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3]) / static_cast(nmode); - auto psidefTPCall = TMath::ATan2(qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3], qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3]) / static_cast(nmode); - - for (int ishift = 1; ishift <= 10; ishift++) { - auto coeffshiftxFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0C, ishift - 0.5)); - auto coeffshiftyFT0C = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0C + 1, ishift - 0.5)); - auto coeffshiftxFT0A = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0A, ishift - 0.5)); - auto coeffshiftyFT0A = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0A + 1, ishift - 0.5)); - auto coeffshiftxFT0M = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0M, ishift - 0.5)); - auto coeffshiftyFT0M = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFT0M + 1, ishift - 0.5)); - auto coeffshiftxFV0A = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFV0A, ishift - 0.5)); - auto coeffshiftyFV0A = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kFV0A + 1, ishift - 0.5)); - auto coeffshiftxTPCpos = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCpos, ishift - 0.5)); - auto coeffshiftyTPCpos = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCpos + 1, ishift - 0.5)); - auto coeffshiftxTPCneg = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCneg, ishift - 0.5)); - auto coeffshiftyTPCneg = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCneg + 1, ishift - 0.5)); - auto coeffshiftxTPCall = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCall, ishift - 0.5)); - auto coeffshiftyTPCall = shiftprofile.at(nmode - 2)->GetBinContent(shiftprofile.at(nmode - 2)->FindBin(cent, 2 * kTPCall + 1, ishift - 0.5)); - - deltapsiFT0C += ((2. / (1.0 * ishift)) * (-coeffshiftxFT0C * TMath::Cos(ishift * static_cast(nmode) * psidefFT0C) + coeffshiftyFT0C * TMath::Sin(ishift * static_cast(nmode) * psidefFT0C))) / static_cast(nmode); - deltapsiFT0A += ((2. / (1.0 * ishift)) * (-coeffshiftxFT0A * TMath::Cos(ishift * static_cast(nmode) * psidefFT0A) + coeffshiftyFT0A * TMath::Sin(ishift * static_cast(nmode) * psidefFT0A))) / static_cast(nmode); - deltapsiFT0M += ((2. / (1.0 * ishift)) * (-coeffshiftxFT0M * TMath::Cos(ishift * static_cast(nmode) * psidefFT0M) + coeffshiftyFT0M * TMath::Sin(ishift * static_cast(nmode) * psidefFT0M))) / static_cast(nmode); - deltapsiFV0A += ((2. / (1.0 * ishift)) * (-coeffshiftxFV0A * TMath::Cos(ishift * static_cast(nmode) * psidefFV0A) + coeffshiftyFV0A * TMath::Sin(ishift * static_cast(nmode) * psidefFV0A))) / static_cast(nmode); - deltapsiTPCpos += ((2. / (1.0 * ishift)) * (-coeffshiftxTPCpos * TMath::Cos(ishift * static_cast(nmode) * psidefTPCpos) + coeffshiftyTPCpos * TMath::Sin(ishift * static_cast(nmode) * psidefTPCpos))) / static_cast(nmode); - deltapsiTPCneg += ((2. / (1.0 * ishift)) * (-coeffshiftxTPCneg * TMath::Cos(ishift * static_cast(nmode) * psidefTPCneg) + coeffshiftyTPCneg * TMath::Sin(ishift * static_cast(nmode) * psidefTPCneg))) / static_cast(nmode); - deltapsiTPCall += ((2. / (1.0 * ishift)) * (-coeffshiftxTPCall * TMath::Cos(ishift * static_cast(nmode) * psidefTPCall) + coeffshiftyTPCall * TMath::Sin(ishift * static_cast(nmode) * psidefTPCall))) / static_cast(nmode); - } - deltapsiFT0C *= static_cast(nmode); - deltapsiFT0A *= static_cast(nmode); - deltapsiFT0M *= static_cast(nmode); - deltapsiFV0A *= static_cast(nmode); - deltapsiTPCpos *= static_cast(nmode); - deltapsiTPCneg *= static_cast(nmode); - deltapsiTPCall *= static_cast(nmode); - - float qvecReShiftedFT0C = qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C) - qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C); - float qvecImShiftedFT0C = qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C) + qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C); - float qvecReShiftedFT0A = qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A) - qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A); - float qvecImShiftedFT0A = qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A) + qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A); - float qvecReShiftedFT0M = qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M) - qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M); - float qvecImShiftedFT0M = qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M) + qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M); - float qvecReShiftedFV0A = qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A) - qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A); - float qvecImShiftedFV0A = qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A) + qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A); - float qvecReShiftedTPCpos = qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos) - qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos); - float qvecImShiftedTPCpos = qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos) + qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos); - float qvecReShiftedTPCneg = qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg) - qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg); - float qvecImShiftedTPCneg = qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg) + qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg); - float qvecReShiftedTPCall = qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall) - qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall); - float qvecImShiftedTPCall = qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall) + qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall); - - qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] = qvecReShiftedFT0C; - qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] = qvecImShiftedFT0C; - qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] = qvecReShiftedFT0A; - qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] = qvecImShiftedFT0A; - qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] = qvecReShiftedFT0M; - qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] = qvecImShiftedFT0M; - qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] = qvecReShiftedFV0A; - qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] = qvecImShiftedFV0A; - qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] = qvecReShiftedTPCpos; - qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] = qvecImShiftedTPCpos; - qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] = qvecReShiftedTPCneg; - qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] = qvecImShiftedTPCneg; - qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] = qvecReShiftedTPCall; - qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] = qvecImShiftedTPCall; - } + for (std::size_t id = 0; id < cfgnMods->size(); id++) { + int nMode = cfgnMods->at(id); + + // Raw Q-vectors, no multiplicity normalization and no corrections + std::vector qVecReRaw{}; + std::vector qVecImRaw{}; + calcQVec(nMode, coll, tracks, qVecReRaw, qVecImRaw, qVecAmp, trkTPCPosLabel, trkTPCNegLabel, trkTPCAllLabel); + + // Scalar Product Q-vectors, normalization by multiplicity/amplitude + std::vector nModeQVecReSp{}; + std::vector nModeQVecImSp{}; + normalizeQVec(nModeQVecReSp, nModeQVecImSp, qVecReRaw, qVecImRaw, qVecAmp, MultNorms::kScalarProd); + correctQVec(cent, nModeQVecReSp, nModeQVecImSp, corrsQvecSp[id], shiftProfileSp, nMode); + // Add to summary vector + qVecReSp.insert(qVecReSp.end(), nModeQVecReSp.begin(), nModeQVecReSp.end()); + qVecImSp.insert(qVecImSp.end(), nModeQVecImSp.begin(), nModeQVecImSp.end()); + + // Pick the desired correction level for the Q-vectors to be stored in the analysis table + int corrLevel = cfgCorrLevel == 0 ? 0 : cfgCorrLevel - 1; + int nCorrections = static_cast(kNCorrections); + + qVecReFT0CSp.push_back(nModeQVecReSp[kFT0C * nCorrections + corrLevel]); + qVecImFT0CSp.push_back(nModeQVecImSp[kFT0C * nCorrections + corrLevel]); + qVecReFT0ASp.push_back(nModeQVecReSp[kFT0A * nCorrections + corrLevel]); + qVecImFT0ASp.push_back(nModeQVecImSp[kFT0A * nCorrections + corrLevel]); + qVecReFT0MSp.push_back(nModeQVecReSp[kFT0M * nCorrections + corrLevel]); + qVecImFT0MSp.push_back(nModeQVecImSp[kFT0M * nCorrections + corrLevel]); + qVecReFV0ASp.push_back(nModeQVecReSp[kFV0A * nCorrections + corrLevel]); + qVecImFV0ASp.push_back(nModeQVecImSp[kFV0A * nCorrections + corrLevel]); + qVecReTPCPosSp.push_back(nModeQVecReSp[kTPCPos * nCorrections + corrLevel]); + qVecImTPCPosSp.push_back(nModeQVecImSp[kTPCPos * nCorrections + corrLevel]); + qVecReTPCNegSp.push_back(nModeQVecReSp[kTPCNeg * nCorrections + corrLevel]); + qVecImTPCNegSp.push_back(nModeQVecImSp[kTPCNeg * nCorrections + corrLevel]); + qVecReTPCAllSp.push_back(nModeQVecReSp[kTPCAll * nCorrections + corrLevel]); + qVecImTPCAllSp.push_back(nModeQVecImSp[kTPCAll * nCorrections + corrLevel]); + + if (cfgProduceRedQVecs) { + + // Ese Q-vectors, normalization by sqrt(multiplicity/amplitude) + std::vector nModeQVecReEse{}; + std::vector nModeQVecImEse{}; + normalizeQVec(nModeQVecReEse, nModeQVecImEse, qVecReRaw, qVecImRaw, qVecAmp, MultNorms::kEsE); + correctQVec(cent, nModeQVecReEse, nModeQVecImEse, corrsQvecEse[id], shiftProfileEse, nMode); + // Add to summary vector + qVecReEse.insert(qVecReEse.end(), nModeQVecReEse.begin(), nModeQVecReEse.end()); + qVecImEse.insert(qVecImEse.end(), nModeQVecImEse.begin(), nModeQVecImEse.end()); + + qVecReFT0CEse.push_back(nModeQVecReEse[kFT0C * nCorrections + corrLevel]); + qVecImFT0CEse.push_back(nModeQVecImEse[kFT0C * nCorrections + corrLevel]); + qVecReFT0AEse.push_back(nModeQVecReEse[kFT0A * nCorrections + corrLevel]); + qVecImFT0AEse.push_back(nModeQVecImEse[kFT0A * nCorrections + corrLevel]); + qVecReFT0MEse.push_back(nModeQVecReEse[kFT0M * nCorrections + corrLevel]); + qVecImFT0MEse.push_back(nModeQVecImEse[kFT0M * nCorrections + corrLevel]); + qVecReFV0AEse.push_back(nModeQVecReEse[kFV0A * nCorrections + corrLevel]); + qVecImFV0AEse.push_back(nModeQVecImEse[kFV0A * nCorrections + corrLevel]); + qVecReTPCPosEse.push_back(nModeQVecReEse[kTPCPos * nCorrections + corrLevel]); + qVecImTPCPosEse.push_back(nModeQVecImEse[kTPCPos * nCorrections + corrLevel]); + qVecReTPCNegEse.push_back(nModeQVecReEse[kTPCNeg * nCorrections + corrLevel]); + qVecImTPCNegEse.push_back(nModeQVecImEse[kTPCNeg * nCorrections + corrLevel]); + qVecReTPCAllEse.push_back(nModeQVecReEse[kTPCAll * nCorrections + corrLevel]); + qVecImTPCAllEse.push_back(nModeQVecImEse[kTPCAll * nCorrections + corrLevel]); } - int CorrLevel = cfgCorrLevel == 0 ? 0 : cfgCorrLevel - 1; - qvecReFT0C.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + CorrLevel]); - qvecImFT0C.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + CorrLevel]); - qvecReFT0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + CorrLevel]); - qvecImFT0A.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + CorrLevel]); - qvecReFT0M.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + CorrLevel]); - qvecImFT0M.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + CorrLevel]); - qvecReFV0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + CorrLevel]); - qvecImFV0A.push_back(qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + CorrLevel]); - qvecReTPCpos.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + CorrLevel]); - qvecImTPCpos.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + CorrLevel]); - qvecReTPCneg.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + CorrLevel]); - qvecImTPCneg.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + CorrLevel]); - qvecReTPCall.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + CorrLevel]); - qvecImTPCall.push_back(qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + CorrLevel]); } // Fill the columns of the Qvectors table. - qVector(cent, IsCalibrated, qvecRe, qvecIm, qvecAmp); + qVector(cent, isCalibrated, qVecReSp, qVecImSp, qVecAmp); if (useDetector["QvectorFT0Cs"]) - qVectorFT0C(IsCalibrated, qvecReFT0C.at(0), qvecImFT0C.at(0), qvecAmp[kFT0C]); + qVectorFT0C(isCalibrated, qVecReFT0CSp.at(0), qVecImFT0CSp.at(0), qVecAmp[kFT0C]); if (useDetector["QvectorFT0As"]) - qVectorFT0A(IsCalibrated, qvecReFT0A.at(0), qvecImFT0A.at(0), qvecAmp[kFT0A]); + qVectorFT0A(isCalibrated, qVecReFT0ASp.at(0), qVecImFT0ASp.at(0), qVecAmp[kFT0A]); if (useDetector["QvectorFT0Ms"]) - qVectorFT0M(IsCalibrated, qvecReFT0M.at(0), qvecImFT0M.at(0), qvecAmp[kFT0M]); + qVectorFT0M(isCalibrated, qVecReFT0MSp.at(0), qVecImFT0MSp.at(0), qVecAmp[kFT0M]); if (useDetector["QvectorFV0As"]) - qVectorFV0A(IsCalibrated, qvecReFV0A.at(0), qvecImFV0A.at(0), qvecAmp[kFV0A]); + qVectorFV0A(isCalibrated, qVecReFV0ASp.at(0), qVecImFV0ASp.at(0), qVecAmp[kFV0A]); if (useDetector["QvectorTPCposs"]) - qVectorTPCpos(IsCalibrated, qvecReTPCpos.at(0), qvecImTPCpos.at(0), qvecAmp[kTPCpos], TrkTPCposLabel); + qVectorTPCPos(isCalibrated, qVecReTPCPosSp.at(0), qVecImTPCPosSp.at(0), qVecAmp[kTPCPos], trkTPCPosLabel); if (useDetector["QvectorTPCnegs"]) - qVectorTPCneg(IsCalibrated, qvecReTPCneg.at(0), qvecImTPCneg.at(0), qvecAmp[kTPCneg], TrkTPCnegLabel); + qVectorTPCNeg(isCalibrated, qVecReTPCNegSp.at(0), qVecImTPCNegSp.at(0), qVecAmp[kTPCNeg], trkTPCNegLabel); if (useDetector["QvectorTPCalls"]) - qVectorTPCall(IsCalibrated, qvecReTPCall.at(0), qvecImTPCall.at(0), qvecAmp[kTPCall], TrkTPCallLabel); + qVectorTPCAll(isCalibrated, qVecReTPCAllSp.at(0), qVecImTPCAllSp.at(0), qVecAmp[kTPCAll], trkTPCAllLabel); - qVectorFT0CVec(IsCalibrated, qvecReFT0C, qvecImFT0C, qvecAmp[kFT0C]); - qVectorFT0AVec(IsCalibrated, qvecReFT0A, qvecImFT0A, qvecAmp[kFT0A]); - qVectorFT0MVec(IsCalibrated, qvecReFT0M, qvecImFT0M, qvecAmp[kFT0M]); - qVectorFV0AVec(IsCalibrated, qvecReFV0A, qvecImFV0A, qvecAmp[kFV0A]); - qVectorTPCposVec(IsCalibrated, qvecReTPCpos, qvecImTPCpos, qvecAmp[kTPCpos], TrkTPCposLabel); - qVectorTPCnegVec(IsCalibrated, qvecReTPCneg, qvecImTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); - qVectorTPCallVec(IsCalibrated, qvecReTPCall, qvecImTPCall, qvecAmp[kTPCall], TrkTPCallLabel); + qVectorFT0CVec(isCalibrated, qVecReFT0CSp, qVecImFT0CSp, qVecAmp[kFT0C]); + qVectorFT0AVec(isCalibrated, qVecReFT0ASp, qVecImFT0ASp, qVecAmp[kFT0A]); + qVectorFT0MVec(isCalibrated, qVecReFT0MSp, qVecImFT0MSp, qVecAmp[kFT0M]); + qVectorFV0AVec(isCalibrated, qVecReFV0ASp, qVecImFV0ASp, qVecAmp[kFV0A]); + qVectorTPCPosVec(isCalibrated, qVecReTPCPosSp, qVecImTPCPosSp, qVecAmp[kTPCPos], trkTPCPosLabel); + qVectorTPCNegVec(isCalibrated, qVecReTPCNegSp, qVecImTPCNegSp, qVecAmp[kTPCNeg], trkTPCNegLabel); + qVectorTPCAllVec(isCalibrated, qVecReTPCAllSp, qVecImTPCAllSp, qVecAmp[kTPCAll], trkTPCAllLabel); // Deprecated, will be removed in future after transition time // if (useDetector["QvectorBPoss"]) - qVectorBPos(IsCalibrated, qvecReTPCpos.at(0), qvecImTPCpos.at(0), qvecAmp[kTPCpos], TrkTPCposLabel); + qVectorBPos(isCalibrated, qVecReTPCPosSp.at(0), qVecImTPCPosSp.at(0), qVecAmp[kTPCPos], trkTPCPosLabel); if (useDetector["QvectorBNegs"]) - qVectorBNeg(IsCalibrated, qvecReTPCneg.at(0), qvecImTPCneg.at(0), qvecAmp[kTPCneg], TrkTPCnegLabel); + qVectorBNeg(isCalibrated, qVecReTPCNegSp.at(0), qVecImTPCNegSp.at(0), qVecAmp[kTPCNeg], trkTPCNegLabel); if (useDetector["QvectorBTots"]) - qVectorBTot(IsCalibrated, qvecReTPCall.at(0), qvecImTPCall.at(0), qvecAmp[kTPCall], TrkTPCallLabel); + qVectorBTot(isCalibrated, qVecReTPCAllSp.at(0), qVecImTPCAllSp.at(0), qVecAmp[kTPCAll], trkTPCAllLabel); - qVectorBPosVec(IsCalibrated, qvecReTPCpos, qvecImTPCpos, qvecAmp[kTPCpos], TrkTPCposLabel); - qVectorBNegVec(IsCalibrated, qvecReTPCneg, qvecImTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); - qVectorBTotVec(IsCalibrated, qvecReTPCall, qvecImTPCall, qvecAmp[kTPCall], TrkTPCallLabel); + qVectorBPosVec(isCalibrated, qVecReTPCPosSp, qVecImTPCPosSp, qVecAmp[kTPCPos], trkTPCPosLabel); + qVectorBNegVec(isCalibrated, qVecReTPCNegSp, qVecImTPCNegSp, qVecAmp[kTPCNeg], trkTPCNegLabel); + qVectorBTotVec(isCalibrated, qVecReTPCAllSp, qVecImTPCAllSp, qVecAmp[kTPCAll], trkTPCAllLabel); ///////////////////////////////////////////////////////////////// + if (cfgProduceRedQVecs) { + eseQVector(cent, isCalibrated, qVecReEse, qVecImEse, qVecAmp); + eseQVectorFT0C(isCalibrated, qVecReFT0CEse.at(0), qVecImFT0CEse.at(0), qVecAmp[kFT0C]); + eseQVectorFT0A(isCalibrated, qVecReFT0AEse.at(0), qVecImFT0AEse.at(0), qVecAmp[kFT0A]); + eseQVectorFT0M(isCalibrated, qVecReFT0MEse.at(0), qVecImFT0MEse.at(0), qVecAmp[kFT0M]); + eseQVectorFV0A(isCalibrated, qVecReFV0AEse.at(0), qVecImFV0AEse.at(0), qVecAmp[kFV0A]); + eseQVectorTPCPos(isCalibrated, qVecReTPCPosEse.at(0), qVecImTPCPosEse.at(0), qVecAmp[kTPCPos], trkTPCPosLabel); + eseQVectorTPCNeg(isCalibrated, qVecReTPCNegEse.at(0), qVecImTPCNegEse.at(0), qVecAmp[kTPCNeg], trkTPCNegLabel); + eseQVectorTPCAll(isCalibrated, qVecReTPCAllEse.at(0), qVecImTPCAllEse.at(0), qVecAmp[kTPCAll], trkTPCAllLabel); + eseQVectorFT0CVec(isCalibrated, qVecReFT0CEse, qVecImFT0CEse, qVecAmp[kFT0C]); + eseQVectorFT0AVec(isCalibrated, qVecReFT0AEse, qVecImFT0AEse, qVecAmp[kFT0A]); + eseQVectorFT0MVec(isCalibrated, qVecReFT0MEse, qVecImFT0MEse, qVecAmp[kFT0M]); + eseQVectorFV0AVec(isCalibrated, qVecReFV0AEse, qVecImFV0AEse, qVecAmp[kFV0A]); + eseQVectorTPCPosVec(isCalibrated, qVecReTPCPosEse, qVecImTPCPosEse, qVecAmp[kTPCPos], trkTPCPosLabel); + eseQVectorTPCNegVec(isCalibrated, qVecReTPCNegEse, qVecImTPCNegEse, qVecAmp[kTPCNeg], trkTPCNegLabel); + eseQVectorTPCAllVec(isCalibrated, qVecReTPCAllEse, qVecImTPCAllEse, qVecAmp[kTPCAll], trkTPCAllLabel); + eseQVectorPerc(qVecReFT0CEse.at(0), qVecImFT0CEse.at(0), qVecAmp[kFT0C], + qVecReFT0AEse.at(0), qVecImFT0AEse.at(0), qVecAmp[kFT0A], + qVecReFT0MEse.at(0), qVecImFT0MEse.at(0), qVecAmp[kFT0M], + qVecReFV0AEse.at(0), qVecImFV0AEse.at(0), qVecAmp[kFV0A], + qVecReTPCPosEse.at(0), qVecImTPCPosEse.at(0), qVecAmp[kTPCPos], + qVecReTPCNegEse.at(0), qVecImTPCNegEse.at(0), qVecAmp[kTPCNeg], + qVecReTPCAllEse.at(0), qVecImTPCAllEse.at(0), qVecAmp[kTPCAll]); + } } // End process. }; diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 78462e10a73..14d9c2c190f 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -75,6 +75,7 @@ DECLARE_SOA_COLUMN(MlScore0, mlScore0, float); //! ML score of the first con DECLARE_SOA_COLUMN(MlScore1, mlScore1, float); //! ML score of the second configured index DECLARE_SOA_COLUMN(ScalarProd, scalarProd, float); //! Scalar product DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality +DECLARE_SOA_COLUMN(RedQVec, redQVec, float); //! Reduced Q-vector } // namespace full DECLARE_SOA_TABLE(HfCandMPtInfos, "AOD", "HFCANDMPTINFO", full::M, @@ -89,6 +90,7 @@ DECLARE_SOA_TABLE(HfCandFlowInfos, "AOD", "HFCANDFLOWINFO", full::MlScore1, full::ScalarProd, full::Cent); +DECLARE_SOA_TABLE(HfRedQVecEsEs, "AOD", "HFREDQVECESE", full::RedQVec); } // namespace o2::aod enum DecayChannel { DplusToPiKPi = 0, @@ -106,15 +108,18 @@ enum DecayChannel { DplusToPiKPi = 0, struct HfTaskFlowCharmHadrons { Produces rowCandMassPtMl; Produces rowCandMassPtMlSpCent; + Produces rowRedQVecEsE; Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qVecDetector{"qVecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; + Configurable qVecRedDetector{"qVecRedDetector", 6, "Detector for Q vector estimation (FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable storeEP{"storeEP", false, "Flag to store EP-related axis"}; Configurable storeMl{"storeMl", false, "Flag to store ML scores"}; + Configurable storeRedQVec{"storeRedQVec", false, "Flag to store reduced Q-vectors for ESE"}; Configurable fillMassPtMlTree{"fillMassPtMlTree", false, "Flag to fill mass, pt and ML scores tree"}; Configurable fillMassPtMlSpCentTree{"fillMassPtMlSpCentTree", false, "Flag to fill mass, pt, ML scores, SP and centrality tree"}; Configurable fillSparse{"fillSparse", true, "Flag to fill sparse"}; @@ -148,7 +153,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -198,6 +203,7 @@ struct HfTaskFlowCharmHadrons { ConfigurableAxis thnConfigAxisResoFV0aTPCtot{"thnConfigAxisResoFV0aTPCtot", {160, -8, 8}, ""}; ConfigurableAxis thnConfigAxisCandidateEta{"thnConfigAxisCandidateEta", {100, -5, 5}, ""}; ConfigurableAxis thnConfigAxisSign{"thnConfigAxisSign", {6, -3.0, 3.0}, ""}; + ConfigurableAxis thnConfigAxisRedQVec{"thnConfigAxisRedQVec", {1000, 0, 100}, ""}; HistogramRegistry registry{"registry", {}}; @@ -225,6 +231,7 @@ struct HfTaskFlowCharmHadrons { const AxisSpec thnAxisNoCollInTimeRangeNarrow{thnConfigAxisNoCollInTimeRangeNarrow, "NoCollInTimeRangeNarrow"}; const AxisSpec thnAxisNoCollInTimeRangeStandard{thnConfigAxisNoCollInTimeRangeStandard, "NoCollInTimeRangeStandard"}; const AxisSpec thnAxisNoCollInRofStandard{thnConfigAxisNoCollInRofStandard, "NoCollInRofStandard"}; + const AxisSpec thnAxisRedQVec{thnConfigAxisRedQVec, "Reduced Q-vector"}; // TODO: currently only the Q vector of FT0c FV0a and TPCtot are considered const AxisSpec thnAxisResoFT0cFV0a{thnConfigAxisResoFT0cFV0a, "Q_{FT0c} #bullet Q_{FV0a}"}; const AxisSpec thnAxisResoFT0cTPCtot{thnConfigAxisResoFT0cTPCtot, "Q_{FT0c} #bullet Q_{TPCtot}"}; @@ -252,6 +259,9 @@ struct HfTaskFlowCharmHadrons { thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); } } + if (storeRedQVec) { + axes.insert(axes.end(), {thnAxisRedQVec}); + } registry.add("hSparseFlowCharm", "THn for SP", HistType::kTHnSparseF, axes); registry.add("hCentEventWithCand", "Centrality distributions with charm candidates;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); registry.add("hCentEventWithCandInSigRegion", "Centrality distributions with charm candidates in signal range;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); @@ -288,6 +298,14 @@ struct HfTaskFlowCharmHadrons { registry.add("spReso/hSpResoFV0aTPCtot", "hSpResoFV0aTPCtot; centrality; Q_{FV0a} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoTPCposTPCneg", "hSpResoTPCposTPCneg; centrality; Q_{TPCpos} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); + if (storeRedQVec) { + registry.add("redQVecs/hSparseRedQVecs", "hSpResoRedQVec; centrality; Q_{red} #bullet Q_{TPCtot}", {HistType::kTHnSparseF, {thnAxisCent, thnAxisRedQVec, thnAxisRedQVec, thnAxisRedQVec, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecFT0C", "hRedQVecFT0C; centrality; q_{FT0c}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecTpcPos", "hRedQVecTpcPos; centrality; q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecTpcNeg", "hRedQVecTpcNeg; centrality; q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecTpcAll", "hRedQVecTpcAll; centrality; q_{TPCall}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + } + if (saveEpResoHisto) { registry.add("epReso/hEpResoFT0cFT0a", "hEpResoFT0cFT0a; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); registry.add("epReso/hEpResoFT0cFV0a", "hEpResoFT0cFV0a; centrality; #Delta#Psi_{sub}", {HistType::kTH2F, {thnAxisCent, thnAxisCosNPhi}}); @@ -430,6 +448,7 @@ struct HfTaskFlowCharmHadrons { /// \param outputMl are the ML scores /// \param occupancy is the occupancy of the collision using the track estimator /// \param hfevselflag flag of the collision associated to utilsEvSelHf.h + /// \param redQVec is the reduced Q vector for EsE void fillThn(const float mass, const float pt, const float eta, @@ -441,7 +460,8 @@ struct HfTaskFlowCharmHadrons { const float sp, const std::vector& outputMl, const float occupancy, - const o2::hf_evsel::HfCollisionRejectionMask hfevselflag) + const o2::hf_evsel::HfCollisionRejectionMask hfevselflag, + const float redQVec) { auto hSparse = registry.get(HIST("hSparseFlowCharm")); const int ndim = hSparse->GetNdimensions(); @@ -480,6 +500,9 @@ struct HfTaskFlowCharmHadrons { values.push_back(evtSelFlags[3]); values.push_back(evtSelFlags[4]); } + if (storeRedQVec) { + values.push_back(redQVec); + } if (static_cast(values.size()) != ndim) { LOGF(fatal, @@ -487,7 +510,6 @@ struct HfTaskFlowCharmHadrons { "does not match THnSparse dimensionality (%d).", static_cast(values.size()), ndim); } - hSparse->Fill(values.data()); } @@ -501,13 +523,16 @@ struct HfTaskFlowCharmHadrons { aod::BCsWithTimestamps const&, float& centrality) { - const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + float occupancy{-999.f}; + if (occEstimator != 0) { + occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + } const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); centrality = o2::hf_centrality::getCentralityColl(collision, CentEstimator); /// monitor the satisfied event selections hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); - registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); return rejectionMask == 0; } @@ -543,6 +568,16 @@ struct HfTaskFlowCharmHadrons { float yQVec = qVecs[1]; float const amplQVec = qVecs[2]; float const evtPl = epHelper.GetEventPlane(xQVec, yQVec, harmonic); + + float redQVec{-999.f}; + std::array qVecRedComps{-999.f, -999.f, -999.f}; + if (storeRedQVec) { + qVecRedComps = getEseQvec(collision, qVecRedDetector.value); + } + float xRedQVec = qVecRedComps[0]; + float yRedQVec = qVecRedComps[1]; + float const amplRedQVec = qVecRedComps[2]; + for (const auto& candidate : candidates) { float massCand = 0.; float signCand = 0.; @@ -681,10 +716,16 @@ struct HfTaskFlowCharmHadrons { etaCand = candidate.eta(); } + float const cosNPhi = std::cos(harmonic * phiCand); + float const sinNPhi = std::sin(harmonic * phiCand); + float const cosDeltaPhi = std::cos(harmonic * (phiCand - evtPl)); + // If TPC is used for the SP estimation, the tracks of the hadron candidate must be removed from the corresponding TPC Q vector to avoid self-correlations - if (qVecDetector == QvecEstimator::TPCNeg || - qVecDetector == QvecEstimator::TPCPos || - qVecDetector == QvecEstimator::TPCTot) { + bool subtractDaugsFromQVec = (qVecDetector == QvecEstimator::TPCNeg || + qVecDetector == QvecEstimator::TPCPos || + qVecDetector == QvecEstimator::TPCTot); + float scalprodCand{-999.f}; + if (subtractDaugsFromQVec) { std::vector tracksQx; std::vector tracksQy; @@ -697,17 +738,13 @@ struct HfTaskFlowCharmHadrons { } // subtract daughters' contribution from the (normalized) Q-vector - for (std::size_t iTrack = 0; iTrack < tracksQx.size(); ++iTrack) { - xQVec -= tracksQx[iTrack]; - yQVec -= tracksQy[iTrack]; - } + float xQVecDaugSubtr = xQVec - std::accumulate(tracksQx.begin(), tracksQx.end(), 0.0); + float yQVecDaugSubtr = yQVec - std::accumulate(tracksQy.begin(), tracksQy.end(), 0.0); + scalprodCand = cosNPhi * xQVecDaugSubtr + sinNPhi * yQVecDaugSubtr; + } else { + scalprodCand = cosNPhi * xQVec + sinNPhi * yQVec; } - float const cosNPhi = std::cos(harmonic * phiCand); - float const sinNPhi = std::sin(harmonic * phiCand); - float const scalprodCand = cosNPhi * xQVec + sinNPhi * yQVec; - float const cosDeltaPhi = std::cos(harmonic * (phiCand - evtPl)); - if (fillMassPtMlTree || fillMassPtMlSpCentTree) { if (downSampleFactor < 1.) { float const pseudoRndm = ptCand * 1000. - static_cast(ptCand * 1000); @@ -722,8 +759,37 @@ struct HfTaskFlowCharmHadrons { rowCandMassPtMlSpCent(massCand, ptCand, outputMl[0], outputMl[1], scalprodCand, cent); } } + + bool subtractDaugsFromRedQVec = storeRedQVec && (qVecRedDetector == QvecEstimator::TPCNeg || + qVecRedDetector == QvecEstimator::TPCPos || + qVecRedDetector == QvecEstimator::TPCTot); + if (subtractDaugsFromRedQVec) { + std::vector tracksRedQx; + std::vector tracksRedQy; + + // IMPORTANT: use the amplitude of the reduced Q-vector to build this Q-vector + if constexpr (std::is_same_v || std::is_same_v) { + getQvecXic0Tracks(candidate, tracksRedQx, tracksRedQy, std::sqrt(amplRedQVec), static_cast(qVecRedDetector.value)); + } else { + getQvecDtracks(candidate, tracksRedQx, tracksRedQy, std::sqrt(amplRedQVec), static_cast(qVecRedDetector.value)); + } + + // subtract daughters' contribution from the (normalized) Q-vector + const float redQVecXDaugSubtr = xRedQVec - std::accumulate(tracksRedQx.begin(), tracksRedQx.end(), 0.0); + const float redQVecYDaugSubtr = yRedQVec - std::accumulate(tracksRedQy.begin(), tracksRedQy.end(), 0.0); + if (qVecRedDetector.value == QvecEstimator::TPCTot || qVecRedDetector.value == QvecEstimator::TPCPos || qVecRedDetector.value == QvecEstimator::TPCNeg) { + // Correct for track multiplicity + redQVec = std::hypot(redQVecXDaugSubtr, redQVecYDaugSubtr) * std::sqrt(amplRedQVec) / std::sqrt(amplRedQVec - tracksRedQx.size()); + } else { + redQVec = std::hypot(xRedQVec, yRedQVec); + } + } + if (storeRedQVec) { + rowRedQVecEsE(redQVec); + } if (fillSparse) { - fillThn(massCand, ptCand, etaCand, signCand, cent, cosNPhi, sinNPhi, cosDeltaPhi, scalprodCand, outputMl, occupancy, hfevflag); + fillThn(massCand, ptCand, etaCand, signCand, cent, cosNPhi, sinNPhi, + cosDeltaPhi, scalprodCand, outputMl, occupancy, hfevflag, redQVec); } } if (hasCandInMassWin) { @@ -878,22 +944,25 @@ struct HfTaskFlowCharmHadrons { float const yQVecFT0m = collision.qvecFT0MIm(); float const xQVecFV0a = collision.qvecFV0ARe(); float const yQVecFV0a = collision.qvecFV0AIm(); - float const xQVecBPos = collision.qvecBPosRe(); - float const yQVecBPos = collision.qvecBPosIm(); - float const xQVecBNeg = collision.qvecBNegRe(); - float const yQVecBNeg = collision.qvecBNegIm(); - float const xQVecBTot = collision.qvecBTotRe(); - float const yQVecBTot = collision.qvecBTotIm(); + float const xQVecTPCPos = collision.qvecTPCposRe(); + float const yQVecTPCPos = collision.qvecTPCposIm(); + float const xQVecTPCNeg = collision.qvecTPCnegRe(); + float const yQVecTPCNeg = collision.qvecTPCnegIm(); + float const xQVecTPCAll = collision.qvecTPCallRe(); + float const yQVecTPCAll = collision.qvecTPCallIm(); centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (storeResoOccu) { - const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); - registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + float occupancy{-999.f}; + if (occEstimator != 0) { + occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); + registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + } const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); std::vector evtSelFlags = getEventSelectionFlags(rejectionMask); registry.fill(HIST("spReso/hSparseReso"), centrality, xQVecFT0c * xQVecFV0a + yQVecFT0c * yQVecFV0a, - xQVecFT0c * xQVecBTot + yQVecFT0c * yQVecBTot, - xQVecFV0a * xQVecBTot + yQVecFV0a * yQVecBTot, + xQVecFT0c * xQVecTPCAll + yQVecFT0c * yQVecTPCAll, + xQVecFV0a * xQVecTPCAll + yQVecFV0a * yQVecTPCAll, occupancy, evtSelFlags[0], evtSelFlags[1], evtSelFlags[2], evtSelFlags[3], evtSelFlags[4]); } @@ -901,6 +970,13 @@ struct HfTaskFlowCharmHadrons { registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(0)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(1)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(2)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(3))); } + if (storeRedQVec) { + registry.fill(HIST("redQVecs/hSparseRedQVecs"), centrality, + std::hypot(collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm()), + std::hypot(collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm()), + std::hypot(collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm()), + std::hypot(collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm())); + } if (!isCollSelected(collision, bcs, centrality)) { // no selection on the centrality is applied, but on event selection flags @@ -909,30 +985,35 @@ struct HfTaskFlowCharmHadrons { registry.fill(HIST("spReso/hSpResoFT0cFT0a"), centrality, xQVecFT0c * xQVecFT0a + yQVecFT0c * yQVecFT0a); registry.fill(HIST("spReso/hSpResoFT0cFV0a"), centrality, xQVecFT0c * xQVecFV0a + yQVecFT0c * yQVecFV0a); - registry.fill(HIST("spReso/hSpResoFT0cTPCpos"), centrality, xQVecFT0c * xQVecBPos + yQVecFT0c * yQVecBPos); - registry.fill(HIST("spReso/hSpResoFT0cTPCneg"), centrality, xQVecFT0c * xQVecBNeg + yQVecFT0c * yQVecBNeg); - registry.fill(HIST("spReso/hSpResoFT0cTPCtot"), centrality, xQVecFT0c * xQVecBTot + yQVecFT0c * yQVecBTot); + registry.fill(HIST("spReso/hSpResoFT0cTPCpos"), centrality, xQVecFT0c * xQVecTPCPos + yQVecFT0c * yQVecTPCPos); + registry.fill(HIST("spReso/hSpResoFT0cTPCneg"), centrality, xQVecFT0c * xQVecTPCNeg + yQVecFT0c * yQVecTPCNeg); + registry.fill(HIST("spReso/hSpResoFT0cTPCtot"), centrality, xQVecFT0c * xQVecTPCAll + yQVecFT0c * yQVecTPCAll); registry.fill(HIST("spReso/hSpResoFT0aFV0a"), centrality, xQVecFT0a * xQVecFV0a + yQVecFT0a * yQVecFV0a); - registry.fill(HIST("spReso/hSpResoFT0aTPCpos"), centrality, xQVecFT0a * xQVecBPos + yQVecFT0a * yQVecBPos); - registry.fill(HIST("spReso/hSpResoFT0aTPCneg"), centrality, xQVecFT0a * xQVecBNeg + yQVecFT0a * yQVecBNeg); - registry.fill(HIST("spReso/hSpResoFT0aTPCtot"), centrality, xQVecFT0a * xQVecBTot + yQVecFT0a * yQVecBTot); + registry.fill(HIST("spReso/hSpResoFT0aTPCpos"), centrality, xQVecFT0a * xQVecTPCPos + yQVecFT0a * yQVecTPCPos); + registry.fill(HIST("spReso/hSpResoFT0aTPCneg"), centrality, xQVecFT0a * xQVecTPCNeg + yQVecFT0a * yQVecTPCNeg); + registry.fill(HIST("spReso/hSpResoFT0aTPCtot"), centrality, xQVecFT0a * xQVecTPCAll + yQVecFT0a * yQVecTPCAll); registry.fill(HIST("spReso/hSpResoFT0mFV0a"), centrality, xQVecFT0m * xQVecFV0a + yQVecFT0m * yQVecFV0a); - registry.fill(HIST("spReso/hSpResoFT0mTPCpos"), centrality, xQVecFT0m * xQVecBPos + yQVecFT0m * yQVecBPos); - registry.fill(HIST("spReso/hSpResoFT0mTPCneg"), centrality, xQVecFT0m * xQVecBNeg + yQVecFT0m * yQVecBNeg); - registry.fill(HIST("spReso/hSpResoFT0mTPCtot"), centrality, xQVecFT0m * xQVecBTot + yQVecFT0m * yQVecBTot); - registry.fill(HIST("spReso/hSpResoFV0aTPCpos"), centrality, xQVecFV0a * xQVecBPos + yQVecFV0a * yQVecBPos); - registry.fill(HIST("spReso/hSpResoFV0aTPCneg"), centrality, xQVecFV0a * xQVecBNeg + yQVecFV0a * yQVecBNeg); - registry.fill(HIST("spReso/hSpResoFV0aTPCtot"), centrality, xQVecFV0a * xQVecBTot + yQVecFV0a * yQVecBTot); - registry.fill(HIST("spReso/hSpResoTPCposTPCneg"), centrality, xQVecBPos * xQVecBNeg + yQVecBPos * yQVecBNeg); + registry.fill(HIST("spReso/hSpResoFT0mTPCpos"), centrality, xQVecFT0m * xQVecTPCPos + yQVecFT0m * yQVecTPCPos); + registry.fill(HIST("spReso/hSpResoFT0mTPCneg"), centrality, xQVecFT0m * xQVecTPCNeg + yQVecFT0m * yQVecTPCNeg); + registry.fill(HIST("spReso/hSpResoFT0mTPCtot"), centrality, xQVecFT0m * xQVecTPCAll + yQVecFT0m * yQVecTPCAll); + registry.fill(HIST("spReso/hSpResoFV0aTPCpos"), centrality, xQVecFV0a * xQVecTPCPos + yQVecFV0a * yQVecTPCPos); + registry.fill(HIST("spReso/hSpResoFV0aTPCneg"), centrality, xQVecFV0a * xQVecTPCNeg + yQVecFV0a * yQVecTPCNeg); + registry.fill(HIST("spReso/hSpResoFV0aTPCtot"), centrality, xQVecFV0a * xQVecTPCAll + yQVecFV0a * yQVecTPCAll); + registry.fill(HIST("spReso/hSpResoTPCposTPCneg"), centrality, xQVecTPCPos * xQVecTPCNeg + yQVecTPCPos * yQVecTPCNeg); + + registry.fill(HIST("redQVecs/hRedQVecFT0C"), centrality, std::hypot(collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcPos"), centrality, std::hypot(collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcNeg"), centrality, std::hypot(collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcAll"), centrality, std::hypot(collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm())); if (saveEpResoHisto) { float const epFT0a = epHelper.GetEventPlane(xQVecFT0a, yQVecFT0a, harmonic); float const epFT0c = epHelper.GetEventPlane(xQVecFT0c, yQVecFT0c, harmonic); float const epFT0m = epHelper.GetEventPlane(xQVecFT0m, yQVecFT0m, harmonic); float const epFV0a = epHelper.GetEventPlane(xQVecFV0a, yQVecFV0a, harmonic); - float const epBPoss = epHelper.GetEventPlane(xQVecBPos, yQVecBPos, harmonic); - float const epBNegs = epHelper.GetEventPlane(xQVecBNeg, yQVecBNeg, harmonic); - float const epBTots = epHelper.GetEventPlane(xQVecBTot, yQVecBTot, harmonic); + float const epBPoss = epHelper.GetEventPlane(xQVecTPCPos, yQVecTPCPos, harmonic); + float const epBNegs = epHelper.GetEventPlane(xQVecTPCNeg, yQVecTPCNeg, harmonic); + float const epBTots = epHelper.GetEventPlane(xQVecTPCAll, yQVecTPCAll, harmonic); registry.fill(HIST("epReso/hEpResoFT0cFT0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epFT0a, harmonic))); registry.fill(HIST("epReso/hEpResoFT0cFV0a"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0c, epFV0a, harmonic))); diff --git a/PWGHF/D2H/Utils/utilsFlow.h b/PWGHF/D2H/Utils/utilsFlow.h index 7efaedcdda3..911fc60dd2c 100644 --- a/PWGHF/D2H/Utils/utilsFlow.h +++ b/PWGHF/D2H/Utils/utilsFlow.h @@ -201,6 +201,56 @@ std::array getQvec(TCollision const& collision, const int qvecEst) } return std::array{-999.f, -999.f, -999.f}; } + +/// Get the Ese Q vector choosing your favourite estimator +/// \param collision is the collision with the Q vector information +/// \param qvecEst is the chosen Q-vector estimator +template +std::array getEseQvec(TCollision const& collision, const int qvecEst) +{ + switch (qvecEst) { + case QvecEstimator::FV0A: + if constexpr (HasQvecFV0A) { + return std::array{collision.eseQvecFV0ARe(), collision.eseQvecFV0AIm(), collision.sumAmplFV0A()}; + } + break; + case QvecEstimator::FT0A: + if constexpr (HasQvecFT0A) { + return std::array{collision.eseQvecFT0ARe(), collision.eseQvecFT0AIm(), collision.sumAmplFT0A()}; + } + break; + case QvecEstimator::FT0C: + if constexpr (HasQvecFT0C) { + return std::array{collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm(), collision.sumAmplFT0C()}; + } + break; + case QvecEstimator::FT0M: + if constexpr (HasQvecFT0M) { + return std::array{collision.eseQvecFT0MRe(), collision.eseQvecFT0MIm(), collision.sumAmplFT0M()}; + } + break; + case QvecEstimator::TPCPos: + if constexpr (HasQvecTPCpos) { + return std::array{collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm(), static_cast(collision.nTrkTPCpos())}; + } + break; + case QvecEstimator::TPCNeg: + if constexpr (HasQvecTPCneg) { + return std::array{collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm(), static_cast(collision.nTrkTPCneg())}; + } + break; + case QvecEstimator::TPCTot: + if constexpr (HasQvecTPCtot) { + return std::array{collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm(), static_cast(collision.nTrkTPCall())}; + } + break; + default: + LOGP(fatal, "Q-vector estimator not valid. Please choose between FV0A, FT0M, FT0A, FT0C, TPCPos, TPCNeg, TPCTot"); + break; + } + return std::array{-999.f, -999.f, -999.f}; +} + } // namespace hf_flow_utils } // namespace o2::analysis From 9c4b03b00b521bb758119ab42b7ac4b9f0037b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Wed, 6 May 2026 09:16:59 +0200 Subject: [PATCH 053/449] [ALICE3,PWGHF] Cleanup legacy ALICE3 (#16114) --- ALICE3/Core/ALICE3CoreLinkDef.h | 1 - ALICE3/Core/CMakeLists.txt | 6 +- ALICE3/Core/TOFResoALICE3.cxx | 43 -- ALICE3/Core/TOFResoALICE3.h | 79 ---- ALICE3/DataModel/ECAL.h | 55 --- ALICE3/DataModel/FTOF.h | 63 --- ALICE3/DataModel/MID.h | 45 -- ALICE3/DataModel/RICH.h | 178 ------- ALICE3/Tasks/CMakeLists.txt | 15 - ALICE3/Tasks/ECALqa.cxx | 113 ----- ALICE3/Tasks/pidFTOFqa.cxx | 156 ------- ALICE3/Tasks/pidRICHqa.cxx | 433 ------------------ .../DataModel/CandidateReconstructionTables.h | 120 ++--- 13 files changed, 62 insertions(+), 1245 deletions(-) delete mode 100644 ALICE3/Core/TOFResoALICE3.cxx delete mode 100644 ALICE3/Core/TOFResoALICE3.h delete mode 100644 ALICE3/DataModel/ECAL.h delete mode 100644 ALICE3/DataModel/FTOF.h delete mode 100644 ALICE3/DataModel/MID.h delete mode 100644 ALICE3/DataModel/RICH.h delete mode 100644 ALICE3/Tasks/ECALqa.cxx delete mode 100644 ALICE3/Tasks/pidFTOFqa.cxx delete mode 100644 ALICE3/Tasks/pidRICHqa.cxx diff --git a/ALICE3/Core/ALICE3CoreLinkDef.h b/ALICE3/Core/ALICE3CoreLinkDef.h index 076c21f8a79..bdd3c955d51 100644 --- a/ALICE3/Core/ALICE3CoreLinkDef.h +++ b/ALICE3/Core/ALICE3CoreLinkDef.h @@ -13,6 +13,5 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::pid::tof::TOFResoALICE3 + ; #pragma link C++ class std::vector < std::vector < unsigned int>> + ; #pragma link C++ class std::vector < std::vector < std::uint32_t>> + ; diff --git a/ALICE3/Core/CMakeLists.txt b/ALICE3/Core/CMakeLists.txt index 159ee735f92..11d4ecdf299 100644 --- a/ALICE3/Core/CMakeLists.txt +++ b/ALICE3/Core/CMakeLists.txt @@ -10,8 +10,7 @@ # or submit itself to any jurisdiction. o2physics_add_library(ALICE3Core - SOURCES TOFResoALICE3.cxx - TrackUtilities.cxx + SOURCES TrackUtilities.cxx FlatLutEntry.cxx FlatTrackSmearer.cxx GeometryContainer.cxx @@ -19,8 +18,7 @@ o2physics_add_library(ALICE3Core O2Physics::AnalysisCore) o2physics_target_root_dictionary(ALICE3Core - HEADERS TOFResoALICE3.h - TrackUtilities.h + HEADERS TrackUtilities.h FlatLutEntry.h GeometryContainer.h LINKDEF ALICE3CoreLinkDef.h) diff --git a/ALICE3/Core/TOFResoALICE3.cxx b/ALICE3/Core/TOFResoALICE3.cxx deleted file mode 100644 index 6d3bdd40383..00000000000 --- a/ALICE3/Core/TOFResoALICE3.cxx +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file TOFResoALICE3.h -/// \author Nicolo' Jacazio -/// \since 11/03/2021 -/// \brief Implementation for the TOF PID response of the expected times resolution -/// - -#include "ALICE3/Core/TOFResoALICE3.h" - -#include - -#include - -namespace o2::pid::tof -{ - -float TOFResoALICE3Param(const float& momentum, const float& momentumError, const float& evtimereso, const float& length, const float& mass, const Parameters& parameters) -{ - if (momentum <= 0) { - return -999.f; - } - - const float p2 = momentum * momentum; - const float Lc = length / 0.0299792458f; - const float mass2 = mass * mass; - const float ep = momentumError * momentum; - // const float ep = momentumError * p2; - const float etexp = Lc * mass2 / p2 / sqrt(mass2 + p2) * ep; - return sqrt(etexp * etexp + parameters[0] * parameters[0] + evtimereso * evtimereso); -} - -} // namespace o2::pid::tof diff --git a/ALICE3/Core/TOFResoALICE3.h b/ALICE3/Core/TOFResoALICE3.h deleted file mode 100644 index e392d120ecf..00000000000 --- a/ALICE3/Core/TOFResoALICE3.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file TOFResoALICE3.h -/// \author Nicolo' Jacazio -/// \since 11/03/2021 -/// \brief Implementation for the TOF PID response of the expected times resolution -/// - -#ifndef ALICE3_CORE_TOFRESOALICE3_H_ -#define ALICE3_CORE_TOFRESOALICE3_H_ - -#include -#include - -#include - -#include -#include - -#include - -namespace o2::pid::tof -{ - -class TOFResoALICE3 : public Parametrization -{ - public: - TOFResoALICE3() : Parametrization("TOFResoALICE3", 1){}; - ~TOFResoALICE3() override = default; - float operator()(const float* x) const override - { - const float p = abs(x[0]); - if (p <= 0) { - return -999; - } - - /** get info **/ - // const float time = x[1]; - const float evtimereso = x[2]; - const float mass = x[3]; - const float L = x[4]; - const float p2 = p * p; - // const float ep = x[5] * x[6]; - const float ep = x[5] * p2; - const float Lc = L / 0.0299792458f; - // const float Lc = L / 29.9792458f; - - const float mass2 = mass * mass; - const float etexp = Lc * mass2 / p2 / sqrt(mass2 + p2) * ep; - return sqrt(etexp * etexp + mParameters[0] * mParameters[0] + evtimereso * evtimereso); - } - ClassDef(TOFResoALICE3, 1); -}; - -float TOFResoALICE3Param(const float& momentum, const float& momentumError, const float& evtimereso, const float& length, const float& mass, const Parameters& parameters); - -template -float TOFResoALICE3ParamTrack(const T& track, const Parameters& parameters) -{ - const float BETA = tan(0.25f * static_cast(M_PI) - 0.5f * atan(track.tgl())); - const float sigmaP = sqrt(track.pt() * track.pt() * track.sigma1Pt() * track.sigma1Pt() + (BETA * BETA - 1.f) / (BETA * (BETA * BETA + 1.f)) * (track.tgl() / sqrt(track.tgl() * track.tgl() + 1.f) - 1.f) * track.sigmaTgl() * track.sigmaTgl()); - // const float sigmaP = std::sqrt( track.getSigma1Pt2() ) * track.pt(); - return TOFResoALICE3Param(track.p(), sigmaP, track.collision().collisionTimeRes() * 1000.f, track.length(), o2::track::pid_constants::sMasses2Z[id], parameters); - // return TOFResoALICE3Param(track.p(), track.sigma1Pt(), collision.collisionTimeRes() * 1000.f, track.length(), o2::track::pid_constants::sMasses[id], parameters); -} - -} // namespace o2::pid::tof - -#endif // ALICE3_CORE_TOFRESOALICE3_H_ diff --git a/ALICE3/DataModel/ECAL.h b/ALICE3/DataModel/ECAL.h deleted file mode 100644 index 9ef1e8a3391..00000000000 --- a/ALICE3/DataModel/ECAL.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file ECAL.h -/// \author Nicolo' Jacazio -/// \since 14/09/2021 -/// \brief Set of tables for the ALICE3 ECAL information -/// - -#ifndef ALICE3_DATAMODEL_ECAL_H_ -#define ALICE3_DATAMODEL_ECAL_H_ - -#include - -namespace o2::aod -{ -namespace alice3ecal -{ -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Index to travel from ECAL to collision -DECLARE_SOA_INDEX_COLUMN(Track, track); //! Index to travel from ECAL to track -DECLARE_SOA_INDEX_COLUMN(McParticle, mcparticle); //! Index to travel from ECAL to particle -DECLARE_SOA_COLUMN(E, e, double); //! Signal in ECAL -DECLARE_SOA_COLUMN(Px, px, double); //! Px -DECLARE_SOA_COLUMN(Py, py, double); //! Py -DECLARE_SOA_COLUMN(Pz, pz, double); //! Pz -DECLARE_SOA_COLUMN(PosZ, posZ, float); //! Position in Z -DECLARE_SOA_COLUMN(PosPhi, posPhi, float); //! Position in phi -} // namespace alice3ecal - -DECLARE_SOA_TABLE(ECALs, "AOD", "A3ECAL", //! Table for the ALICE3 ECAL detector - o2::soa::Index<>, - alice3ecal::CollisionId, - alice3ecal::TrackId, - alice3ecal::McParticleId, - alice3ecal::E, - alice3ecal::Px, - alice3ecal::Py, - alice3ecal::Pz, - alice3ecal::PosPhi, - alice3ecal::PosZ); - -using ECAL = ECALs::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_ECAL_H_ diff --git a/ALICE3/DataModel/FTOF.h b/ALICE3/DataModel/FTOF.h deleted file mode 100644 index 3d047c21fd5..00000000000 --- a/ALICE3/DataModel/FTOF.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file FTOF.h -/// \author Nicolo' Jacazio -/// \since 27/05/2021 -/// \brief Set of tables for the ALICE3 FTOF information -/// - -#ifndef ALICE3_DATAMODEL_FTOF_H_ -#define ALICE3_DATAMODEL_FTOF_H_ - -#include - -namespace o2::aod -{ -namespace alice3ftof -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); //! -DECLARE_SOA_COLUMN(FTOFLength, ftofLength, float); //! -DECLARE_SOA_COLUMN(FTOFSignal, ftofSignal, float); //! -DECLARE_SOA_COLUMN(FTOFDeltaEl, ftofDeltaEl, float); //! -DECLARE_SOA_COLUMN(FTOFDeltaMu, ftofDeltaMu, float); //! -DECLARE_SOA_COLUMN(FTOFDeltaPi, ftofDeltaPi, float); //! -DECLARE_SOA_COLUMN(FTOFDeltaKa, ftofDeltaKa, float); //! -DECLARE_SOA_COLUMN(FTOFDeltaPr, ftofDeltaPr, float); //! -DECLARE_SOA_COLUMN(FTOFNsigmaEl, ftofNsigmaEl, float); //! -DECLARE_SOA_COLUMN(FTOFNsigmaMu, ftofNsigmaMu, float); //! -DECLARE_SOA_COLUMN(FTOFNsigmaPi, ftofNsigmaPi, float); //! -DECLARE_SOA_COLUMN(FTOFNsigmaKa, ftofNsigmaKa, float); //! -DECLARE_SOA_COLUMN(FTOFNsigmaPr, ftofNsigmaPr, float); //! -} // namespace alice3ftof - -DECLARE_SOA_TABLE(FTOFs, "AOD", "FTOF", //! - o2::soa::Index<>, - alice3ftof::TrackId, - alice3ftof::FTOFLength, - alice3ftof::FTOFSignal, - alice3ftof::FTOFDeltaEl, - alice3ftof::FTOFDeltaMu, - alice3ftof::FTOFDeltaPi, - alice3ftof::FTOFDeltaKa, - alice3ftof::FTOFDeltaPr, - alice3ftof::FTOFNsigmaEl, - alice3ftof::FTOFNsigmaMu, - alice3ftof::FTOFNsigmaPi, - alice3ftof::FTOFNsigmaKa, - alice3ftof::FTOFNsigmaPr); - -using FTOF = FTOFs::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_FTOF_H_ diff --git a/ALICE3/DataModel/MID.h b/ALICE3/DataModel/MID.h deleted file mode 100644 index 7357e689eda..00000000000 --- a/ALICE3/DataModel/MID.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file MID.h -/// \author Vít Kučera -/// \note Based on RICH.h -/// \brief Set of tables for the ALICE3 MID information -/// - -#ifndef ALICE3_DATAMODEL_MID_H_ -#define ALICE3_DATAMODEL_MID_H_ - -#include - -#include - -namespace o2::aod -{ -namespace alice3mid -{ -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! -DECLARE_SOA_INDEX_COLUMN(Track, track); //! -DECLARE_SOA_COLUMN(MIDIsMuon, midIsMuon, uint8_t); //! FIXME: To be changed to bool once bool columns are groupable. -} // namespace alice3mid - -DECLARE_SOA_TABLE(MIDs, "AOD", "MID", //! - o2::soa::Index<>, - alice3mid::CollisionId, - alice3mid::TrackId, - alice3mid::MIDIsMuon); - -using MID = MIDs::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_MID_H_ diff --git a/ALICE3/DataModel/RICH.h b/ALICE3/DataModel/RICH.h deleted file mode 100644 index a1fc7c7c692..00000000000 --- a/ALICE3/DataModel/RICH.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file RICH.h -/// \author Nicolo' Jacazio -/// \since 25/02/2021 -/// \brief Set of tables for the ALICE3 RICH information -/// - -#ifndef ALICE3_DATAMODEL_RICH_H_ -#define ALICE3_DATAMODEL_RICH_H_ - -#include -#include - -namespace o2::aod -{ -namespace alice3rich -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); //! Index to travel from track to RICH -DECLARE_SOA_COLUMN(RICHSignal, richSignal, float); //! Signal in RICH -DECLARE_SOA_COLUMN(RICHSignalError, richSignalError, float); //! Error on the RICH signal -DECLARE_SOA_COLUMN(RICHDeltaEl, richDeltaEl, float); //! signal - exp. signal for electrons -DECLARE_SOA_COLUMN(RICHDeltaMu, richDeltaMu, float); //! signal - exp. signal for muons -DECLARE_SOA_COLUMN(RICHDeltaPi, richDeltaPi, float); //! signal - exp. signal for pions -DECLARE_SOA_COLUMN(RICHDeltaKa, richDeltaKa, float); //! signal - exp. signal for kaons -DECLARE_SOA_COLUMN(RICHDeltaPr, richDeltaPr, float); //! signal - exp. signal for protons -DECLARE_SOA_COLUMN(RICHNsigmaEl, richNsigmaEl, float); //! nsigma separation for electrons -DECLARE_SOA_COLUMN(RICHNsigmaMu, richNsigmaMu, float); //! nsigma separation for muons -DECLARE_SOA_COLUMN(RICHNsigmaPi, richNsigmaPi, float); //! nsigma separation for pions -DECLARE_SOA_COLUMN(RICHNsigmaKa, richNsigmaKa, float); //! nsigma separation for kaons -DECLARE_SOA_COLUMN(RICHNsigmaPr, richNsigmaPr, float); //! nsigma separation for protons -DECLARE_SOA_DYNAMIC_COLUMN(RICHDelta, richDelta, //! Delta separation with the RICH detector for the combined species - [](const float& El, const float& Mu, const float& Pi, - const float& Ka, const float& Pr, const o2::track::PID::ID& index) -> float { - switch (index) { - case o2::track::PID::Electron: - return El; - case o2::track::PID::Muon: - return Mu; - case o2::track::PID::Pion: - return Pi; - case o2::track::PID::Kaon: - return Ka; - case o2::track::PID::Proton: - return Pr; - default: - return -999.f; - } - }); -DECLARE_SOA_DYNAMIC_COLUMN(RICHNsigma, richNsigma, //! Nsigma separation with the RICH detector for the combined species - [](const float& El, const float& Mu, const float& Pi, - const float& Ka, const float& Pr, const o2::track::PID::ID& index) -> float { - switch (index) { - case o2::track::PID::Electron: - return El; - case o2::track::PID::Muon: - return Mu; - case o2::track::PID::Pion: - return Pi; - case o2::track::PID::Kaon: - return Ka; - case o2::track::PID::Proton: - return Pr; - default: - return -999.f; - } - }); -} // namespace alice3rich - -namespace alice3frich -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); //! Index to travel from track to FRICH -DECLARE_SOA_COLUMN(FRICHSignal, frichSignal, float); //! Signal in RICH -DECLARE_SOA_COLUMN(FRICHSignalError, frichSignalError, float); //! Error on the RICH signal -DECLARE_SOA_COLUMN(FRICHDeltaEl, frichDeltaEl, float); //! signal - exp. signal for electrons -DECLARE_SOA_COLUMN(FRICHDeltaMu, frichDeltaMu, float); //! signal - exp. signal for muons -DECLARE_SOA_COLUMN(FRICHDeltaPi, frichDeltaPi, float); //! signal - exp. signal for pions -DECLARE_SOA_COLUMN(FRICHDeltaKa, frichDeltaKa, float); //! signal - exp. signal for kaons -DECLARE_SOA_COLUMN(FRICHDeltaPr, frichDeltaPr, float); //! signal - exp. signal for protons -DECLARE_SOA_COLUMN(FRICHNsigmaEl, frichNsigmaEl, float); //! nsigma separation for electrons -DECLARE_SOA_COLUMN(FRICHNsigmaMu, frichNsigmaMu, float); //! nsigma separation for muons -DECLARE_SOA_COLUMN(FRICHNsigmaPi, frichNsigmaPi, float); //! nsigma separation for pions -DECLARE_SOA_COLUMN(FRICHNsigmaKa, frichNsigmaKa, float); //! nsigma separation for kaons -DECLARE_SOA_COLUMN(FRICHNsigmaPr, frichNsigmaPr, float); //! nsigma separation for protons -DECLARE_SOA_DYNAMIC_COLUMN(FRICHDelta, frichDelta, //! Delta separation with the FRICH detector for the combined species - [](const float& El, const float& Mu, const float& Pi, - const float& Ka, const float& Pr, const o2::track::PID::ID& index) -> float { - switch (index) { - case o2::track::PID::Electron: - return El; - case o2::track::PID::Muon: - return Mu; - case o2::track::PID::Pion: - return Pi; - case o2::track::PID::Kaon: - return Ka; - case o2::track::PID::Proton: - return Pr; - default: - return -999.f; - } - }); -DECLARE_SOA_DYNAMIC_COLUMN(FRICHNsigma, frichNsigma, //! Nsigma separation with the FRICH detector for the combined species - [](const float& El, const float& Mu, const float& Pi, - const float& Ka, const float& Pr, const o2::track::PID::ID& index) -> float { - switch (index) { - case o2::track::PID::Electron: - return El; - case o2::track::PID::Muon: - return Mu; - case o2::track::PID::Pion: - return Pi; - case o2::track::PID::Kaon: - return Ka; - case o2::track::PID::Proton: - return Pr; - default: - return -999.f; - } - }); -} // namespace alice3frich - -DECLARE_SOA_TABLE(RICHs, "AOD", "RICH", //! Table for the ALICE3 RICH detector - o2::soa::Index<>, - alice3rich::TrackId, - alice3rich::RICHSignal, - alice3rich::RICHSignalError, - alice3rich::RICHDeltaEl, - alice3rich::RICHDeltaMu, - alice3rich::RICHDeltaPi, - alice3rich::RICHDeltaKa, - alice3rich::RICHDeltaPr, - alice3rich::RICHNsigmaEl, - alice3rich::RICHNsigmaMu, - alice3rich::RICHNsigmaPi, - alice3rich::RICHNsigmaKa, - alice3rich::RICHNsigmaPr, - alice3rich::RICHDelta, - alice3rich::RICHNsigma); -using RICH = RICHs::iterator; - -DECLARE_SOA_TABLE(FRICHs, "AOD", "FRICH", //! Table for the ALICE3 Forward RICH detector - o2::soa::Index<>, - alice3frich::TrackId, - alice3frich::FRICHSignal, - alice3frich::FRICHSignalError, - alice3frich::FRICHDeltaEl, - alice3frich::FRICHDeltaMu, - alice3frich::FRICHDeltaPi, - alice3frich::FRICHDeltaKa, - alice3frich::FRICHDeltaPr, - alice3frich::FRICHNsigmaEl, - alice3frich::FRICHNsigmaMu, - alice3frich::FRICHNsigmaPi, - alice3frich::FRICHNsigmaKa, - alice3frich::FRICHNsigmaPr, - alice3frich::FRICHDelta, - alice3frich::FRICHNsigma); - -using FRICH = FRICHs::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_RICH_H_ diff --git a/ALICE3/Tasks/CMakeLists.txt b/ALICE3/Tasks/CMakeLists.txt index 822d407221f..8af7d1d1815 100644 --- a/ALICE3/Tasks/CMakeLists.txt +++ b/ALICE3/Tasks/CMakeLists.txt @@ -24,21 +24,6 @@ o2physics_add_dpl_workflow(alice3-lutmaker PUBLIC_LINK_LIBRARIES O2::Framework FairRoot::Base O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(alice3-pid-rich-qa - SOURCES pidRICHqa.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(alice3-ecal-qa - SOURCES ECALqa.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(alice3-pid-ftof-qa - SOURCES pidFTOFqa.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(alice3-pid-separation-power SOURCES alice3SeparationPower.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/ALICE3/Tasks/ECALqa.cxx b/ALICE3/Tasks/ECALqa.cxx deleted file mode 100644 index 73a73ca32a3..00000000000 --- a/ALICE3/Tasks/ECALqa.cxx +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file ECALqa.cxx -/// \author Nicolo' Jacazio -/// \since 14/09/2021 -/// \brief Task to use the ALICE3 ECAL table -/// - -#include "ALICE3/DataModel/ECAL.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -namespace o2::aod -{ - -namespace indices -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); -DECLARE_SOA_INDEX_COLUMN(ECAL, ecal); - -DECLARE_SOA_INDEX_COLUMN(McParticle, mcparticle); - -} // namespace indices - -DECLARE_SOA_INDEX_TABLE_USER(ECALTracksIndex, Tracks, "ECALTRK", indices::TrackId, indices::ECALId); -DECLARE_SOA_INDEX_TABLE_USER(ECALMcPartIndex, McParticles, "ECALPART", indices::McParticleId, indices::ECALId); -} // namespace o2::aod - -struct ecalIndexBuilder { // Builder of the ECAL-track index linkage - Builds ind; - Builds indPart; - void init(o2::framework::InitContext&) - { - } -}; - -struct ecalQaMc { - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; - - void init(o2::framework::InitContext&) - { - histos.add("energy", ";Energy (GeV/#it{c});Entries", HistType::kTH1F, {{100, 0, 100}}); - histos.add("energyVsp", ";Energy (GeV/#it{c});#it{p} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("ecalpVsp", ";#it{p}_{ECAL} (GeV/#it{c});#it{p} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("ecalpxVspx", ";#it{p}_{ECAL x} (GeV/#it{c});#it{p} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("ecalpyVspy", ";#it{p}_{ECAL y} (GeV/#it{c});#it{p} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("ecalpzVspz", ";#it{p}_{ECAL z} (GeV/#it{c});#it{p} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("energyVsecalp", ";Energy (GeV/#it{c});#it{p}_{ECAL} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("energyVsecalpx", ";Energy (GeV/#it{c});#it{p}_{ECAL x} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("energyVsecalpy", ";Energy (GeV/#it{c});#it{p}_{ECAL y} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("energyVsecalpz", ";Energy (GeV/#it{c});#it{p}_{ECAL z} (GeV/#it{c});Entries", HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}); - histos.add("PDGs", "Particle PDGs;PDG Code", kTH1D, {{100, 0.f, 100.f}}); - } - - using Trks = soa::Join; - void process(const soa::Join& mcParticles, - const Trks&, - const aod::McTrackLabels&, - const aod::ECALs&, - const aod::Collisions&) - { - for (auto& particle : mcParticles) { - if (!particle.has_ecal()) - continue; - histos.fill(HIST("energy"), particle.ecal().e()); - const float ecalp = std::sqrt(particle.ecal().px() * particle.ecal().px() + particle.ecal().py() * particle.ecal().py() + particle.ecal().pz() * particle.ecal().pz()); - histos.fill(HIST("energyVsp"), particle.ecal().e(), particle.p()); - histos.fill(HIST("ecalpVsp"), ecalp, particle.p()); - histos.fill(HIST("ecalpxVspx"), particle.ecal().px(), particle.px()); - histos.fill(HIST("ecalpyVspy"), particle.ecal().py(), particle.py()); - histos.fill(HIST("ecalpzVspz"), particle.ecal().pz(), particle.pz()); - histos.fill(HIST("energyVsecalp"), particle.ecal().e(), ecalp); - histos.fill(HIST("energyVsecalpx"), particle.ecal().e(), particle.ecal().px()); - histos.fill(HIST("energyVsecalpy"), particle.ecal().e(), particle.ecal().py()); - histos.fill(HIST("energyVsecalpz"), particle.ecal().e(), particle.ecal().pz()); - histos.get(HIST("PDGs"))->Fill(Form("%i", particle.pdgCode()), 1.f); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfg) -{ - auto workflow = WorkflowSpec{adaptAnalysisTask(cfg)}; - workflow.push_back(adaptAnalysisTask(cfg)); - return workflow; -} diff --git a/ALICE3/Tasks/pidFTOFqa.cxx b/ALICE3/Tasks/pidFTOFqa.cxx deleted file mode 100644 index ba899e4dc85..00000000000 --- a/ALICE3/Tasks/pidFTOFqa.cxx +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#include "ALICE3/DataModel/FTOF.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -namespace o2::aod -{ - -namespace indices -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); -DECLARE_SOA_INDEX_COLUMN(FTOF, ftof); -} // namespace indices - -DECLARE_SOA_INDEX_TABLE_USER(FTOFTracksIndex, Tracks, "FTOFTRK", indices::TrackId, indices::FTOFId); -} // namespace o2::aod - -struct ftofIndexBuilder { - Builds ind; - void init(o2::framework::InitContext&) - { - } -}; - -struct ftofPidQaMC { - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; - Configurable pdgCode{"pdgCode", 0, "pdg code of the particles to accept"}; - Configurable useOnlyPhysicsPrimary{"useOnlyPhysicsPrimary", 1, - "Whether to use only physical primary particles."}; - Configurable minLength{"minLength", 0, "Minimum length of accepted tracks (cm)"}; - Configurable maxLength{"maxLength", 1000, "Maximum length of accepted tracks (cm)"}; - Configurable minEta{"minEta", -1.4, "Minimum eta of accepted tracks"}; - Configurable maxEta{"maxEta", 1.4, "Maximum eta of accepted tracks"}; - Configurable nBinsP{"nBinsP", 500, "Number of momentum bins"}; - Configurable minP{"minP", 0.01, "Minimum momentum plotted (GeV/c)"}; - Configurable maxP{"maxP", 100, "Maximum momentum plotted (GeV/c)"}; - Configurable nBinsNsigma{"nBinsNsigma", 600, "Number of Nsigma bins"}; - Configurable minNsigma{"minNsigma", -100.f, "Minimum Nsigma plotted"}; - Configurable maxNsigma{"maxNsigma", 100.f, "Maximum Nsigma plotted"}; - Configurable nBinsDelta{"nBinsDelta", 100, "Number of delta bins"}; - Configurable minDelta{"minDelta", -1.f, "Minimum delta plotted"}; - Configurable maxDelta{"maxDelta", 1.f, "Maximum delta plotted"}; - Configurable logAxis{"logAxis", 1, "Flag to use a log momentum axis"}; - - void init(o2::framework::InitContext&) - { - AxisSpec momAxis{nBinsP, minP, maxP}; - if (logAxis) { - momAxis.makeLogarithmic(); - } - const AxisSpec nsigmaAxis{nBinsNsigma, minNsigma, maxNsigma}; - const AxisSpec deltaAxis{nBinsDelta, minDelta, maxDelta}; - - histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); - histos.add("event/length", ";FTOF length (cm)", kTH1F, {{100, 0, 100}}); - histos.add("event/eta", ";#it{#eta}", kTH1F, {{100, -10, 10}}); - histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {momAxis}); - histos.add("p/Prim", "Primaries;#it{p} (GeV/#it{c})", kTH1F, {momAxis}); - histos.add("p/Sec", "Secondaries;#it{p} (GeV/#it{c})", kTH1F, {momAxis}); - histos.add("pt/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {momAxis}); - histos.add("qa/length", ";FTOF length (cm)", kTH1F, {{100, 0, 100}}); - histos.add("qa/signal", ";FTOF signal (ps)", kTH1F, {{100, 0, 1000}}); - histos.add("qa/signalvsP", ";#it{p} (GeV/#it{c});FTOF signal (ps)", kTH2F, {momAxis, {1000, 0, 0.3}}); - histos.add("qa/deltaEl", ";#it{p} (GeV/#it{c});#Delta(e) (ps)", kTH2F, {momAxis, deltaAxis}); - histos.add("qa/deltaMu", ";#it{p} (GeV/#it{c});#Delta(#mu) (ps)", kTH2F, {momAxis, deltaAxis}); - histos.add("qa/deltaPi", ";#it{p} (GeV/#it{c});#Delta(#pi) (ps)", kTH2F, {momAxis, deltaAxis}); - histos.add("qa/deltaKa", ";#it{p} (GeV/#it{c});#Delta(K) (ps)", kTH2F, {momAxis, deltaAxis}); - histos.add("qa/deltaPr", ";#it{p} (GeV/#it{c});#Delta(p) (ps)", kTH2F, {momAxis, deltaAxis}); - histos.add("qa/nsigmaEl", ";#it{p} (GeV/#it{c});N_{#sigma}^{FTOF}(e)", kTH2F, {momAxis, nsigmaAxis}); - histos.add("qa/nsigmaMu", ";#it{p} (GeV/#it{c});N_{#sigma}^{FTOF}(#mu)", kTH2F, {momAxis, nsigmaAxis}); - histos.add("qa/nsigmaPi", ";#it{p} (GeV/#it{c});N_{#sigma}^{FTOF}(#pi)", kTH2F, {momAxis, nsigmaAxis}); - histos.add("qa/nsigmaKa", ";#it{p} (GeV/#it{c});N_{#sigma}^{FTOF}(K)", kTH2F, {momAxis, nsigmaAxis}); - histos.add("qa/nsigmaPr", ";#it{p} (GeV/#it{c});N_{#sigma}^{FTOF}(p)", kTH2F, {momAxis, nsigmaAxis}); - } - - using Trks = soa::Join; - void process(const Trks& tracks, - const aod::McTrackLabels& labels, - const aod::FTOFs&, - const aod::McParticles_000&, - const aod::Collisions& colls) - { - for (const auto& col : colls) { - histos.fill(HIST("event/vertexz"), col.posZ()); - } - for (const auto& track : tracks) { - histos.fill(HIST("event/length"), track.ftof().ftofLength()); - histos.fill(HIST("event/eta"), track.eta()); - if (!track.has_ftof()) { - continue; - } - if (track.ftof().ftofLength() < minLength) { - continue; - } - if (track.ftof().ftofLength() > maxLength) { - continue; - } - if (track.eta() > maxEta || track.eta() < minEta) { - continue; - } - const auto mcParticle = labels.iteratorAt(track.globalIndex()).mcParticle_as(); - if (pdgCode != 0 && abs(mcParticle.pdgCode()) != pdgCode) { - continue; - } - if (useOnlyPhysicsPrimary == 1 && !mcParticle.isPhysicalPrimary()) { // Selecting primaries - histos.fill(HIST("p/Sec"), track.p()); - continue; - } - histos.fill(HIST("p/Prim"), track.p()); - histos.fill(HIST("p/Unselected"), track.p()); - histos.fill(HIST("pt/Unselected"), track.pt()); - histos.fill(HIST("qa/length"), track.ftof().ftofLength()); - histos.fill(HIST("qa/signal"), track.ftof().ftofSignal()); - histos.fill(HIST("qa/signalvsP"), track.p(), track.ftof().ftofSignal()); - histos.fill(HIST("qa/deltaEl"), track.p(), track.ftof().ftofDeltaEl()); - histos.fill(HIST("qa/deltaMu"), track.p(), track.ftof().ftofDeltaMu()); - histos.fill(HIST("qa/deltaPi"), track.p(), track.ftof().ftofDeltaPi()); - histos.fill(HIST("qa/deltaKa"), track.p(), track.ftof().ftofDeltaKa()); - histos.fill(HIST("qa/deltaPr"), track.p(), track.ftof().ftofDeltaPr()); - histos.fill(HIST("qa/nsigmaEl"), track.p(), track.ftof().ftofNsigmaEl()); - histos.fill(HIST("qa/nsigmaMu"), track.p(), track.ftof().ftofNsigmaMu()); - histos.fill(HIST("qa/nsigmaPi"), track.p(), track.ftof().ftofNsigmaPi()); - histos.fill(HIST("qa/nsigmaKa"), track.p(), track.ftof().ftofNsigmaKa()); - histos.fill(HIST("qa/nsigmaPr"), track.p(), track.ftof().ftofNsigmaPr()); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfg) -{ - return WorkflowSpec{adaptAnalysisTask(cfg), adaptAnalysisTask(cfg)}; -} diff --git a/ALICE3/Tasks/pidRICHqa.cxx b/ALICE3/Tasks/pidRICHqa.cxx deleted file mode 100644 index 4a420ffe34f..00000000000 --- a/ALICE3/Tasks/pidRICHqa.cxx +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file qaTOFMC.cxx -/// \author Nicolò Jacazio -/// \brief Task to produce QA output of the PID with ALICE3 RICH running on the MC. -/// - -#include "ALICE3/DataModel/RICH.h" -#include "Common/DataModel/PIDResponseTOF.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -using namespace o2; -using namespace o2::track; -using namespace o2::framework; -using namespace o2::framework::expressions; - -void customize(std::vector& workflowOptions) -{ - std::vector options{ - {"qa-el", VariantType::Int, 1, {"Produce PID information for the electron mass hypothesis"}}, - {"qa-mu", VariantType::Int, 1, {"Produce PID information for the muon mass hypothesis"}}, - {"qa-pikapr", VariantType::Int, 1, {"Produce PID information for the Pion, Kaon, Proton mass hypothesis"}}}; - std::swap(workflowOptions, options); -} - -#include - -namespace o2::aod -{ - -namespace indices -{ -DECLARE_SOA_INDEX_COLUMN(Track, track); -DECLARE_SOA_INDEX_COLUMN(RICH, rich); -DECLARE_SOA_INDEX_COLUMN(FRICH, frich); -} // namespace indices - -DECLARE_SOA_INDEX_TABLE_USER(RICHTracksIndex, Tracks, "RICHTRK", indices::TrackId, indices::RICHId); -DECLARE_SOA_INDEX_TABLE_USER(FRICHTracksIndex, Tracks, "FRICHTRK", indices::TrackId, indices::FRICHId); -} // namespace o2::aod - -struct richIndexBuilder { // Builder of the RICH-track index linkage - Builds indB; - Builds indF; - void init(o2::framework::InitContext&) - { - } -}; - -template -struct richPidQaMc { - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; - Configurable pdgCode{"pdgCode", 0, "pdg code of the particles to accept"}; - Configurable useOnlyPhysicsPrimary{"useOnlyPhysicsPrimary", 1, - "Whether to use only physical primary particles."}; - Configurable useTOF{"useTOF", 0, - "Whether to use the TOF information"}; - Configurable minLength{"minLength", 0, "Minimum length of accepted tracks (cm)"}; - Configurable maxLength{"maxLength", 1000, "Maximum length of accepted tracks (cm)"}; - Configurable minEta{"minEta", -1.4, "Minimum eta of accepted tracks"}; - Configurable maxEta{"maxEta", 1.4, "Maximum eta of accepted tracks"}; - Configurable nBinsP{"nBinsP", 500, "Number of momentum bins"}; - Configurable minP{"minP", -2, "Minimum momentum plotted (GeV/c)"}; - Configurable maxP{"maxP", 2, "Maximum momentum plotted (GeV/c)"}; - Configurable nBinsNsigma{"nBinsNsigma", 600, "Number of Nsigma bins"}; - Configurable minNsigma{"minNsigma", -100.f, "Minimum Nsigma plotted"}; - Configurable maxNsigma{"maxNsigma", 100.f, "Maximum Nsigma plotted"}; - Configurable nBinsDelta{"nBinsDelta", 600, "Number of delta bins"}; - Configurable minDelta{"minDelta", -0.4f, "Minimum delta plotted (rad)"}; - Configurable maxDelta{"maxDelta", 0.4f, "Maximum delta plotted (rad)"}; - Configurable logAxis{"logAxis", 1, "Flag to use a log momentum axis"}; - Configurable nSigmaNorm{"nSigmaNorm", 0.7071067811865475f, "Normalization for the combined Nsigma"}; - - static constexpr int Np = 5; - static constexpr std::string_view hbRICHDelta[Np] = {"bRICH/delta/El", "bRICH/delta/Mu", "bRICH/delta/Pi", "bRICH/delta/Ka", "bRICH/delta/Pr"}; - static constexpr std::string_view hbRICHNSigma[Np] = {"bRICH/nsigma/El", "bRICH/nsigma/Mu", "bRICH/nsigma/Pi", "bRICH/nsigma/Ka", "bRICH/nsigma/Pr"}; - static constexpr std::string_view hbRICHNSigmaPrm[Np] = {"bRICH/nsigmaprm/El", "bRICH/nsigmaprm/Mu", "bRICH/nsigmaprm/Pi", "bRICH/nsigmaprm/Ka", "bRICH/nsigmaprm/Pr"}; - static constexpr std::string_view hbRICHNSigmaSec[Np] = {"bRICH/nsigmasec/El", "bRICH/nsigmasec/Mu", "bRICH/nsigmasec/Pi", "bRICH/nsigmasec/Ka", "bRICH/nsigmasec/Pr"}; - static constexpr std::string_view hbRICHNSigmaMC[Np] = {"bRICH/nsigmaMC/El", "bRICH/nsigmaMC/Mu", "bRICH/nsigmaMC/Pi", "bRICH/nsigmaMC/Ka", "bRICH/nsigmaMC/Pr"}; - static constexpr std::string_view hbRICHNSigmaMCSec[Np] = {"bRICH/nsigmaMCsec/El", "bRICH/nsigmaMCsec/Mu", "bRICH/nsigmaMCsec/Pi", "bRICH/nsigmaMCsec/Ka", "bRICH/nsigmaMCsec/Pr"}; - static constexpr std::string_view hbRICHNSigmaMCPrm[Np] = {"bRICH/nsigmaMCprm/El", "bRICH/nsigmaMCprm/Mu", "bRICH/nsigmaMCprm/Pi", "bRICH/nsigmaMCprm/Ka", "bRICH/nsigmaMCprm/Pr"}; - - static constexpr std::string_view hfRICHDelta[Np] = {"fRICH/delta/El", "fRICH/delta/Mu", "fRICH/delta/Pi", "fRICH/delta/Ka", "fRICH/delta/Pr"}; - static constexpr std::string_view hfRICHNSigma[Np] = {"fRICH/nsigma/El", "fRICH/nsigma/Mu", "fRICH/nsigma/Pi", "fRICH/nsigma/Ka", "fRICH/nsigma/Pr"}; - static constexpr std::string_view hfRICHNSigmaPrm[Np] = {"fRICH/nsigmaprm/El", "fRICH/nsigmaprm/Mu", "fRICH/nsigmaprm/Pi", "fRICH/nsigmaprm/Ka", "fRICH/nsigmaprm/Pr"}; - static constexpr std::string_view hfRICHNSigmaSec[Np] = {"fRICH/nsigmasec/El", "fRICH/nsigmasec/Mu", "fRICH/nsigmasec/Pi", "fRICH/nsigmasec/Ka", "fRICH/nsigmasec/Pr"}; - static constexpr std::string_view hfRICHNSigmaMC[Np] = {"fRICH/nsigmaMC/El", "fRICH/nsigmaMC/Mu", "fRICH/nsigmaMC/Pi", "fRICH/nsigmaMC/Ka", "fRICH/nsigmaMC/Pr"}; - static constexpr std::string_view hfRICHNSigmaMCSec[Np] = {"fRICH/nsigmaMCsec/El", "fRICH/nsigmaMCsec/Mu", "fRICH/nsigmaMCsec/Pi", "fRICH/nsigmaMCsec/Ka", "fRICH/nsigmaMCsec/Pr"}; - static constexpr std::string_view hfRICHNSigmaMCPrm[Np] = {"fRICH/nsigmaMCprm/El", "fRICH/nsigmaMCprm/Mu", "fRICH/nsigmaMCprm/Pi", "fRICH/nsigmaMCprm/Ka", "fRICH/nsigmaMCprm/Pr"}; - static constexpr std::string_view hfRICHNSigmaVsp[Np] = {"fRICH/nsigmavsp/El", "fRICH/nsigmavsp/Mu", "fRICH/nsigmavsp/Pi", "fRICH/nsigmavsp/Ka", "fRICH/nsigmavsp/Pr"}; - static constexpr std::string_view hfRICHNSigmaMCVsp[Np] = {"fRICH/nsigmaMCvsp/El", "fRICH/nsigmaMCvsp/Mu", "fRICH/nsigmaMCvsp/Pi", "fRICH/nsigmaMCvsp/Ka", "fRICH/nsigmaMCvsp/Pr"}; - static constexpr std::string_view hfRICHNSigmaMCSecVsp[Np] = {"fRICH/nsigmaMCsecvsp/El", "fRICH/nsigmaMCsecvsp/Mu", "fRICH/nsigmaMCsecvsp/Pi", "fRICH/nsigmaMCsecvsp/Ka", "fRICH/nsigmaMCsecvsp/Pr"}; - static constexpr std::string_view hfRICHNSigmaMCPrmVsp[Np] = {"fRICH/nsigmaMCprmvsp/El", "fRICH/nsigmaMCprmvsp/Mu", "fRICH/nsigmaMCprmvsp/Pi", "fRICH/nsigmaMCprmvsp/Ka", "fRICH/nsigmaMCprmvsp/Pr"}; - - static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p"}; - static constexpr int PDGs[Np] = {11, 13, 211, 321, 2212}; - template - void addParticleHistos() - { - AxisSpec pAxis{nBinsP, minP, maxP, "#it{p} (GeV/#it{c})"}; - AxisSpec ptAxis{nBinsP, minP, maxP, "#it{p}_{T} (GeV/#it{c})"}; - if (logAxis) { - pAxis.makeLogarithmic(); - ptAxis.makeLogarithmic(); - } - const AxisSpec nsigmaAxis{nBinsNsigma, minNsigma, maxNsigma, Form("N_{#sigma}^{RICH}(%s)", pT[pid_type])}; - - TString tit = Form("%s", pT[i]); - if (useTOF) { - tit = Form("TOF Selected %s", pT[i]); - } - // NSigma - histos.add(hbRICHNSigmaMC[i].data(), "True " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hbRICHNSigmaMCPrm[i].data(), "True Primary " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hbRICHNSigmaMCSec[i].data(), "True Secondary " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - - histos.add(hfRICHNSigmaMC[i].data(), "True " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaMCPrm[i].data(), "True Primary " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaMCSec[i].data(), "True Secondary " + tit, HistType::kTH2F, {ptAxis, nsigmaAxis}); - - histos.add(hfRICHNSigmaMCVsp[i].data(), "True " + tit, HistType::kTH2F, {pAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaMCPrmVsp[i].data(), "True Primary " + tit, HistType::kTH2F, {pAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaMCSecVsp[i].data(), "True Secondary " + tit, HistType::kTH2F, {pAxis, nsigmaAxis}); - } - - void init(o2::framework::InitContext&) - { - AxisSpec pAxis{nBinsP, minP, maxP, "#it{p} (GeV/#it{c})"}; - AxisSpec ptAxis{nBinsP, minP, maxP, "#it{p}_{T} (GeV/#it{c})"}; - if (logAxis) { - pAxis.makeLogarithmic(); - ptAxis.makeLogarithmic(); - } - - const AxisSpec sigAxis{1000, 0, 0.3, "Cherenkov angle (rad)"}; - const AxisSpec lengthAxis{1000, 0, 3000, "Track length (cm)"}; - const AxisSpec sigErrAxis{100, 0, 1, "Cherenkov angle error (rad)"}; - const char* detName = useTOF ? "TOF-RICH" : "RICH"; - const AxisSpec nsigmaAxis{nBinsNsigma, minNsigma, maxNsigma, Form("N_{#sigma}^{%s}(%s)", detName, pT[pid_type])}; - const AxisSpec deltaAxis{nBinsDelta, minDelta, maxDelta, Form("#Delta(%s) (rad)", pT[pid_type])}; - const AxisSpec etaAxis{100, -4, 4, "#it{#eta}"}; - - histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); - histos.add("particle/p", "", kTH1F, {pAxis}); - histos.add("particle/pt", "", kTH1F, {ptAxis}); - histos.add("particle/eta", "", kTH1F, {etaAxis}); - histos.add("tracks/p", "", kTH1F, {pAxis}); - histos.add("tracks/pt", "", kTH1F, {ptAxis}); - histos.add("tracks/eta", "", kTH1F, {etaAxis}); - histos.add("tracks/length", "", kTH1F, {lengthAxis}); - -#define MakeRICHHistos(rich) \ - histos.add(rich "/TrackSelection", "", kTH1F, {{10, 0.5, 10.5}}); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(1, "Tracks read"); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(2, "Passed RICH"); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(3, "Passed TOF"); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(4, Form("Passed minLength %.2f", minLength.value)); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(5, Form("Passed maxLength %.2f", maxLength.value)); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(6, Form("Passed minEta %.2f", minEta.value)); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(7, Form("Passed maxEta %.2f", maxEta.value)); \ - histos.get(HIST(rich "/TrackSelection"))->GetXaxis()->SetBinLabel(8, "Passed PDG"); \ - histos.add(rich "/pt", "Unselected", kTH1F, {ptAxis}); \ - histos.add(rich "/ptPrm", "Primaries", kTH1F, {ptAxis}); \ - histos.add(rich "/ptSec", "Secondaries", kTH1F, {ptAxis}); \ - histos.add(rich "/p", "Unselected", kTH1F, {pAxis}); \ - histos.add(rich "/pPrm", "Primaries", kTH1F, {pAxis}); \ - histos.add(rich "/pSec", "Secondaries", kTH1F, {pAxis}); \ - histos.add(rich "/signal", "", kTH1F, {sigAxis}); \ - histos.add(rich "/eta", "", kTH1F, {etaAxis}); \ - histos.add(rich "/signalerror", "", kTH1F, {sigErrAxis}); \ - histos.add(rich "/signalvsP", "Unselected", kTH2F, {pAxis, sigAxis}); \ - histos.add(rich "/signalvsPPrm", "Primaries", kTH2F, {pAxis, sigAxis}); \ - histos.add(rich "/signalvsPSec", "Secondaries", kTH2F, {pAxis, sigAxis}); - - MakeRICHHistos("bRICH"); - MakeRICHHistos("fRICH"); - -#undef MakeRICHHistos - - histos.add(hbRICHDelta[pid_type].data(), "", kTH2F, {pAxis, deltaAxis}); - histos.add(hbRICHNSigma[pid_type].data(), "", HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hbRICHNSigmaPrm[pid_type].data(), "Primary", HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hbRICHNSigmaSec[pid_type].data(), "Secondary", HistType::kTH2F, {ptAxis, nsigmaAxis}); - - histos.add(hfRICHDelta[pid_type].data(), "", kTH2F, {pAxis, deltaAxis}); - histos.add(hfRICHNSigma[pid_type].data(), "", HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaPrm[pid_type].data(), "Primary", HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaSec[pid_type].data(), "Secondary", HistType::kTH2F, {ptAxis, nsigmaAxis}); - histos.add(hfRICHNSigmaVsp[pid_type].data(), "", HistType::kTH2F, {pAxis, nsigmaAxis}); - - addParticleHistos<0>(); - addParticleHistos<1>(); - addParticleHistos<2>(); - addParticleHistos<3>(); - addParticleHistos<4>(); - } - - template - void fillNsigma(const T& track, const TT& particle, const float& nsigma) - { - if (abs(particle.pdgCode()) != PDGs[pidIndex]) { - return; - } - histos.fill(HIST(hbRICHNSigmaMC[pidIndex]), track.pt(), nsigma); - - if (particle.isPhysicalPrimary()) { // Selecting primaries - histos.fill(HIST(hbRICHNSigmaMCPrm[pidIndex]), track.pt(), nsigma); - } else { - histos.fill(HIST(hbRICHNSigmaMCSec[pidIndex]), track.pt(), nsigma); - } - } - - template - void fillNsigmafRICH(const T& track, const TT& particle, const float& nsigma) - { - if (abs(particle.pdgCode()) != PDGs[pidIndex]) { - return; - } - histos.fill(HIST(hfRICHNSigmaMC[pidIndex]), track.pt(), nsigma); - histos.fill(HIST(hfRICHNSigmaMCVsp[pidIndex]), track.p(), nsigma); - - if (particle.isPhysicalPrimary()) { // Selecting primaries - histos.fill(HIST(hfRICHNSigmaMCPrm[pidIndex]), track.pt(), nsigma); - histos.fill(HIST(hfRICHNSigmaMCPrmVsp[pidIndex]), track.p(), nsigma); - } else { - histos.fill(HIST(hfRICHNSigmaMCSec[pidIndex]), track.pt(), nsigma); - histos.fill(HIST(hfRICHNSigmaMCSecVsp[pidIndex]), track.p(), nsigma); - } - } - - using Trks = soa::Join; - using TrksfRICH = soa::Join; - void process(const Trks& tracks, - const aod::McParticles_000& mcParticles, - const TrksfRICH& tracksfrich, - const aod::RICHs&, - const aod::FRICHs&, - const aod::Collisions& colls) - { - for (const auto& col : colls) { - histos.fill(HIST("event/vertexz"), col.posZ()); - } - for (const auto& p : mcParticles) { - if (pdgCode != 0 && abs(p.pdgCode()) != pdgCode) { - continue; - } - histos.fill(HIST("particle/p"), p.p()); - histos.fill(HIST("particle/pt"), p.pt()); - histos.fill(HIST("particle/eta"), p.eta()); - } - - for (const auto& t : tracks) { - histos.fill(HIST("tracks/p"), t.p()); - histos.fill(HIST("tracks/pt"), t.pt()); - histos.fill(HIST("tracks/eta"), t.eta()); - histos.fill(HIST("tracks/length"), t.length()); - } - - auto rejectTrack = [&](const auto& t, auto h) { - if (t.length() < minLength) { - return true; - } - histos.fill(h, 4); - if (t.length() > maxLength) { - return true; - } - histos.fill(h, 5); - if (t.eta() < minEta) { - return true; - } - histos.fill(h, 6); - if (t.eta() > maxEta) { - return true; - } - histos.fill(h, 7); - const auto mcParticle = t.template mcParticle_as(); - if (pdgCode != 0 && abs(mcParticle.pdgCode()) != pdgCode) { - return true; - } - histos.fill(h, 8); - return false; - }; - - for (const auto& track : tracks) { // Barrel RICH - histos.fill(HIST("bRICH/TrackSelection"), 1); - if (!track.has_rich()) { - continue; - } - histos.fill(HIST("bRICH/TrackSelection"), 2); - if (useTOF && !track.hasTOF()) { - continue; - } - histos.fill(HIST("bRICH/TrackSelection"), 3); - if (rejectTrack(track, HIST("bRICH/TrackSelection"))) { - continue; - } - - const float delta = track.rich().richDelta(pid_type); - float nsigma = track.rich().richNsigma(pid_type); - if (useTOF) { - if constexpr (pid_type == 0) { // Electron - nsigma += track.tofNSigmaEl(); - } else if constexpr (pid_type == 1) { // Muon - nsigma += track.tofNSigmaMu(); - } else if constexpr (pid_type == 2) { // Pion - nsigma += track.tofNSigmaPi(); - } else if constexpr (pid_type == 3) { // Kaon - nsigma += track.tofNSigmaKa(); - } else if constexpr (pid_type == 4) { // Proton - nsigma += track.tofNSigmaPr(); - } - nsigma *= nSigmaNorm; // Normalize to 1 - } - - histos.fill(HIST("bRICH/p"), track.p()); - histos.fill(HIST("bRICH/pt"), track.pt()); - histos.fill(HIST("bRICH/eta"), track.eta()); - histos.fill(HIST("bRICH/signal"), track.rich().richSignal()); - histos.fill(HIST("bRICH/signalerror"), track.rich().richSignalError()); - histos.fill(HIST("bRICH/signalvsP"), track.p(), track.rich().richSignal()); - - histos.fill(HIST(hbRICHNSigma[pid_type]), track.pt(), nsigma); - histos.fill(HIST(hbRICHDelta[pid_type]), track.p(), delta); - // const auto mcParticle = labels.iteratorAt(track.globalIndex()).mcParticle_as(); - const auto mcParticle = track.mcParticle_as(); - if (mcParticle.isPhysicalPrimary()) { // Selecting primaries - histos.fill(HIST(hbRICHNSigmaPrm[pid_type]), track.pt(), nsigma); - histos.fill(HIST("bRICH/signalvsPPrm"), track.p(), track.rich().richSignal()); - histos.fill(HIST("bRICH/pPrm"), track.p()); - histos.fill(HIST("bRICH/ptPrm"), track.pt()); - } else { - histos.fill(HIST(hbRICHNSigmaSec[pid_type]), track.pt(), nsigma); - histos.fill(HIST("bRICH/signalvsPSec"), track.p(), track.rich().richSignal()); - histos.fill(HIST("bRICH/pSec"), track.p()); - histos.fill(HIST("bRICH/ptSec"), track.pt()); - } - fillNsigma<0>(track, mcParticle, nsigma); - fillNsigma<1>(track, mcParticle, nsigma); - fillNsigma<2>(track, mcParticle, nsigma); - fillNsigma<3>(track, mcParticle, nsigma); - fillNsigma<4>(track, mcParticle, nsigma); - } - - for (const auto& track : tracksfrich) { // Forward RICH - histos.fill(HIST("fRICH/TrackSelection"), 1); - if (!track.has_frich()) { - continue; - } - histos.fill(HIST("fRICH/TrackSelection"), 2); - if (rejectTrack(track, HIST("fRICH/TrackSelection"))) { - continue; - } - - const float delta = track.frich().frichDelta(pid_type); - const float nsigma = track.frich().frichNsigma(pid_type); - - histos.fill(HIST("fRICH/p"), track.p()); - histos.fill(HIST("fRICH/pt"), track.pt()); - histos.fill(HIST("fRICH/eta"), track.eta()); - histos.fill(HIST("fRICH/signal"), track.frich().frichSignal()); - histos.fill(HIST("fRICH/signalerror"), track.frich().frichSignalError()); - histos.fill(HIST("fRICH/signalvsP"), track.p(), track.frich().frichSignal()); - - histos.fill(HIST(hfRICHNSigma[pid_type]), track.pt(), nsigma); - histos.fill(HIST(hfRICHDelta[pid_type]), track.p(), delta); - const auto mcParticle = track.mcParticle_as(); - if (mcParticle.isPhysicalPrimary()) { // Selecting primaries - histos.fill(HIST(hfRICHNSigmaPrm[pid_type]), track.pt(), nsigma); - histos.fill(HIST("fRICH/signalvsPPrm"), track.p(), track.frich().frichSignal()); - histos.fill(HIST("fRICH/pPrm"), track.p()); - histos.fill(HIST("fRICH/ptPrm"), track.pt()); - } else { - histos.fill(HIST(hfRICHNSigmaSec[pid_type]), track.pt(), nsigma); - histos.fill(HIST("fRICH/signalvsPSec"), track.p(), track.frich().frichSignal()); - histos.fill(HIST("fRICH/pSec"), track.p()); - histos.fill(HIST("fRICH/ptSec"), track.pt()); - } - fillNsigmafRICH<0>(track, mcParticle, nsigma); - fillNsigmafRICH<1>(track, mcParticle, nsigma); - fillNsigmafRICH<2>(track, mcParticle, nsigma); - fillNsigmafRICH<3>(track, mcParticle, nsigma); - fillNsigmafRICH<4>(track, mcParticle, nsigma); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfg) -{ - auto workflow = WorkflowSpec{adaptAnalysisTask(cfg)}; - if (cfg.options().get("qa-el")) { - workflow.push_back(adaptAnalysisTask>(cfg, TaskName{"pidRICH-qa-El"})); - } - if (cfg.options().get("qa-mu")) { - workflow.push_back(adaptAnalysisTask>(cfg, TaskName{"pidRICH-qa-Mu"})); - } - if (cfg.options().get("qa-pikapr")) { - workflow.push_back(adaptAnalysisTask>(cfg, TaskName{"pidRICH-qa-Pi"})); - workflow.push_back(adaptAnalysisTask>(cfg, TaskName{"pidRICH-qa-Ka"})); - workflow.push_back(adaptAnalysisTask>(cfg, TaskName{"pidRICH-qa-Pr"})); - } - return workflow; -} diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 02c0e0b297b..46931f96988 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -23,7 +23,7 @@ // #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ALICE3/DataModel/ECAL.h" +// #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/RecoDecay.h" #include @@ -1732,65 +1732,65 @@ DECLARE_SOA_TABLE(HfCandXicResid, "AOD", "HFCANDXICRESID", hf_cand_xic_to_xi_pi_pi::ZSvPull); // specific chic candidate properties -namespace hf_cand_chic -{ -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi index -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, ECALs, "_1"); -DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass -} // namespace hf_cand_chic - -// declare dedicated chi_c candidate table -DECLARE_SOA_TABLE(HfCandChicBase, "AOD", "HFCANDCHICBASE", - // general columns - HFCAND_COLUMNS, - // 2-prong specific columns - hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, - hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, - hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, - hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, - hf_cand_chic::Prong0Id, hf_cand_chic::Prong1Id, - hf_track_index::HFflag, hf_cand_chic::JpsiToMuMuMass, - /* dynamic columns */ - hf_cand_2prong::M, - hf_cand_2prong::M2, - /* prong 2 */ - // hf_cand::PtProng1, - // hf_cand::Pt2Prong1, - // hf_cand::PVectorProng1, - /* dynamic columns that use candidate momentum components */ - hf_cand::Pt, - hf_cand::Pt2, - hf_cand::P, - hf_cand::P2, - hf_cand::PVector, - hf_cand::Cpa, - hf_cand::CpaXY, - hf_cand::Ct, - hf_cand::ImpactParameterXY, - hf_cand_2prong::MaxNormalisedDeltaIP, - hf_cand::Eta, - hf_cand::Phi, - hf_cand::Y, - hf_cand::E, - hf_cand::E2); - -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(HfCandChicExt, HfCandChicBase, "HFCANDCHICEXT", - hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); - -using HfCandChic = HfCandChicExt; - -// table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfCandChicMcRec, "AOD", "HFCANDCHICMCREC", //! - hf_cand_mc_flag::FlagMcMatchRec, - hf_cand_mc_flag::OriginMcRec, - hf_cand_mc_flag::FlagMcDecayChanRec); - -// table with results of generator level MC matching -DECLARE_SOA_TABLE(HfCandChicMcGen, "AOD", "HFCANDCHICMCGEN", //! - hf_cand_mc_flag::FlagMcMatchGen, - hf_cand_mc_flag::OriginMcGen, - hf_cand_mc_flag::FlagMcDecayChanGen); +// namespace hf_cand_chic +// { +// DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi index +// DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, ECALs, "_1"); +// DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass +// } // namespace hf_cand_chic + +// // declare dedicated chi_c candidate table +// DECLARE_SOA_TABLE(HfCandChicBase, "AOD", "HFCANDCHICBASE", +// // general columns +// HFCAND_COLUMNS, +// // 2-prong specific columns +// hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, +// hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, +// hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, +// hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, +// hf_cand_chic::Prong0Id, hf_cand_chic::Prong1Id, +// hf_track_index::HFflag, hf_cand_chic::JpsiToMuMuMass, +// /* dynamic columns */ +// hf_cand_2prong::M, +// hf_cand_2prong::M2, +// /* prong 2 */ +// // hf_cand::PtProng1, +// // hf_cand::Pt2Prong1, +// // hf_cand::PVectorProng1, +// /* dynamic columns that use candidate momentum components */ +// hf_cand::Pt, +// hf_cand::Pt2, +// hf_cand::P, +// hf_cand::P2, +// hf_cand::PVector, +// hf_cand::Cpa, +// hf_cand::CpaXY, +// hf_cand::Ct, +// hf_cand::ImpactParameterXY, +// hf_cand_2prong::MaxNormalisedDeltaIP, +// hf_cand::Eta, +// hf_cand::Phi, +// hf_cand::Y, +// hf_cand::E, +// hf_cand::E2); + +// // extended table with expression columns that can be used as arguments of dynamic columns +// DECLARE_SOA_EXTENDED_TABLE_USER(HfCandChicExt, HfCandChicBase, "HFCANDCHICEXT", +// hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); + +// using HfCandChic = HfCandChicExt; + +// // table with results of reconstruction level MC matching +// DECLARE_SOA_TABLE(HfCandChicMcRec, "AOD", "HFCANDCHICMCREC", //! +// hf_cand_mc_flag::FlagMcMatchRec, +// hf_cand_mc_flag::OriginMcRec, +// hf_cand_mc_flag::FlagMcDecayChanRec); + +// // table with results of generator level MC matching +// DECLARE_SOA_TABLE(HfCandChicMcGen, "AOD", "HFCANDCHICMCGEN", //! +// hf_cand_mc_flag::FlagMcMatchGen, +// hf_cand_mc_flag::OriginMcGen, +// hf_cand_mc_flag::FlagMcDecayChanGen); // specific Lb candidate properties namespace hf_cand_lb From 14591e040d14d619b6f5b0f4514231448c24526f Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Wed, 6 May 2026 02:27:17 -0600 Subject: [PATCH 054/449] [PWGLF] Update DCA cuts for systematic studies and add V0 mass plots (#16120) Co-authored-by: Paola Vargas Torres --- PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx | 158 ++++++++++++++++++++----- 1 file changed, 127 insertions(+), 31 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index 25545401f27..ef69d76fce9 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -83,7 +83,6 @@ struct DedxPidAnalysis { static constexpr int EtaIntervals = 8; static constexpr int ParticlesType = 4; static constexpr int CentralityClasses = 10; - float tpcCut = 0.6; float pionMin = 0.35; float pionMax = 0.45; float elTofCut = 0.1; @@ -197,6 +196,11 @@ struct DedxPidAnalysis { Configurable etaMin{"etaMin", -0.8f, "etaMin"}; Configurable etaMax{"etaMax", +0.8f, "etaMax"}; Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable nSigmaDCAxy{"nSigmaDCAxy", 3.0, "nSigma DCAxy selection"}; + Configurable dcaXYp0{"dcaXYp0", 0.0105f, "DCAxy formula: p0 + p1/pt^p2"}; + Configurable dcaXYp1{"dcaXYp1", 0.0350f, "DCAxy p1 parameter"}; + Configurable dcaXYp2{"dcaXYp2", 1.1f, "DCA_xy p2 parameter"}; + Configurable nSigmaDCAz{"nSigmaDCAz", 3.0, "nSigma DCAz selection"}; Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; // v0 cuts Configurable v0cospaMin{"v0cospaMin", 0.999f, "Minimum V0 CosPA"}; @@ -215,7 +219,8 @@ struct DedxPidAnalysis { Configurable v0rapidityCut{"v0rapidityCut", 0.5f, "V0 rapidity cut"}; Configurable v0ProperLifetimeCutK0s{"v0ProperLifetimeCutK0s", 20.f, "V0 proper lifetime cut for K0s"}; Configurable v0ProperLifetimeCutLambda{"v0ProperLifetimeCutLambda", 30.f, "V0 proper lifetime cut for Lambda"}; - Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; + Configurable nsigmaMax{"nsigmaMax", 3.0f, "Maximum nsigma cut"}; + Configurable tpcMomentumCut{"tpcMomentumCut", 0.6f, "Momentum threshold above which TOF is required"}; Configurable invMassCutK0s{"invMassCutK0s", 0.015f, "invariant Mass Cut for K0s"}; Configurable invMassCutLambda{"invMassCutLambda", 0.015f, "invariant Mass Cut for Lambda"}; Configurable invMassCutGamma{"invMassCutGamma", 0.015f, "invariant Mass Cut for Gamma"}; @@ -276,8 +281,8 @@ struct DedxPidAnalysis { selectedTracks.SetMaxChi2PerClusterTPC(maxChi2TPC); selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); selectedTracks.SetMaxChi2PerClusterITS(maxChi2ITS); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(maxDCAz); + // selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); + // selectedTracks.SetMaxDcaZ(maxDCAz); selectedTracks.SetRequireGoldenChi2(true); return selectedTracks; @@ -299,7 +304,8 @@ struct DedxPidAnalysis { LOGF(info, "GoodZvtxFT0vsPV cut disabled"); } if (nINELSelectionMode == NoSelINEL) { - LOGF(info, "INEL cut disabled"); + LOGF(info, "Applying just INEL"); + label = "INEL"; } else if (nINELSelectionMode == SelINELgt0) { LOGF(info, "Applying INEL > 0 cut"); label = "INEL > 0"; @@ -483,6 +489,30 @@ struct DedxPidAnalysis { for (int i = 0; i < CentralityClasses + 1; ++i) { hDedxVspTMomentumVsCent[i] = registryDeDx.add(DedxvspTMomentumvsCent[i].data(), "dE/dx", HistType::kTH3F, {{ptAxis}, {dedxAxis}, {etaAxis}}); } + + // Invariant Mass + registryDeDx.add("hMassK0s", "Invariant mass K0s;m_{#pi#pi} (GeV/c^{2});Counts", + HistType::kTH1F, {{200, 0.4, 0.6}}); + registryDeDx.add("hMassLambda", "Invariant mass #Lambda;m_{p#pi} (GeV/c^{2});Counts", + HistType::kTH1F, {{200, 1.08, 1.16}}); + registryDeDx.add("hMassAntiLambda", "Invariant mass #bar{#Lambda};m_{#bar{p}#pi} (GeV/c^{2});Counts", + HistType::kTH1F, {{200, 1.08, 1.16}}); + registryDeDx.add("hMassGamma", "Invariant mass #gamma;m_{ee} (GeV/c^{2});Counts", + HistType::kTH1F, {{200, 0.0, 0.1}}); + + // Armenteros-Podolanski plot + registryDeDx.add("hArmenterosAll", "Armenteros-Podolanski (all V0s);#alpha;q_{T} (GeV/c)", + HistType::kTH2F, {{200, -1, 1}, {200, 0, 0.3}}); + + // Armenteros-Podolanski plot by particle + registryDeDx.add("hArmenterosK0s", "Armenteros-Podolanski K0s;#alpha;q_{T} (GeV/c)", + HistType::kTH2F, {{200, -1, 1}, {200, 0, 0.3}}); + registryDeDx.add("hArmenterosLambda", "Armenteros-Podolanski #Lambda;#alpha;q_{T} (GeV/c)", + HistType::kTH2F, {{200, -1, 1}, {200, 0, 0.3}}); + registryDeDx.add("hArmenterosAntiLambda", "Armenteros-Podolanski #bar{#Lambda};#alpha;q_{T} (GeV/c)", + HistType::kTH2F, {{200, -1, 1}, {200, 0, 0.3}}); + registryDeDx.add("hArmenterosGamma", "Armenteros-Podolanski #gamma;#alpha;q_{T} (GeV/c)", + HistType::kTH2F, {{200, -1, 1}, {200, 0, 0.3}}); } registryDeDx.add( @@ -663,6 +693,23 @@ struct DedxPidAnalysis { registryDeDx.add("Tracks_vs_pT_all", "pT All", HistType::kTH1F, {{ptAxis}}); registryDeDx.add("Tracks_vs_pT_all_cuts", "pT All + cuts", HistType::kTH1F, {{ptAxis}}); + // NCluster distributions + registryDeDx.add("hTPCClustersBefore", "N clusters TPC found Before", HistType::kTH1F, {{200, 0, 200, "N_{cl,found, Before}"}}); + registryDeDx.add("hTPCClustersAfter", "N clusters TPC found After", HistType::kTH1F, {{200, 0, 200, "N_{cl,found, After}"}}); + + registryDeDx.add("hTPCPIDBefore", "N clusters TPC PID Before", HistType::kTH1F, {{200, 0, 200, "N_{cl,PID, Before}"}}); + registryDeDx.add("hTPCPIDAfter", "N clusters TPC PID After", HistType::kTH1F, {{200, 0, 200, "N_{cl,PID, After}"}}); + + // DCA cut + registryDeDx.add("hDCAxyVsPt_before", "DCAxy vs pT before cut;#it{p}_{T} (GeV/c);DCA_{xy} (cm)", + HistType::kTH2F, {{ptAxis}, {200, -0.5, 0.5}}); + registryDeDx.add("hDCAzVsPt_before", "DCAz vs pT before cut;#it{p}_{T} (GeV/c);DCA_{z} (cm)", + HistType::kTH2F, {{ptAxis}, {200, -0.5, 0.5}}); + registryDeDx.add("hDCAxyVsPt_after", "DCAxy vs pT after cut;#it{p}_{T} (GeV/c);DCA_{xy} (cm)", + HistType::kTH2F, {{ptAxis}, {200, -0.5, 0.5}}); + registryDeDx.add("hDCAzVsPt_after", "DCAz vs pT after cut;#it{p}_{T} (GeV/c);DCA_{z} (cm)", + HistType::kTH2F, {{ptAxis}, {200, -0.5, 0.5}}); + // Event Counter registryDeDx.add("evsel", "events selected", HistType::kTH1F, {{6, 0.5, 6.5, ""}}); auto hstat = registryDeDx.get(HIST("evsel")); @@ -721,6 +768,7 @@ struct DedxPidAnalysis { xSec->SetBinLabel(V0TypeGamma, "V0TypeGamma"); xSec->SetBinLabel(V0RapidityGamma, "V0RapidityGamma"); xSec->SetBinLabel(MassCutGamma, "MassCutGamma"); + mySelectionPrim = myTrackSelection(); } @@ -740,7 +788,20 @@ struct DedxPidAnalysis { return true; } - + // DCA xy cut + template + bool passesDCAxyCut(const T1& track) const + { + const float maxDcaXY = nSigmaDCAxy.value * (dcaXYp0.value + dcaXYp1.value / std::pow(track.pt(), dcaXYp2.value)) / 3.0; + return std::abs(track.dcaXY()) < maxDcaXY; + } + // DCA z cut + template + bool passesDCAzCut(const T1& track) const + { + const float maxiDcaZ = nSigmaDCAz.value * (maxDCAz.value) / 3.0; + return std::abs(track.dcaZ()) < maxiDcaZ; + } // Momentum template float getMomentum(const T1& track) @@ -780,7 +841,7 @@ struct DedxPidAnalysis { return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - /*double sigmap = 0.0; + double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -794,19 +855,20 @@ struct DedxPidAnalysis { sigman = std::hypot(ntrack.tpcNSigmaPi(), ntrack.tofNSigmaPi()); } - if (ptrack.tpcInnerParam() > tpcCut) { + if (ptrack.tpcInnerParam() > tpcMomentumCut) { if (!ptrack.hasTOF()) return false; - if (std::abs(sigmap) > nsigmaTOFmax) + if (std::abs(sigmap) > nsigmaMax) return false; } - if (ntrack.tpcInnerParam() > tpcCut) { + if (ntrack.tpcInnerParam() > tpcMomentumCut) { if (!ntrack.hasTOF()) return false; - if (std::abs(sigman) > nsigmaTOFmax) + if (std::abs(sigman) > nsigmaMax) return false; - }*/ + } + if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionK0s); @@ -860,7 +922,7 @@ struct DedxPidAnalysis { if (!passedSingleTrackSelection(ntrack, collision)) return false; - /*double sigmap = 0.0; + double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -874,19 +936,19 @@ struct DedxPidAnalysis { sigman = std::hypot(ntrack.tpcNSigmaPi(), ntrack.tofNSigmaPi()); } - if (ptrack.tpcInnerParam() > tpcCut) { + if (ptrack.tpcInnerParam() > tpcMomentumCut) { if (!ptrack.hasTOF()) return false; - if (std::abs(sigmap) > nsigmaTOFmax) + if (std::abs(sigmap) > nsigmaMax) return false; } - if (ntrack.tpcInnerParam() > tpcCut) { + if (ntrack.tpcInnerParam() > tpcMomentumCut) { if (!ntrack.hasTOF()) return false; - if (std::abs(sigman) > nsigmaTOFmax) + if (std::abs(sigman) > nsigmaMax) return false; - }*/ + } if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionLambda); @@ -935,7 +997,7 @@ struct DedxPidAnalysis { return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - /*double sigmap = 0.0; + double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -948,19 +1010,19 @@ struct DedxPidAnalysis { sigmap = std::hypot(ptrack.tpcNSigmaPi(), ptrack.tofNSigmaPi()); sigman = std::hypot(ntrack.tpcNSigmaPr(), ntrack.tofNSigmaPr()); } - if (ptrack.tpcInnerParam() > tpcCut) { + if (ptrack.tpcInnerParam() > tpcMomentumCut) { if (!ptrack.hasTOF()) return false; - if (std::abs(sigmap) > nsigmaTOFmax) + if (std::abs(sigmap) > nsigmaMax) return false; } - if (ntrack.tpcInnerParam() > tpcCut) { + if (ntrack.tpcInnerParam() > tpcMomentumCut) { if (!ntrack.hasTOF()) return false; - if (std::abs(sigman) > nsigmaTOFmax) + if (std::abs(sigman) > nsigmaMax) return false; - }*/ + } if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionAntiLambda); @@ -1011,7 +1073,7 @@ struct DedxPidAnalysis { if (!passedSingleTrackSelection(ntrack, collision)) return false; - /*double sigmap = 0.0; + double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -1025,19 +1087,19 @@ struct DedxPidAnalysis { sigman = std::hypot(ntrack.tpcNSigmaEl(), ntrack.tofNSigmaEl()); } - if (ptrack.tpcInnerParam() > tpcCut) { + if (ptrack.tpcInnerParam() > tpcMomentumCut) { if (!ptrack.hasTOF()) return false; - if (std::abs(sigmap) > nsigmaTOFmax) + if (std::abs(sigmap) > nsigmaMax) return false; } - if (ntrack.tpcInnerParam() > tpcCut) { + if (ntrack.tpcInnerParam() > tpcMomentumCut) { if (!ntrack.hasTOF()) return false; - if (std::abs(sigman) > nsigmaTOFmax) + if (std::abs(sigman) > nsigmaMax) return false; - }*/ + } const float gammaMass = 2 * MassElectron; // GeV/c^2 if (fillHist) @@ -1462,6 +1524,7 @@ struct DedxPidAnalysis { } if (nINELSelectionMode == NoSelINEL) { + registryDeDx.fill(HIST("evsel"), EvCutLabel::INELgt); } else if (nINELSelectionMode == SelINELgt0) { if (!collision.isInelGt0()) return; @@ -1490,10 +1553,28 @@ struct DedxPidAnalysis { for (const auto& trk : tracks) { registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::AllPri); - // track Selection + // Ncl distribution before cuts + registryDeDx.fill(HIST("hTPCClustersBefore"), trk.tpcNClsFound()); + registryDeDx.fill(HIST("hTPCPIDBefore"), trk.tpcNClsPID()); + + // track Selection wo DCA if (!mySelectionPrim.IsSelected(trk)) continue; + // Before DCA cuts + registryDeDx.fill(HIST("hDCAxyVsPt_before"), trk.pt(), trk.dcaXY()); + registryDeDx.fill(HIST("hDCAzVsPt_before"), trk.pt(), trk.dcaZ()); + + // DCA cuts + if (!passesDCAxyCut(trk)) + continue; + if (!passesDCAzCut(trk)) + continue; + + // After DCA cuts + registryDeDx.fill(HIST("hDCAxyVsPt_after"), trk.pt(), trk.dcaXY()); + registryDeDx.fill(HIST("hDCAzVsPt_after"), trk.pt(), trk.dcaZ()); + registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::SelectionPrim); // For pt registryDeDx.fill(HIST("Tracks_vs_pT_all"), trk.pt()); @@ -1527,6 +1608,10 @@ struct DedxPidAnalysis { // For pt + cuts registryDeDx.fill(HIST("Tracks_vs_pT_all_cuts"), trk.pt()); + // Ncl distribution After all cuts + registryDeDx.fill(HIST("hTPCClustersAfter"), trk.tpcNClsFound()); + registryDeDx.fill(HIST("hTPCPIDAfter"), trk.tpcNClsPID()); + float signedP = trk.sign() * getMomentum(trk); float signedpT = trk.sign() * trk.pt(); @@ -1718,12 +1803,17 @@ struct DedxPidAnalysis { fillHist = true; + // Armenteros for all V0 + registryDeDx.fill(HIST("hArmenterosAll"), v0.alpha(), v0.qtarm()); + // K0s Selection if (passedK0Selection(v0, negTrack, posTrack, collision)) { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_PionsK0s"), posTrack.eta(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_PionsK0s"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsK0s"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsK0s"), negTrack.p(), negTrack.tpcNClsPID()); + registryDeDx.fill(HIST("hMassK0s"), v0.mK0Short()); + registryDeDx.fill(HIST("hArmenterosK0s"), v0.alpha(), v0.qtarm()); for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { registryDeDx.fill(HIST(DedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); @@ -1740,6 +1830,8 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_PionsLambda"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ProtonsLambda"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsLambda"), negTrack.p(), negTrack.tpcNClsPID()); + registryDeDx.fill(HIST("hMassLambda"), v0.mLambda()); + registryDeDx.fill(HIST("hArmenterosLambda"), v0.alpha(), v0.qtarm()); for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { registryDeDx.fill(HIST(DedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); @@ -1756,6 +1848,8 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_ProtonsLambda"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsLambda"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ProtonsLambda"), negTrack.p(), negTrack.tpcNClsPID()); + registryDeDx.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + registryDeDx.fill(HIST("hArmenterosAntiLambda"), v0.alpha(), v0.qtarm()); for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { registryDeDx.fill(HIST(DedxvsMomentumNeg[2]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); @@ -1772,6 +1866,8 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_ElectronsGamma"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ElectronsGamma"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ElectronsGamma"), negTrack.p(), negTrack.tpcNClsPID()); + registryDeDx.fill(HIST("hMassGamma"), v0.mGamma()); + registryDeDx.fill(HIST("hArmenterosGamma"), v0.alpha(), v0.qtarm()); for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { registryDeDx.fill(HIST(DedxvsMomentumNeg[3]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); From b3395162e3c0456a21334700560de85e973d3686 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Wed, 6 May 2026 14:27:32 +0530 Subject: [PATCH 055/449] [PWGLF] Added rejection condition for track misidentification (#16109) --- PWGLF/Tasks/Resonances/kstarqa.cxx | 73 +++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 15a859b5f5f..cb175523fd2 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -101,6 +101,7 @@ struct Kstarqa { Configurable isapplypTdepPIDTOF{"isapplypTdepPIDTOF", false, "Apply pT dependent PID for TOF"}; Configurable isApplyParticleMID{"isApplyParticleMID", false, "Apply particle misidentification"}; Configurable isApplyParticleMIDPtDep{"isApplyParticleMIDPtDep", false, "Apply pT dependent MID selection"}; + Configurable isApplyParticleMIDPtDep2{"isApplyParticleMIDPtDep2", false, "Apply pT dependent MID selection (nSigma less of contamination lt nSigma of signal)"}; Configurable allGenEvents{"allGenEvents", false, "Fill all generated events in MC for signal loss calculations"}; Configurable isApplyDeepAngle{"isApplyDeepAngle", false, "Deep Angle cut"}; @@ -670,7 +671,7 @@ struct Kstarqa { return true; } } else { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi) < configGp.nsigmaCutCombinedPi && std::abs(candidate.tpcNSigmaPi()) < configGp.nsigmaCutCombinedPi) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi) < configGp.nsigmaCutTOFPi && std::abs(candidate.tpcNSigmaPi()) < configGp.nsigmaCutTPCPi) { return true; } } @@ -693,7 +694,7 @@ struct Kstarqa { return true; } } else { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa) < configGp.nsigmaCutCombinedKa && std::abs(candidate.tpcNSigmaKa()) < configGp.nsigmaCutCombinedKa) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa) < configGp.nsigmaCutTOFKa && std::abs(candidate.tpcNSigmaKa()) < configGp.nsigmaCutTPCKa) { return true; } } @@ -827,6 +828,25 @@ struct Kstarqa { return false; } + template + bool selectionMIDPtDep2(const T& candidate, int PID) + { + const float ptCut1 = 1.0f; + const float ptCut2p5 = 2.5f; + const float ptCut07 = 0.7f; + + if (PID == PIDParticle::kPion) { + if (candidate.pt() >= ptCut1 && candidate.pt() < ptCut2p5 && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < std::abs(candidate.tpcNSigmaKa())) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() >= ptCut07 && candidate.pt() < ptCut2p5 && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < std::abs(candidate.tpcNSigmaPi())) { + return true; + } + } + return false; + } + template bool selectionPIDPtDep(const T& candidate, int PID) { @@ -1184,6 +1204,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(track1, 0)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(track2, 1)) // Pion misidentified as kaon + continue; + } + rEventSelection.fill(HIST("tracksCheckData"), 5.5); if (cQAplots) { @@ -1327,6 +1354,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(t1, 0)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(t2, 1)) // Pion misidentified as kaon + continue; + } + if (!selectionPair(t1, t2)) { continue; } @@ -1406,6 +1440,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(t1, 0)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(t2, 1)) // Pion misidentified as kaon + continue; + } + if (!t1.has_mcParticle() || !t2.has_mcParticle()) { continue; // skip if no MC particle associated } @@ -1556,6 +1597,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(track1, 0)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(track2, 1)) // Pion misidentified as kaon + continue; + } + rEventSelection.fill(HIST("tracksCheckData"), 5.5); // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) // continue; @@ -2124,6 +2172,13 @@ struct Kstarqa { if (selectionMIDPtDep(track2, 0)) // Pion misidentified as kaon continue; } + + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(track1, 1)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(track2, 0)) // Pion misidentified as kaon + continue; + } rEventSelection.fill(HIST("recMCparticles"), 13.5); // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > configGp.ctrackRapidity) @@ -2170,6 +2225,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(track1, 0)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep2(track2, 1)) // Pion misidentified as kaon + continue; + } + // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) // continue; @@ -2401,6 +2463,13 @@ struct Kstarqa { continue; } + if (configGp.isApplyParticleMIDPtDep2) { + if (selectionMIDPtDep2(track1, 1)) // Pion misidentified as kaon + continue; + if (selectionMIDPtDep2(track2, 0)) // Kaon misidentified as pion + continue; + } + // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) // continue; From 41644d3755f09b0c0fedc76a1ec2fe9b1a1beeb8 Mon Sep 17 00:00:00 2001 From: Kai Cui <129373281+kcui1@users.noreply.github.com> Date: Wed, 6 May 2026 11:15:55 +0200 Subject: [PATCH 056/449] [PWGLF] Add More Hist for FT0A/C Respectively in HSCorrelation Task (#16121) --- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 8eafed86a5e..4e4574d55f1 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -1916,10 +1916,19 @@ struct HStrangeCorrelation { for (int i = 1; i <= histos.get(HIST("Prediction/hEventSelection"))->GetNbinsX(); i++) { histos.get(HIST("Prediction/hEventSelection"))->GetXaxis()->SetBinLabel(i, eventSelLabel[i - 1]); } - if (masterConfigurations.useCentralityinPrediction) + if (masterConfigurations.useCentralityinPrediction) { + if (masterConfigurations.doSeparateFT0Prediction) { + histos.add("Prediction/hTriggerFT0A", "Trigger Tracks FT0A", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + histos.add("Prediction/hTriggerFT0C", "Trigger Tracks FT0C", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + } histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); - else + } else { + if (masterConfigurations.doSeparateFT0Prediction) { + histos.add("Prediction/hTriggerFT0A", "Trigger Tracks FT0A", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + histos.add("Prediction/hTriggerFT0C", "Trigger Tracks FT0C", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + } histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + } for (int i = 0; i < AssocParticleTypes; i++) { if (TESTBIT(doCorrelation, i)) histos.add(fmt::format("Prediction/h{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); @@ -3328,7 +3337,19 @@ struct HStrangeCorrelation { if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { triggerIndices.emplace_back(iteratorNum); - histos.fill(HIST("Prediction/hTrigger"), gpt, geta, gphi); + if (masterConfigurations.useCentralityinPrediction) { + if (masterConfigurations.doSeparateFT0Prediction) { + histos.fill(HIST("Prediction/hTriggerFT0A"), gpt, geta, centMultFT0A); + histos.fill(HIST("Prediction/hTriggerFT0C"), gpt, geta, centMultFT0C); + } + histos.fill(HIST("Prediction/hTrigger"), gpt, geta, centMultFT0M); + } else { + if (masterConfigurations.doSeparateFT0Prediction) { + histos.fill(HIST("Prediction/hTriggerFT0A"), gpt, geta, multFT0A); + histos.fill(HIST("Prediction/hTriggerFT0C"), gpt, geta, multFT0C); + } + histos.fill(HIST("Prediction/hTrigger"), gpt, geta, multFT0M); + } } if (masterConfigurations.doCorrelationHadron) { if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { From 155c2a6c5d16ff5d84caa186b374055a58b01a11 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Wed, 6 May 2026 11:53:14 +0200 Subject: [PATCH 057/449] [PWGUD] add true gap service and TPC-FT0 correlations (#16083) Co-authored-by: ALICE Action Bot --- PWGUD/DataModel/UDTruegapsideTables.h | 41 ++ PWGUD/TableProducer/CMakeLists.txt | 5 + PWGUD/TableProducer/trueGapProducer.cxx | 73 +++ PWGUD/Tasks/CMakeLists.txt | 5 + PWGUD/Tasks/flowLongRangeCorrUpc.cxx | 760 ++++++++++++++++++++++++ 5 files changed, 884 insertions(+) create mode 100644 PWGUD/DataModel/UDTruegapsideTables.h create mode 100644 PWGUD/TableProducer/trueGapProducer.cxx create mode 100644 PWGUD/Tasks/flowLongRangeCorrUpc.cxx diff --git a/PWGUD/DataModel/UDTruegapsideTables.h b/PWGUD/DataModel/UDTruegapsideTables.h new file mode 100644 index 00000000000..79255e3dc78 --- /dev/null +++ b/PWGUD/DataModel/UDTruegapsideTables.h @@ -0,0 +1,41 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file UDTruegapsideTables.h +/// \author Zhiyong Lu (zhiyong.lu@cern.ch) +/// \since Apr/7/2026 +/// \brief header defines truegapside outputs + +#ifndef PWGUD_DATAMODEL_UDTRUEGAPSIDETABLES_H_ +#define PWGUD_DATAMODEL_UDTRUEGAPSIDETABLES_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace o2::aod +{ +namespace upcservice +{ +DECLARE_SOA_COLUMN(Truegapside, truegapside, int); +} // namespace upcservice +DECLARE_SOA_TABLE(Truegapside, "AOD", "TRUEGAPSIDE", upcservice::Truegapside); +} // namespace o2::aod + +#endif // PWGUD_DATAMODEL_UDTRUEGAPSIDETABLES_H_ diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index c16870f0603..284b1af9fdc 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -66,6 +66,11 @@ o2physics_add_dpl_workflow(upc-cand-producer-muon PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(true-gap-producer + SOURCES trueGapProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc-cand-producer-global-muon SOURCES upcCandProducerGlobalMuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking diff --git a/PWGUD/TableProducer/trueGapProducer.cxx b/PWGUD/TableProducer/trueGapProducer.cxx new file mode 100644 index 00000000000..bb059d15b78 --- /dev/null +++ b/PWGUD/TableProducer/trueGapProducer.cxx @@ -0,0 +1,73 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file trueGapProducer.cxx +/// \author Zhiyong Lu (zhiyong.lu@cern.ch) +/// \since Apr/7/2026 +/// \brief task producing truegap + +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/DataModel/UDTruegapsideTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +struct TrueGapProducer { + SGSelector sgSelector; + Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; + Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; + Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; + Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; + + using UDCollisionsFull = soa::Join; + + Produces truegapside; + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; + AxisSpec axisgap = {binEdges, "true gap side"}; + registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); + } + + void process(UDCollisionsFull::iterator const& collision) + { + auto truegap = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + truegapside(truegap); + registry.fill(HIST("truegap"), truegap); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index bf1c0e7be72..3f5c41c0c25 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -259,6 +259,11 @@ o2physics_add_dpl_workflow(flow-mc-upc PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flow-long-range-corr-upc + SOURCES flowLongRangeCorrUpc.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(analysis-mc-dpm-jet-sg-v3 SOURCES analysisMCDPMJetSGv3.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGUD/Tasks/flowLongRangeCorrUpc.cxx b/PWGUD/Tasks/flowLongRangeCorrUpc.cxx new file mode 100644 index 00000000000..4b2aafbdaf4 --- /dev/null +++ b/PWGUD/Tasks/flowLongRangeCorrUpc.cxx @@ -0,0 +1,760 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file flowLongRangeCorrUpc.cxx +/// \author Zhiyong Lu (zhiyong.lu@cern.ch), Yongxi Du (yongxi.du@cern.ch) +/// \since Apr/7/2026 +/// \brief task for TPC-FT0 correlations in UPC + +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGUD/Core/UDHelpers.h" // udhelpers::Bits256, makeBits256, testBit, getPhiEtaFromFitBit +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/DataModel/UDTruegapsideTables.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include // o2::ft0::Geometry +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::math; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +struct FlowLongRangeCorrUpc { + // event selection + O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 1, "choose one side 0:A; 1:C") + O2_DEFINE_CONFIGURABLE(cfgGapSideMerge, bool, true, "merge A and C side") + // flags that already enabled in sgcandproducer: kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kIsVertexITSTPC, isGoodRCTCollision + O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") + O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 5, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") + + // track selection + O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgPtCutRefMin, float, 0.2f, "minimum accepted reference track pT") + O2_DEFINE_CONFIGURABLE(cfgPtCutRefMax, float, 3.0f, "minimum accepted reference track pT") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgGlobalTrack, bool, true, "use global track") + O2_DEFINE_CONFIGURABLE(cfgDcaXY, bool, true, "enable dcaxy cut") + O2_DEFINE_CONFIGURABLE(cfgDcaZ, bool, false, "enable dcaz cut") + O2_DEFINE_CONFIGURABLE(cfgDcaZCut, float, 10.0, "dcaz cut") + O2_DEFINE_CONFIGURABLE(cfgMaxTPCChi2NCl, int, 4, "max chi2 for tpc fit") + O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum number of crossed TPC Rows") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum number of found TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum number of ITS clusters") + + // user define + O2_DEFINE_CONFIGURABLE(cfgUseNchCorrected, bool, true, "use efficiency corrected tracks") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, true, "enable trigger pT < associated pT cut") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, true, "enable trigger pT < associated pT cut in mixed event") + O2_DEFINE_CONFIGURABLE(cfgCutMerging, float, 0.02, "Merging cut on track merge") + O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgDrawEtaPhiDis, bool, false, "draw eta-phi distribution for detectors in used") + + SliceCache cache; + + ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; + ConfigurableAxis axisPhi{"axisPhi", {72, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {36, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {20, -2, 2}, "delta eta axis for histograms"}; + ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; + ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; + ConfigurableAxis axisDeltaEtaFt0aFt0c{"axisDeltaEtaFt0aFt0c", {32, 5.5, 8.5}, "delta eta axis"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, "multiplicity axis for histograms"}; + ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, 0, 10}, "vertex axis for mixed event histograms"}; + ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30}, "multiplicity / centrality axis for mixed event histograms"}; + + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; + ConfigurableAxis axisThresholdFt0a{"axisThresholdFt0a", {5, 0, 5}, "FT0A amplitude"}; + AxisSpec axisChID = {220, 0, 220}; + + // make the filters and cuts. + Filter trackFilter = (aod::udtrack::isPVContributor == true); + Filter collisionFilter = (cfgGapSideMerge == true) + ? ((aod::udcollision::gapSide == (uint8_t)0 || aod::udcollision::gapSide == (uint8_t)1) && + (aod::upcservice::truegapside == 0 || aod::upcservice::truegapside == 1)) + : ((aod::udcollision::gapSide == (uint8_t)cfgGapSide) && + (aod::upcservice::truegapside == cfgGapSide)); + + using UDTracksFull = soa::Filtered>; + using UDCollisionsFull = soa::Filtered>; + + // FT0 geometry + o2::ft0::Geometry ft0Det{}; + // Minimal offset container compatible with UDHelpers.h expectations: getX/getY/getZ + struct OffsetXYZ { + double x{0}, y{0}, z{0}; + double getX() const { return x; } + double getY() const { return y; } + double getZ() const { return z; } + }; + std::array offsetFT0{}; // iRunOffset = 0 for now + int iRunOffset = 0; + static constexpr uint64_t Ft0IndexA = 96; + + // Corrections + TH3D* mEfficiency = nullptr; + bool correctionsLoaded = false; + + // Define the outputs + OutputObj sameTpcFt0a{"sameEvent_TPC_FT0A"}; + OutputObj mixedTpcFt0a{"mixedEvent_TPC_FT0A"}; + OutputObj sameTpcFt0c{"sameEvent_TPC_FT0C"}; + OutputObj mixedTpcFt0c{"mixedEvent_TPC_FT0C"}; + OutputObj sameFt0aFt0c{"sameEvent_FT0A_FT0C"}; + OutputObj mixedFt0aFt0c{"mixedEvent_FT0A_FT0C"}; + HistogramRegistry registry{"registry"}; + + // define global variables + Service ccdb; + TRandom3* gRandom = new TRandom3(); + enum EventType { + SameEvent = 1, + MixedEvent = 3 + }; + enum FITIndex { + kFT0A = 0, + kFT0C = 1 + }; + enum DataType { + kReco, + kGen + }; + + void init(InitContext&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + LOGF(info, "Starting init"); + + const AxisSpec axisEtaFull{90, -4., 5., "#eta"}; + std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; + AxisSpec axisgap = {binEdges, "true gap side"}; + if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) { + registry.add("truegap_inused", "truegap_inused", {HistType::kTH1D, {axisgap}}); + registry.add("trackSign", "trackSign", {HistType::kTH1D, {{10, -5, 5}}}); + registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); + registry.add("Phi_FT0A", "Phi_FT0A", {HistType::kTH1D, {axisPhi}}); + registry.add("Phi_FT0C", "Phi_FT0C", {HistType::kTH1D, {axisPhi}}); + registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + registry.add("Eta_FT0A", "Eta_FT0A", {HistType::kTH1D, {{20, 3., 5.}}}); + registry.add("Eta_FT0C", "Eta_FT0C", {HistType::kTH1D, {{20, -4.0, -2.0}}}); + registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); + registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); + registry.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPtTrigger}}); + registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("Nch_used_TPCFT0A", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + registry.add("Nch_used_TPCFT0C", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisThresholdFt0a}}); + registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisThresholdFt0a}}); + registry.add("hDCAz", "DCAz after cuts; DCAz (cm); Pt", {HistType::kTH2D, {{100, -0.5, 0.5}, {100, 0, 10}}}); + registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{100, -0.5, 0.5}, {100, 0, 10}}}); + if (cfgDrawEtaPhiDis) { + registry.add("EtaPhi", "", {HistType::kTH2F, {axisEtaFull, axisPhi}}); + } + } + + if (doprocessSameTpcFt0a) { + registry.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); + registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (doprocessSameTpcFt0c) { + registry.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); + registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (doprocessSameFt0aFt0c) { + registry.add("deltaEta_deltaPhi_same_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); + registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + + registry.add("eventcount_TPCFT0A", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_TPCFT0C", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_FT0AFT0C", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + + LOGF(info, "Initializing correlation container"); + std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; + std::vector effAxis = { + {axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}, + }; + std::vector userAxis; + std::vector corrAxisTpcFt0c = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; + std::vector corrAxisFt0aFt0c = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaFt0aFt0c, "#Delta#eta"}}; + + if (doprocessSameTpcFt0a) { + sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + mixedTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + } + if (doprocessSameTpcFt0c) { + sameTpcFt0c.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + mixedTpcFt0c.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + } + if (doprocessSameFt0aFt0c) { + sameFt0aFt0c.setObject(new CorrelationContainer("sameEvent_FT0A_FT0C", "sameEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + mixedFt0aFt0c.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + } + + ft0Det.calculateChannelCenter(); + + LOGF(info, "End of init"); + } + + template + bool trackSelected(TTrack track) + { + if (track.pt() < cfgPtCutMin || track.pt() > cfgPtCutMax) { + return false; + } + if (!track.isPVContributor()) { + return false; + } + if (cfgGlobalTrack && !(track.hasITS() && track.hasTPC())) { + return false; + } + if (track.tpcNClsCrossedRows() < cfgCutTPCCrossedRows) { + return false; + } + auto tpcClu = track.tpcNClsFindable() - track.tpcNClsFindableMinusFound(); + if (tpcClu < cfgCutTPCclu) { + return false; + } + if (track.tpcChi2NCl() >= cfgMaxTPCChi2NCl) { + return false; + } + if (track.itsNCls() < cfgCutITSclu) { + return false; + } + if (cfgDcaZ && !(std::fabs(track.dcaZ()) < cfgDcaZCut)) { + return false; + } + double dcaLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (cfgDcaXY && !(std::fabs(track.dcaXY()) < dcaLimit)) { + return false; + } + + return true; + } + + void loadCorrection(uint64_t timestamp) + { + if (correctionsLoaded) { + return; + } + if (cfgEfficiency.value.empty() == false) { + mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); + } + correctionsLoaded = true; + } + + bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) + { + float eff = 1.; + if (mEfficiency) { + int etaBin = mEfficiency->GetXaxis()->FindBin(eta); + int ptBin = mEfficiency->GetYaxis()->FindBin(pt); + int zBin = mEfficiency->GetZaxis()->FindBin(posZ); + eff = mEfficiency->GetBinContent(etaBin, ptBin, zBin); + } else { + eff = 1.0; + } + if (eff == 0) + return false; + weight_nue = 1. / eff; + return true; + } + + template + double trackCounter(TTracks tracks, float posZ) + { + float weff1 = 1; + double nTracksRaw = 0.; + double nTracksCorrected = 0.; + for (auto const& track1 : tracks) { + if (!trackSelected(track1)) + continue; + nTracksRaw += 1.; + auto momentum = std::array{track1.px(), track1.py(), track1.pz()}; + double pt = track1.pt(); + double eta = RecoDecay::eta(momentum); + if (!getEfficiencyCorrection(weff1, eta, pt, posZ)) + continue; + nTracksCorrected += weff1; + } + if (cfgUseNchCorrected) + return nTracksCorrected; + else + return nTracksRaw; + } + + template + void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. + { + float weff1 = 1; + float vtxz = collision.posZ(); + registry.fill(HIST("truegap_inused"), collision.truegapside()); + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), vtxz); + for (auto const& track1 : tracks) { + if (!trackSelected(track1)) + continue; + auto momentum = std::array{track1.px(), track1.py(), track1.pz()}; + double pt = track1.pt(); + double phi = RecoDecay::phi(momentum); + double eta = RecoDecay::eta(momentum); + if (!getEfficiencyCorrection(weff1, eta, pt, vtxz)) + continue; + registry.fill(HIST("Phi"), RecoDecay::constrainAngle(phi, 0.0)); + registry.fill(HIST("Eta"), eta); + registry.fill(HIST("EtaCorrected"), eta, weff1); + registry.fill(HIST("pT"), pt); + registry.fill(HIST("pTCorrected"), pt, weff1); + registry.fill(HIST("hDCAz"), track1.dcaZ(), pt); + registry.fill(HIST("hDCAxy"), track1.dcaXY(), pt); + registry.fill(HIST("trackSign"), track1.sign()); + } + } + + template + void fillCorrelationsTPCFT0(TTracks tracks1, aod::UDCollisionFITBits const& fitBits, float posZ, int system, int corType) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (fitBits.size() > 1) { + LOGF(fatal, "fillCorrelationsTPCFT0(): fitBits.size() = %d (expected 0 or 1)", fitBits.size()); + return; + } + if (fitBits.size() == 0) { + // no TPC-FT0 correlations for this collision + return; + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + if (!trackSelected(track1)) + continue; + auto momentum = std::array{track1.px(), track1.py(), track1.pz()}; + double pt = track1.pt(); + double tr_phi = RecoDecay::phi(momentum); + double tr_eta = RecoDecay::eta(momentum); + if (!getEfficiencyCorrection(triggerWeight, tr_eta, pt, posZ)) + continue; + if (system == SameEvent) { + if (corType == kFT0C) { + registry.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, pt, triggerWeight); + } else if (corType == kFT0A) { + registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, pt, triggerWeight); + } + if (cfgDrawEtaPhiDis) { + registry.fill(HIST("EtaPhi"), tr_eta, tr_phi, triggerWeight); + } + } + + // Only one row per collision is expected. + auto row = fitBits.begin(); + const auto w1 = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3()); + const auto w2 = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3()); + for (int chanelid = 0; chanelid < udhelpers::kFT0Bits; ++chanelid) { + // skip A channels if filling TPC-FT0C + if (corType == kFT0C && chanelid < udhelpers::kFT0AChannels) + continue; + // skip C channels if filling TPC-FT0A + if (corType == kFT0A && chanelid >= udhelpers::kFT0AChannels) + continue; + + // at least 1 fired channel + if (!udhelpers::testBit(w1, chanelid)) { + continue; + } + double fitCh_phi = 0., fitCh_eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, chanelid, offsetFT0, iRunOffset, fitCh_phi, fitCh_eta); + if (!ok) + continue; + float thr = 1.; + if (udhelpers::testBit(w2, chanelid)) + thr = 2.; + + if (system == SameEvent) { + if (corType == kFT0C) { + registry.fill(HIST("Phi_FT0C"), RecoDecay::constrainAngle(fitCh_phi, 0.0)); + registry.fill(HIST("Eta_FT0C"), fitCh_eta); + } else if (corType == kFT0A) { + registry.fill(HIST("Phi_FT0A"), RecoDecay::constrainAngle(fitCh_phi, 0.0)); + registry.fill(HIST("Eta_FT0A"), fitCh_eta); + } + if (cfgDrawEtaPhiDis) { + registry.fill(HIST("EtaPhi"), fitCh_eta, fitCh_phi, thr); + } + registry.fill(HIST("FT0Amp"), chanelid, thr); + } + + float deltaPhi = RecoDecay::constrainAngle(tr_phi - fitCh_phi, -PIHalf); + float deltaEta = tr_eta - fitCh_eta; + // fill the right sparse and histograms + if (system == SameEvent) { + if (corType == kFT0A) { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, thr * triggerWeight); + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, pt, pt, deltaPhi, deltaEta, thr * triggerWeight); + } else if (corType == kFT0C) { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, thr * triggerWeight); + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, pt, pt, deltaPhi, deltaEta, thr * triggerWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0A) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, thr * triggerWeight); + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, pt, pt, deltaPhi, deltaEta, thr * triggerWeight); + } else if (corType == kFT0C) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, thr * triggerWeight); + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, pt, pt, deltaPhi, deltaEta, thr * triggerWeight); + } + } + } + } + } + + template + void fillCorrelationsFT0AFT0C(aod::UDCollisionFITBits const& fitBits1, aod::UDCollisionFITBits const& fitBits2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (fitBits1.size() > 1 || fitBits2.size() > 1) { + LOGF(fatal, "fillCorrelationsFT0AFT0C(): fitBits1.size() = %d, fitBits2.size() = %d (expected 0 or 1)", fitBits1.size(), fitBits2.size()); + return; + } + if (fitBits1.size() == 0 || fitBits2.size() == 0) { + // no TPC-FT0 correlations for this collision + return; + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + // Only one row per collision is expected. + auto rowA = fitBits1.begin(); + const auto w1A = udhelpers::makeBits256(rowA.thr1W0(), rowA.thr1W1(), rowA.thr1W2(), rowA.thr1W3()); + const auto w2A = udhelpers::makeBits256(rowA.thr2W0(), rowA.thr2W1(), rowA.thr2W2(), rowA.thr2W3()); + auto rowC = fitBits2.begin(); + const auto w1C = udhelpers::makeBits256(rowC.thr1W0(), rowC.thr1W1(), rowC.thr1W2(), rowC.thr1W3()); + const auto w2C = udhelpers::makeBits256(rowC.thr2W0(), rowC.thr2W1(), rowC.thr2W2(), rowC.thr2W3()); + for (int chanelidA = 0; chanelidA < udhelpers::kFT0AChannels; ++chanelidA) { + // at least 1 fired channel + if (!udhelpers::testBit(w1A, chanelidA)) { + continue; + } + double fitCh_phiA = 0., fitCh_etaA = 0.; + const bool okA = udhelpers::getPhiEtaFromFitBit(ft0Det, chanelidA, offsetFT0, iRunOffset, fitCh_phiA, fitCh_etaA); + if (!okA) + continue; + float thrA = 1.; + if (udhelpers::testBit(w2A, chanelidA)) + thrA = 2.; + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist_FT0A_FT0C"), fSampleIndex, posZ, 0.5, thrA); + } + for (int chanelidC = udhelpers::kFT0AChannels; chanelidC < udhelpers::kFT0Bits; ++chanelidC) { + // at least 1 fired channel + if (!udhelpers::testBit(w1C, chanelidC)) { + continue; + } + double fitCh_phiC = 0., fitCh_etaC = 0.; + const bool okC = udhelpers::getPhiEtaFromFitBit(ft0Det, chanelidC, offsetFT0, iRunOffset, fitCh_phiC, fitCh_etaC); + if (!okC) + continue; + float thrC = 1.; + if (udhelpers::testBit(w2C, chanelidC)) + thrC = 2.; + + float deltaPhi = RecoDecay::constrainAngle(fitCh_phiA - fitCh_phiC, -PIHalf); + float deltaEta = fitCh_etaA - fitCh_etaC; + + // fill the right sparse and histograms + if (system == SameEvent) { + registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, thrA * thrC * triggerWeight); + sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, thrA * thrC * triggerWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, thrA * thrC * triggerWeight); + mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, thrA * thrC * triggerWeight); + } + } + } + } + + void processSameTpcFt0a(UDCollisionsFull::iterator const& collision, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + LOGF(info, "processSameTpcFt0a: collisionId:%d, tracks.size() = %d", collision.globalIndex(), tracks.size()); + LOGF(info, "processSameTpcFt0a: collisionId:%d, fitBits.size() = %d", collision.globalIndex(), fitBits.size()); + if (fitBits.size() > 1) { + LOGF(fatal, "processSameTpcFt0a: fitBits.size() = %d (expected 0 or 1)", fitBits.size()); + return; + } + + auto currentRunNumber = collision.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + double Nch = trackCounter(tracks, collision.posZ()); + if (Nch < cfgMinMult || Nch >= cfgMaxMult) { + return; + } + registry.fill(HIST("eventcount_TPCFT0A"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + registry.fill(HIST("Nch_used_TPCFT0A"), Nch); + + sameTpcFt0a->fillEvent(Nch, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsTPCFT0(tracks, fitBits, collision.posZ(), SameEvent, kFT0A); + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processSameTpcFt0a, "Process same event for TPC-FT0 correlation", true); + + void processMixedTpcFt0a(UDCollisionsFull const& collisions, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + auto getTracksSize = [&tracks, this](UDCollisionsFull::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::udtrack::udCollisionId, collision.globalIndex(), this->cache); + auto mult = trackCounter(associatedTracks, collision.posZ()); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + double Nch1 = trackCounter(tracks1, collision1.posZ()); + double Nch2 = trackCounter(tracks2, collision2.posZ()); + if (Nch1 < cfgMinMult || Nch1 >= cfgMaxMult) + continue; + if (Nch2 < cfgMinMult || Nch2 >= cfgMaxMult) + continue; + + auto fitBits2 = fitBits.sliceByCached(o2::aod::udtrack::udCollisionId, collision2.globalIndex(), this->cache); + if (fitBits2.size() > 1) { + LOGF(fatal, "processMixedTpcFt0a: collision2 Id:%d, fitBits2.size() = %d (expected 0 or 1)", collision2.globalIndex(), fitBits2.size()); + return; + } + if (fitBits2.size() == 0) { + continue; + } + + registry.fill(HIST("eventcount_TPCFT0A"), MixedEvent); // fill the mixed event in the 3 bin + auto currentRunNumber = collision1.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + fillCorrelationsTPCFT0(tracks1, fitBits2, collision1.posZ(), MixedEvent, kFT0A); + } + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processMixedTpcFt0a, "Process mixed events for TPC-FT0A correlation", true); + + void processSameTpcFt0c(UDCollisionsFull::iterator const& collision, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + if (fitBits.size() > 1) { + LOGF(fatal, "processSameTpcFt0c: fitBits.size() = %d (expected 0 or 1)", fitBits.size()); + return; + } + + auto currentRunNumber = collision.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + double Nch = trackCounter(tracks, collision.posZ()); + if (Nch < cfgMinMult || Nch >= cfgMaxMult) { + return; + } + registry.fill(HIST("eventcount_TPCFT0C"), SameEvent); // because its same event i put it in the 1 bin + if (!doprocessSameTpcFt0a) + fillYield(collision, tracks); + registry.fill(HIST("Nch_used_TPCFT0C"), Nch); + + sameTpcFt0c->fillEvent(Nch, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsTPCFT0(tracks, fitBits, collision.posZ(), SameEvent, kFT0C); + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processSameTpcFt0c, "Process same events for TPC-FT0C correlation", false); + + void processMixedTpcFt0c(UDCollisionsFull const& collisions, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + auto getTracksSize = [&tracks, this](UDCollisionsFull::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::udtrack::udCollisionId, collision.globalIndex(), this->cache); + auto mult = trackCounter(associatedTracks, collision.posZ()); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + double Nch1 = trackCounter(tracks1, collision1.posZ()); + double Nch2 = trackCounter(tracks2, collision2.posZ()); + if (Nch1 < cfgMinMult || Nch1 >= cfgMaxMult) + continue; + if (Nch2 < cfgMinMult || Nch2 >= cfgMaxMult) + continue; + + auto fitBits2 = fitBits.sliceByCached(o2::aod::udtrack::udCollisionId, collision2.globalIndex(), this->cache); + if (fitBits2.size() > 1) { + LOGF(fatal, "processMixedTpcFt0a: collision2 Id:%d, fitBits2.size() = %d (expected 0 or 1)", collision2.globalIndex(), fitBits2.size()); + return; + } + if (fitBits2.size() == 0) { + continue; + } + + registry.fill(HIST("eventcount_TPCFT0C"), MixedEvent); // fill the mixed event in the 3 bin + auto currentRunNumber = collision1.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + fillCorrelationsTPCFT0(tracks1, fitBits2, collision1.posZ(), MixedEvent, kFT0C); + } + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); + + void processSameFt0aFt0c(UDCollisionsFull::iterator const& collision, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + if (fitBits.size() > 1) { + LOGF(fatal, "processSameTpcFt0c: fitBits.size() = %d (expected 0 or 1)", fitBits.size()); + return; + } + + auto currentRunNumber = collision.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + double Nch = trackCounter(tracks, collision.posZ()); + if (Nch < cfgMinMult || Nch >= cfgMaxMult) { + return; + } + registry.fill(HIST("eventcount_FT0AFT0C"), SameEvent); // because its same event i put it in the 1 bin + if (!doprocessSameTpcFt0a) + fillYield(collision, tracks); + + sameFt0aFt0c->fillEvent(Nch, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFT0AFT0C(fitBits, fitBits, collision.posZ(), SameEvent); + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processSameFt0aFt0c, "Process same events for FT0A-FT0C correlation", false); + + void processMixedFt0aFt0c(UDCollisionsFull const& collisions, UDTracksFull const& tracks, aod::UDCollisionFITBits const& fitBits) + { + auto getTracksSize = [&tracks, this](UDCollisionsFull::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::udtrack::udCollisionId, collision.globalIndex(), this->cache); + auto mult = trackCounter(associatedTracks, collision.posZ()); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + double Nch1 = trackCounter(tracks1, collision1.posZ()); + double Nch2 = trackCounter(tracks2, collision2.posZ()); + if (Nch1 < cfgMinMult || Nch1 >= cfgMaxMult) + continue; + if (Nch2 < cfgMinMult || Nch2 >= cfgMaxMult) + continue; + + auto fitBits1 = fitBits.sliceByCached(o2::aod::udtrack::udCollisionId, collision1.globalIndex(), this->cache); + auto fitBits2 = fitBits.sliceByCached(o2::aod::udtrack::udCollisionId, collision2.globalIndex(), this->cache); + if (fitBits1.size() > 1 || fitBits2.size() > 1) { + LOGF(fatal, "processMixedTpcFt0a: fitBits1.size() = %d, fitBits2.size() = %d (expected 0 or 1)", fitBits1.size(), fitBits2.size()); + return; + } + if (fitBits1.size() == 0 || fitBits2.size() == 0) { + continue; + } + + registry.fill(HIST("eventcount_FT0AFT0C"), MixedEvent); // fill the mixed event in the 3 bin + auto currentRunNumber = collision1.runNumber(); + auto runDuration = ccdb->getRunDuration(currentRunNumber); + loadCorrection(runDuration.first); + + fillCorrelationsFT0AFT0C(fitBits1, fitBits2, collision1.posZ(), MixedEvent); + } + } + PROCESS_SWITCH(FlowLongRangeCorrUpc, processMixedFt0aFt0c, "Process mixed events for FT0A-FT0C correlation", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 5818d9fa710485c0629ae724de26511dcebcd11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Wed, 6 May 2026 11:58:37 +0200 Subject: [PATCH 058/449] [PWGCF] Fix includes (#16088) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 2 ++ .../Tasks/v0ptHadPiKaProt.cxx | 3 +- PWGCF/Femto/Core/pairHistManager.h | 2 +- PWGCF/Femto/Tasks/femtoPairEfficiency.cxx | 18 +++++------ ...irTaskTrackTrackSpherHarMultKtExtended.cxx | 1 - PWGCF/Flow/Tasks/flowFlucGfwPp.cxx | 31 ++++++++++++++----- .../Tasks/flowGenericFramework.cxx | 2 -- .../Tasks/multiharmonicCorrelations.cxx | 15 +++++++-- .../Tasks/multiparticleCumulants.cxx | 25 ++++++++++----- .../TwoParticleCorrelations/Tasks/corrFit.cxx | 3 -- .../Tasks/lambdaSpinPolarization.cxx | 1 - .../Tasks/longrangecorrDerived.cxx | 1 - 12 files changed, 69 insertions(+), 35 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index ed52213971c..c7bc8f8627c 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index ab0452aac82..a10705d4c0c 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -37,8 +37,8 @@ #include #include +#include #include -#include #include #include #include @@ -48,6 +48,7 @@ #include #include +#include #include #include #include diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index 9c533c8bf4d..a4fd9451ed2 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -20,7 +20,7 @@ #include "PWGCF/Femto/Core/histManager.h" #include "PWGCF/Femto/Core/modes.h" -#include +#include "Common/Core/RecoDecay.h" #include #include diff --git a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx index 6705f731599..49816c6b409 100644 --- a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx +++ b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx @@ -17,15 +17,15 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include #include diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 90d231f1927..e69e4b68ca6 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -50,7 +50,6 @@ #include #include #include -#include #include #include diff --git a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx index 037527c84f1..1405b0a60b0 100644 --- a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx +++ b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx @@ -14,41 +14,58 @@ /// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch, Wenya Wu, TUM, wenya.wu@cern.ch #include "PWGCF/GenericFramework/Core/FlowContainer.h" -#include "PWGCF/GenericFramework/Core/FlowPtContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" #include "PWGCF/GenericFramework/Core/GFWConfig.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EseTable.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.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 +#include +#include #include +#include +#include #include +#include #include -#include +#include #include +#include #include #include diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 5a1a358e7d3..e1eedcd7744 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -69,10 +69,8 @@ #include #include #include -#include #include #include -#include #include #include #include diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx index f47b8e0c4f5..5ea45627e26 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx @@ -15,15 +15,26 @@ #include "Common/DataModel/TrackSelectionTables.h" // needed for aod::TracksDCA table #include +#include #include +#include #include -#include +#include +#include +#include #include +#include +#include #include -#include +#include +#include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx index da32ae73479..d99dc18aa21 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx @@ -13,24 +13,35 @@ /// \brief Task for producing multiparticle cumulants /// \author Pei-Ying Kuan, TU München, pei-ying.kuan@cern.ch -#include -#include -#include -#include // needed for aod::TracksDCA table +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" // needed for aod::TracksDCA table #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 diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx index 450d9005646..15265a76dab 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx @@ -14,7 +14,6 @@ /// \author Thor Jensen (thor.kjaersgaard.jensen@cern.ch) #include "PWGCF/Core/CorrelationContainer.h" -#include "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" @@ -28,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +44,6 @@ #include #include -#include #include #include #include diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx index 747473bfdf6..7635688b9fb 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 8fadf85472a..705795bf863 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -36,7 +36,6 @@ #include #include -#include #include #include #include From d6fa9ed3d70a8544b79fe88c5bf35c8fc06afb58 Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Wed, 6 May 2026 12:09:05 +0200 Subject: [PATCH 059/449] [PWGLF] PWGLF - new QA hist in hStrangeCorrelation.cxx (#16111) Co-authored-by: Lucia Anna Tarasovicova --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 4e4574d55f1..55606515998 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -1774,6 +1774,12 @@ struct HStrangeCorrelation { histos.add("hNumberOfRejectedPairsHadron", "hNumberOfRejectedPairsHadron", kTH1F, {{1, 0, 1}}); histos.add("hNumberOfRejectedPairsPion", "hNumberOfRejectedPairsPion", kTH1F, {{1, 0, 1}}); } + if (doprocessSameEventHHadrons) { + histos.add("hDCAzTriggerHadron", "hDCAzTriggerHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); + histos.add("hDCAxyTriggerHadron", "hDCAxyTriggerHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); + histos.add("hDCAzAssociatedHadron", "hDCAzAssociatedHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); + histos.add("hDCAxyAssociatedHadron", "hDCAxyAssociatedHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); + } if (doprocessSameEventHV0s || doprocessMixedEventHV0s) { histos.add("hNumberOfRejectedPairsV0", "hNumberOfRejectedPairsV0", kTH1F, {{1, 0, 1}}); } @@ -2156,6 +2162,8 @@ struct HStrangeCorrelation { auto track = triggerTrack.track_as(); if (!isValidTrigger(track, triggerTrack.isLeading())) continue; + histos.fill(HIST("hDCAzTriggerHadron"), track.dcaZ(), track.pt()); + histos.fill(HIST("hDCAxyTriggerHadron"), track.dcaXY(), track.pt()); float efficiency = 1.0f; if (efficiencyFlags.applyEfficiencyCorrection) { efficiency = hEfficiencyTrigger->Interpolate(track.pt(), track.eta()); @@ -2178,6 +2186,8 @@ struct HStrangeCorrelation { continue; float efficiency = 1.0f; float purity = 1.0f; + histos.fill(HIST("hDCAzAssocHadron"), assoc.dcaZ(), assoc.pt()); + histos.fill(HIST("hDCAxyAssocHadron"), assoc.dcaXY(), assoc.pt()); if (efficiencyFlags.applyEfficiencyCorrection) { efficiency = hEfficiencyHadron->Interpolate(assoc.pt(), assoc.eta()); if (efficiencyFlags.applyPurityHadron) From d8605333d0d6f295d66066bed691997ec1e46181 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Wed, 6 May 2026 14:03:09 +0200 Subject: [PATCH 060/449] [PWGHF] Species-dependent minimum prong pt cut in skimming (#15755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marcello Di Costanzo Co-authored-by: ALICE Action Bot Co-authored-by: Vít Kučera <26327373+vkucera@users.noreply.github.com> --- PWGHF/Core/SelectorCuts.h | 17 ++++++----- PWGHF/TableProducer/trackIndexSkimCreator.cxx | 29 ++++++++++++++----- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 17a223bcd20..764fd0cc0c6 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -232,7 +232,7 @@ static const std::vector labelsCutVar = {"massMin", "massMax", "cos namespace hf_cuts_presel_3prong { static constexpr int NBinsPt = 2; -static constexpr int NCutVars = 4; +static constexpr int NCutVars = 5; // default values for the pT bin edges (can be used to configure histogram axis) // common for any 3-prong candidate // offset by 1 from the bin numbers in cuts array @@ -243,20 +243,21 @@ constexpr double BinsPt[NBinsPt + 1] = { const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; // default values for the cuts -constexpr double Cuts[NBinsPt][NCutVars] = {{1.75, 2.05, 0.7, 0.02}, /* 1 < pt < 5 */ - {1.75, 2.05, 0.5, 0.02}}; /* 5 < pt < 1000 */ +constexpr double Cuts[NBinsPt][NCutVars] = {{1.75, 2.05, 0.7, 0.02, 0.3}, /* 1 < pt < 5 */ + {1.75, 2.05, 0.5, 0.02, 0.3}}; /* 5 < pt < 1000 */ // row labels static const std::vector labelsPt{}; // column labels -static const std::vector labelsCutVar = {"massMin", "massMax", "cosp", "decL"}; +static const std::vector labelsCutVar = {"massMin", "massMax", "cosp", "decL", "ptProngMin"}; + } // namespace hf_cuts_presel_3prong namespace hf_cuts_presel_ds { static constexpr int NBinsPt = 2; -static constexpr int NCutVars = 5; +static constexpr int NCutVars = 6; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array constexpr double BinsPt[NBinsPt + 1] = { @@ -266,14 +267,14 @@ constexpr double BinsPt[NBinsPt + 1] = { const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; // default values for the cuts -constexpr double Cuts[NBinsPt][NCutVars] = {{1.70, 2.15, 0.7, 0.02, 0.02}, /* 1 < pt < 5 */ - {1.70, 2.15, 0.5, 0.02, 0.02}}; /* 5 < pt < 1000 */ +constexpr double Cuts[NBinsPt][NCutVars] = {{1.70, 2.15, 0.7, 0.02, 0.3, 0.02}, /* 1 < pt < 5 */ + {1.70, 2.15, 0.5, 0.02, 0.3, 0.02}}; /* 5 < pt < 1000 */ // row labels static const std::vector labelsPt{}; // column labels -static const std::vector labelsCutVar = {"massMin", "massMax", "cosp", "decL", "deltaMassKK"}; +static const std::vector labelsCutVar = {"massMin", "massMax", "cosp", "decL", "ptProngMin", "deltaMassKK"}; } // namespace hf_cuts_presel_ds namespace hf_cuts_presel_dstar diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index cc96d59c074..c53e4c32f59 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -1820,7 +1820,7 @@ struct HfTrackIndexSkimCreator { template void applyPreselectionPhiDecay(const int binPt, T1 const& pVecTrack0, T1 const& pVecTrack1, T1 const& pVecTrack2, T2& cutStatus, T3& whichHypo, auto& isSelected) { - const double deltaMassMax = cut3Prong[hf_cand_3prong::DecayType::DsToKKPi].get(binPt, 4u); + const double deltaMassMax = cut3Prong[hf_cand_3prong::DecayType::DsToKKPi].get(binPt, 5u); if (TESTBIT(whichHypo[hf_cand_3prong::DecayType::DsToKKPi], 0)) { const double mass2PhiKKPi = RecoDecay::m2(std::array{pVecTrack0, pVecTrack1}, std::array{arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][0][0], arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][0][1]}); if (mass2PhiKKPi > (MassPhi + deltaMassMax) * (MassPhi + deltaMassMax) || mass2PhiKKPi < (MassPhi - deltaMassMax) * (MassPhi - deltaMassMax)) { @@ -1836,7 +1836,7 @@ struct HfTrackIndexSkimCreator { if (whichHypo[hf_cand_3prong::DecayType::DsToKKPi] == 0) { CLRBIT(isSelected, hf_cand_3prong::DecayType::DsToKKPi); if (config.debug) { - cutStatus[hf_cand_3prong::DecayType::DsToKKPi][4] = false; + cutStatus[hf_cand_3prong::DecayType::DsToKKPi][5] = false; } } } @@ -1848,7 +1848,7 @@ struct HfTrackIndexSkimCreator { /// \param isIdentifiedPidTrack0 is the flag that tells if the track 0 has been tagged as a proton /// \param isIdentifiedPidTrack2 is the flag that tells if the track 2 has been tagged as a proton /// \param cutStatus is a 2D array with outcome of each selection (filled only in debug mode) - /// \param whichHypo information of the mass hypoteses that were selected + /// \param whichHypo information of the mass hypotheses that were selected /// \param isSelected is a bitmap with selection outcome template void applyPreselection3Prong(T2 const& pVecTrack0, T2 const& pVecTrack1, T2 const& pVecTrack2, const auto isIdentifiedPidTrack0, const auto isIdentifiedPidTrack2, T3& cutStatus, T4& whichHypo, auto& isSelected) @@ -1889,7 +1889,7 @@ struct HfTrackIndexSkimCreator { } // invariant mass - if ((config.debug || TESTBIT(isSelected, iDecay3P))) { + if (config.debug || TESTBIT(isSelected, iDecay3P)) { const double minMass = cut3Prong[iDecay3P].get(binPt, 0u); const double maxMass = cut3Prong[iDecay3P].get(binPt, 1u); if (minMass >= 0. && maxMass > 0.) { // no need to check isSelected but to avoid mistakes @@ -2000,7 +2000,7 @@ struct HfTrackIndexSkimCreator { /// \param cutStatus is a 2D array with outcome of each selection (filled only in debug mode) /// \param isSelected ia s bitmap with selection outcome template - void applySelection3Prong(const T1& pVecCand, const T2& secVtx, const T3& primVtx, T4& cutStatus, auto& isSelected) + void applySelection3Prong(const T1& pVecCand, const std::array& ptProngs, const T2& secVtx, const T3& primVtx, T4& cutStatus, auto& isSelected) { if (config.debug || isSelected > 0) { @@ -2029,7 +2029,7 @@ struct HfTrackIndexSkimCreator { } // decay length - if ((config.debug || TESTBIT(isSelected, iDecay3P))) { + if (config.debug || TESTBIT(isSelected, iDecay3P)) { const auto decayLength = RecoDecay::distance(primVtx, secVtx); if (decayLength < cut3Prong[iDecay3P].get(binPt, 3u)) { // 3u == decLenIndex[iDecay3P] CLRBIT(isSelected, iDecay3P); @@ -2038,6 +2038,17 @@ struct HfTrackIndexSkimCreator { } } } + + // prong pT + if (config.debug || TESTBIT(isSelected, iDecay3P)) { + const auto ptProngMin = cut3Prong[iDecay3P].get(binPt, 4u); // 4u == ptProngMinIndex[iDecay3P] + if (ptProngs[0] < ptProngMin || ptProngs[1] < ptProngMin || ptProngs[2] < ptProngMin) { + CLRBIT(isSelected, iDecay3P); + if (config.debug) { + cutStatus[iDecay3P][4] = false; + } + } + } } } } @@ -2784,7 +2795,8 @@ struct HfTrackIndexSkimCreator { const auto pVecCandProng3Pos = RecoDecay::pVec(pvec0, pvec1, pvec2); // 3-prong selections after secondary vertex - applySelection3Prong(pVecCandProng3Pos, secondaryVertex3, pvRefitCoord3Prong2Pos1Neg, cutStatus3Prong, isSelected3ProngCand); + const std::array ptProngs{trackPos1.pt(), trackNeg1.pt(), trackPos2.pt()}; + applySelection3Prong(pVecCandProng3Pos, ptProngs, secondaryVertex3, pvRefitCoord3Prong2Pos1Neg, cutStatus3Prong, isSelected3ProngCand); std::array, kN3ProngDecaysUsedMlForHfFilters> mlScores3Prongs; if (config.applyMlForHfFilters) { @@ -3059,7 +3071,8 @@ struct HfTrackIndexSkimCreator { const auto pVecCandProng3Neg = RecoDecay::pVec(pvec0, pvec1, pvec2); // 3-prong selections after secondary vertex - applySelection3Prong(pVecCandProng3Neg, secondaryVertex3, pvRefitCoord3Prong1Pos2Neg, cutStatus3Prong, isSelected3ProngCand); + const std::array ptProngs{trackPos1.pt(), trackNeg1.pt(), trackNeg2.pt()}; + applySelection3Prong(pVecCandProng3Neg, ptProngs, secondaryVertex3, pvRefitCoord3Prong1Pos2Neg, cutStatus3Prong, isSelected3ProngCand); std::array, kN3ProngDecaysUsedMlForHfFilters> mlScores3Prongs{}; if (config.applyMlForHfFilters) { From 0214d62cf8a63975b99af94bc52700b98cd7967a Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Wed, 6 May 2026 14:07:44 +0200 Subject: [PATCH 061/449] [PWGHF] add THnSparse with the charm-bulk correlation for the v0 pt in taskPtFlucCharmHadrons (#15941) Co-authored-by: Copilot Co-authored-by: ALICE Action Bot --- PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx | 317 ++++++++++++++------- 1 file changed, 216 insertions(+), 101 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx index d0695616c84..f705e0ea31d 100644 --- a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx @@ -13,6 +13,8 @@ /// \brief Analysis task for charm hadron pt fluctuation /// /// \author Prottay Das, prottay.das@cern.ch +/// \author Wu Chuntai, UNIPD, CCNU, and INFN Padova +/// \author Andrea Rossi, INFN Padova #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" @@ -37,6 +39,7 @@ #include #include +#include #include #include #include @@ -57,6 +60,12 @@ enum DecayChannel { DplusToPiKPi = 0, D0ToPiK, D0ToKPi }; +enum CandD0Type { PureD0 = 0, + PureD0bar, + ReflectedD0, + ReflectedD0bar +}; + struct HfTaskPtFlucCharmHadrons { Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; @@ -64,6 +73,7 @@ struct HfTaskPtFlucCharmHadrons { Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP computation"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> classMl{"classMl", {0, 2}, "Indices of BDT scores to be stored. Two indexes max."}; + Configurable saveCharmBulkCorrelations{"saveCharmBulkCorrelations", false, "Flag to save charm-bulk correlations in THnSparse"}; Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; Configurable cfgITSbarrel{"cfgITSbarrel", 1, "Number of ITS inner barrel"}; @@ -77,6 +87,7 @@ struct HfTaskPtFlucCharmHadrons { Configurable etaAMax{"etaAMax", 0.0f, "A: negative eta max (0)"}; Configurable etaBMin{"etaBMin", 0.4f, "B: positive eta min (eta_min)"}; // or set from etaMinGap in code Configurable etaBMax{"etaBMax", 0.8f, "B: positive eta max"}; + Configurable etaTrkMax{"etaTrkMax", 0.8f, "Track eta max"}; Configurable ptTrkMin{"ptTrkMin", 0.2f, "Track pT min for (charged hadrons)"}; Configurable ptTrkMax{"ptTrkMax", 2.0f, "Track pT max for (charged hadrons)"}; @@ -107,7 +118,7 @@ struct HfTaskPtFlucCharmHadrons { Filter filterSelectDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag; Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; - + Filter filterSelectTracks = (nabs(aod::track::eta) < etaTrkMax) && (aod::track::pt > ptTrkMin) && (aod::track::pt < ptTrkMax) && (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); Partition selectedD0ToPiKWMl = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag; Partition selectedD0ToKPiWMl = aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; @@ -118,8 +129,15 @@ struct HfTaskPtFlucCharmHadrons { ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0}, "Candidate pT axis"}; ConfigurableAxis axisCent{"axisCent", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Centrality axis"}; ConfigurableAxis axisSign{"axisSign", {VARIABLE_WIDTH, -1.0, 1.0}, "Sign axis"}; - ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; + ConfigurableAxis axisMlOne{"axisMlOne", {1000, 0., 1.}, ""}; + ConfigurableAxis axisMlTwo{"axisMlTwo", {100, 0., 1.}, ""}; + ConfigurableAxis axisCandEta{"axisCandEta", {20, -1., 1.}, ""}; + ConfigurableAxis axisMPtTrkA{"axisMPtTrkA", {50, 0., 5.}, ""}; + ConfigurableAxis axisMPtTrkB{"axisMPtTrkB", {50, 0., 5.}, ""}; + ConfigurableAxis axisPtCandProduct{"axisPtCandProduct", {50, 0., 50.}, ""}; + ConfigurableAxis axisPtTrkProduct{"axisPtTrkProduct", {50, 0., 25.}, ""}; + ConfigurableAxis axisNTrkA{"axisNTrkA", {2000, 0., 2000.}, ""}; + ConfigurableAxis axisNTrkB{"axisNTrkB", {2000, 0., 2000.}, ""}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -139,8 +157,15 @@ struct HfTaskPtFlucCharmHadrons { const AxisSpec aPt{axisPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec aCent{axisCent, "Centrality"}; const AxisSpec aSign{axisSign, "Sign"}; - const AxisSpec thnAxisMlOne{thnConfigAxisMlOne, "Bkg score"}; - const AxisSpec thnAxisMlTwo{thnConfigAxisMlTwo, "FD score"}; + const AxisSpec aMlOne{axisMlOne, "Bkg score"}; + const AxisSpec aMlTwo{axisMlTwo, "FD score"}; + const AxisSpec aCandEta{axisCandEta, "Eta"}; + const AxisSpec aMPtTrkA{axisMPtTrkA, "Mean pT of tracks in subevent A (GeV/#it{c})"}; + const AxisSpec aMPtTrkB{axisMPtTrkB, "Mean pT of tracks in subevent B (GeV/#it{c})"}; + const AxisSpec aPtCandProduct{axisPtCandProduct, "#it{p}_{T}^{cand} * <#it{p}_{T}>^{trks} (GeV^{2}/#it{c}^{2})"}; + const AxisSpec aPtTrkProduct{axisPtTrkProduct, "#it{p}_{T}^{trks}(A) * #it{p}_{T}^{trks}(B) (GeV^{2}/#it{c}^{2})"}; + const AxisSpec aNTrkA{axisNTrkA, "N_{tracks} in subevent A"}; + const AxisSpec aNTrkB{axisNTrkB, "N_{tracks} in subevent B"}; // Event-level accumulators (charged hadrons only!) registry.add("hEvents", "events vs cent", HistType::kTH1F, {aCent}, true); @@ -155,53 +180,104 @@ struct HfTaskPtFlucCharmHadrons { registry.add("pNB", " vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); // Candidate mass distributions - registry.add("hD_mass", "D candidate mass (weight=1)", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); - registry.add("hD_f", "hD_f", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); - registry.add("hD_f_wPtB", "hD_f_wPtB", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); + registry.add("hD_mass", "D candidate mass (weight=1)", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo}, true); + registry.add("hD_f", "hD_f", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo}, true); + registry.add("hD_f_wPtB", "hD_f_wPtB", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo}, true); + + // charm-bulk correlations (optional) + if (saveCharmBulkCorrelations) { + registry.add("hCharmBulkCorrelations", "Charm-bulk correlations", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo, aCandEta, aMPtTrkA, aMPtTrkB, aPtCandProduct}, true); + registry.add("hMeanPtTrkAllColls", "Mean pT of charged hadrons for all collisions", HistType::kTHnSparseF, {aCent, aMPtTrkA, aMPtTrkB, aPtTrkProduct, aNTrkA, aNTrkB}, true); + } + + hfEvSel.addHistograms(registry); // collision monitoring ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); }; // end init - /// Get the centrality - /// \param collision is the collision with the centrality information - double getCentrality(Colls::iterator const& collision) + // --------------------------------------------------------------------------- + // Helper functions + // --------------------------------------------------------------------------- + /// Check event selections for collision and fill event selection histograms, and revalculate centrality + /// \param collision is the collision + template + bool isSelectedHfCollision(Coll const& collision, float& cent) + { + o2::hf_evsel::HfCollisionRejectionMask collRejMask{}; + if (centEstimator == CentralityEstimator::FT0A) { + collRejMask = hfEvSel.getHfCollisionRejectionMask(collision, cent, ccdb, registry); + } else if (centEstimator == CentralityEstimator::FT0C) { + collRejMask = hfEvSel.getHfCollisionRejectionMask(collision, cent, ccdb, registry); + } else if (centEstimator == CentralityEstimator::FT0M) { + collRejMask = hfEvSel.getHfCollisionRejectionMask(collision, cent, ccdb, registry); + } else if (centEstimator == CentralityEstimator::FV0A) { + collRejMask = hfEvSel.getHfCollisionRejectionMask(collision, cent, ccdb, registry); + } else { + LOG(fatal) << "Centrality estimator not recognized for collision selection"; + } + hfEvSel.fillHistograms(collision, collRejMask, cent); + return collRejMask == 0; + } + + /// Get candidate mass + template + std::pair getCandMassAndSign(const CandT& cand, DecayChannel channel, Trk const& /*tracks*/) { - double cent = -999.; - switch (centEstimator) { - case CentralityEstimator::FV0A: - cent = collision.centFV0A(); - break; - case CentralityEstimator::FT0M: - cent = collision.centFT0M(); - break; - case CentralityEstimator::FT0A: - cent = collision.centFT0A(); - break; - case CentralityEstimator::FT0C: - cent = collision.centFT0C(); - break; - default: - LOG(warning) << "Centrality estimator not valid. Possible values are V0A, T0M, T0A, T0C. Fallback to V0A"; - cent = collision.centFV0A(); - break; + if constexpr (std::is_same_v) { + return {HfHelper::invMassDplusToPiKPi(cand), cand.template prong0_as().sign()}; } - return cent; + if constexpr (std::is_same_v) { + if (channel == DecayChannel::D0ToPiK) { + return {HfHelper::invMassD0ToPiK(cand), cand.isSelD0bar() ? CandD0Type::ReflectedD0bar : CandD0Type::PureD0}; + } + if (channel == DecayChannel::D0ToKPi) { + return {HfHelper::invMassD0barToKPi(cand), cand.isSelD0() ? CandD0Type::ReflectedD0 : CandD0Type::PureD0bar}; + } + } + return {0., 0.}; // default return value for unsupported types } template - bool selectionTrack(const T& candidate) const + bool selectionTrack(const T& track) const { - if (!(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster.value && candidate.tpcNClsFound() > cfgTPCcluster.value && candidate.itsNClsInnerBarrel() >= cfgITSbarrel.value && std::abs(candidate.dcaXY()) < cfgCutDCAxy.value && std::abs(candidate.dcaZ()) < cfgCutDCAz.value)) { + if (!(track.isGlobalTrack() && track.isPVContributor() && track.itsNCls() > cfgITScluster.value && track.tpcNClsFound() > cfgTPCcluster.value && track.itsNClsInnerBarrel() >= cfgITSbarrel.value)) { return false; } return true; } - // ------------------------- + /// remove candidate daughters from the mean pT of tracks in A and B (if they are in the respective subevent) + template + float removeDaughtersFromMeanPt(const CandT& cand, float rawMeanPt, int n, const std::vector& trkIDs) + { + int removedCount = 0; + float removedSumPt = 0.f; + auto removeDaug = [&](int daugID, float daugPt) { + if (std::binary_search(trkIDs.begin(), trkIDs.end(), daugID)) { + removedSumPt += daugPt; + ++removedCount; + } + }; + if constexpr (Channel == DecayChannel::DplusToPiKPi) { + removeDaug(cand.prong0Id(), cand.ptProng0()); + removeDaug(cand.prong1Id(), cand.ptProng1()); + removeDaug(cand.prong2Id(), cand.ptProng2()); + } else if constexpr (Channel == DecayChannel::D0ToPiK || Channel == DecayChannel::D0ToKPi) { + removeDaug(cand.prong0Id(), cand.ptProng0()); + removeDaug(cand.prong1Id(), cand.ptProng1()); + } + if (removedCount > 0) { + double totalSum = static_cast(rawMeanPt) * n; + return static_cast((totalSum - removedSumPt) / (n - removedCount)); + } + return rawMeanPt; + } + + // --------------------------------------------------------------------------- // Event-wise mean pT from charged hadron tracks - // ------------------------- + // --------------------------------------------------------------------------- template std::pair computeMeanPtCharged(Trk const& tracks, float etaMin, float etaMax) const { @@ -217,9 +293,6 @@ struct HfTaskPtFlucCharmHadrons { continue; } float pt = trk.pt(); - if (pt < ptTrkMin.value || pt >= ptTrkMax.value) { - continue; - } sumPt += pt; ++n; } @@ -277,109 +350,151 @@ struct HfTaskPtFlucCharmHadrons { ml2 >= mlTwoMin.value && ml2 < mlTwoMax.value); } - /// Compute the scalar product - /// \param collision is the collision with the Q vector information and event plane - /// \param candidates are the selected candidates + /// Compute the mean pT of the event using charged tracks in two eta-separated subevents, and correlate with D candidates + /// \param collision is the collision with centrality and event selection + /// \param candidates are the D candidates to correlate with the mean pT of the event + /// \param tracks are the tracks used to compute the mean pT of the event template void runPtFlucAnalysis(Colls::iterator const& collision, T1 const& candidates, Trk const& tracks) { - float cent = getCentrality(collision); - if (cent < centralityMin || cent > centralityMax) { + float cent{0.f}; + if (!isSelectedHfCollision(collision, cent)) { return; } // Compute in two eta-separated subevents using CHARGED tracks only - auto [meanPtA, nA] = computeMeanPtCharged(tracks, etaAMin.value, etaAMax.value); - auto [meanPtB, nB] = computeMeanPtCharged(tracks, etaBMin.value, etaBMax.value); + auto [RawMeanPtA, nA] = computeMeanPtCharged(tracks, etaAMin.value, etaAMax.value); + auto [RawMeanPtB, nB] = computeMeanPtCharged(tracks, etaBMin.value, etaBMax.value); // QA registry.fill(HIST("pNA"), cent, static_cast(nA)); registry.fill(HIST("pNB"), cent, static_cast(nB)); - if (!std::isfinite(meanPtA) || !std::isfinite(meanPtB)) { + if (!std::isfinite(RawMeanPtA) || !std::isfinite(RawMeanPtB)) { return; } registry.fill(HIST("hEvents"), cent, 1.f); - registry.fill(HIST("pMeanPtA"), cent, meanPtA); - registry.fill(HIST("pMeanPtB"), cent, meanPtB); - registry.fill(HIST("pMeanPtAmeanPtB"), cent, meanPtA * meanPtB); - - int nDcandTotA = 0; + registry.fill(HIST("pMeanPtA"), cent, RawMeanPtA); + registry.fill(HIST("pMeanPtB"), cent, RawMeanPtB); + registry.fill(HIST("pMeanPtAmeanPtB"), cent, RawMeanPtA * RawMeanPtB); + if (saveCharmBulkCorrelations) { + registry.fill(HIST("hMeanPtTrkAllColls"), cent, RawMeanPtA, RawMeanPtB, RawMeanPtA * RawMeanPtB, nA, nB); - for (const auto& cand : candidates) { - if (!passCandInA(cand)) { - continue; - } + std::vector trkIDA; + std::vector trkIDB; - // compute ML exactly like numerator - const auto [ml1, ml2] = getMlScores(cand); + trkIDA.reserve(tracks.size() / 2); + trkIDB.reserve(tracks.size() / 2); - // apply same ML cut - if (!passMlCut(ml1, ml2)) { - continue; - } - float pt = cand.pt(); - if (pt < ptTrkMinD.value || pt >= ptTrkMaxD.value) { - continue; + // collect track IDs in A and B + for (const auto& trk : tracks) { + if (!selectionTrack(trk)) { + continue; + } + float eta = trk.eta(); + if (eta > etaAMin.value && eta < etaAMax.value) { + trkIDA.push_back(trk.globalIndex()); + } else if (eta > etaBMin.value && eta < etaBMax.value) { + trkIDB.push_back(trk.globalIndex()); + } } - ++nDcandTotA; - } + std::sort(trkIDA.begin(), trkIDA.end()); + std::sort(trkIDB.begin(), trkIDB.end()); - if (nDcandTotA <= 0) { - return; // cannot build fraction - } + for (const auto& cand : candidates) { + // apply ML selection + auto [ml1, ml2] = getMlScores(cand); + if (!passMlCut(ml1, ml2)) { + continue; + } - registry.fill(HIST("hEventsD"), cent, 1.f); - const float invND = 1.f / static_cast(nDcandTotA); + // remove the daughters from the mean pT of tracks and calculate pt product + float eta = cand.eta(); + float pt = cand.pt(); + + float candPtProduct{0.f}; + float meanPtA{0.f}; + float meanPtB{0.f}; + if (eta > etaAMin.value && eta < etaAMax.value) { + meanPtB = removeDaughtersFromMeanPt(cand, RawMeanPtB, nB, trkIDB); + meanPtA = RawMeanPtA; // no need to remove daughters from A if candidate is in A + candPtProduct = pt * meanPtB; + } else if (eta > etaBMin.value && eta < etaBMax.value) { + meanPtA = removeDaughtersFromMeanPt(cand, RawMeanPtA, nA, trkIDA); + meanPtB = RawMeanPtB; // no need to remove daughters from B if candidate is in B + candPtProduct = pt * meanPtA; + } - for (const auto& candidate : candidates) { - if (!passCandInA(candidate)) { - continue; - } + // get candidate mass and sign + auto [invMass, sign] = getCandMassAndSign(cand, Channel, tracks); - // ML first (same definition) - const auto [ml1, ml2] = getMlScores(candidate); - if (!passMlCut(ml1, ml2)) { - continue; + // fill charm-bulk correlation thnsparse + registry.fill(HIST("hCharmBulkCorrelations"), invMass, cent, pt, sign, ml1, ml2, eta, meanPtA, meanPtB, candPtProduct); } + } else { + int nDcandTotA = 0; + for (const auto& cand : candidates) { + if (!passCandInA(cand)) { + continue; + } + + // compute ML exactly like numerator + const auto [ml1, ml2] = getMlScores(cand); - // compute mass - float massCand = 0.; - float signCand = 0.; - if constexpr (std::is_same_v) { - massCand = HfHelper::invMassDplusToPiKPi(candidate); - auto trackprong0 = candidate.template prong0_as(); - signCand = trackprong0.sign(); - } else { - if constexpr (Channel == DecayChannel::D0ToPiK) { - massCand = HfHelper::invMassD0ToPiK(candidate); - signCand = candidate.isSelD0bar() ? 3 : 1; // 3: reflected D0bar, 1: pure D0 excluding reflected D0bar - } else if constexpr (Channel == DecayChannel::D0ToKPi) { - massCand = HfHelper::invMassD0barToKPi(candidate); - signCand = candidate.isSelD0() ? 3 : 2; // 3: reflected D0, 2: pure D0bar excluding reflected D0 + // apply same ML cut + if (!passMlCut(ml1, ml2)) { + continue; } + float pt = cand.pt(); + if (pt < ptTrkMinD.value || pt >= ptTrkMaxD.value) { + continue; + } + + ++nDcandTotA; } - const double ptCand = candidate.pt(); - if (ptCand < ptTrkMinD.value || ptCand >= ptTrkMaxD.value) { - continue; + if (nDcandTotA == 0) { + return; // cannot build fraction } - registry.fill(HIST("hD_mass"), massCand, cent, ptCand, signCand, ml1, ml2, 1.f); - registry.fill(HIST("hD_f"), massCand, cent, ptCand, signCand, ml1, ml2, invND); - registry.fill(HIST("hD_f_wPtB"), massCand, cent, ptCand, signCand, ml1, ml2, meanPtB * invND); + registry.fill(HIST("hEventsD"), cent, 1.f); + const float invND = 1.f / static_cast(nDcandTotA); + + for (const auto& candidate : candidates) { + if (!passCandInA(candidate)) { + continue; + } + + // ML first (same definition) + const auto [ml1, ml2] = getMlScores(candidate); + if (!passMlCut(ml1, ml2)) { + continue; + } + + // compute mass + auto [massCand, signCand] = getCandMassAndSign(candidate, Channel, tracks); + + const double ptCand = candidate.pt(); + if (ptCand < ptTrkMinD.value || ptCand >= ptTrkMaxD.value) { + continue; + } + + registry.fill(HIST("hD_mass"), massCand, cent, ptCand, signCand, ml1, ml2, 1.f); + registry.fill(HIST("hD_f"), massCand, cent, ptCand, signCand, ml1, ml2, invND); + registry.fill(HIST("hD_f_wPtB"), massCand, cent, ptCand, signCand, ml1, ml2, RawMeanPtB * invND); + } } - } + } // end runPtFlucAnalysis // D0 with ML void processD0Ml(Colls::iterator const& collision, CandD0DataWMl const& /*candidatesD0*/, - TracksWithExtra const& tracks) + soa::Filtered const& tracks) { auto candsD0ToPiKWMl = selectedD0ToPiKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsD0ToKPiWMl = selectedD0ToKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); @@ -391,7 +506,7 @@ struct HfTaskPtFlucCharmHadrons { // Dplus with ML void processDplusMl(Colls::iterator const& collision, CandDplusDataWMl const& candidatesDplus, - TracksWithExtra const& tracks) + soa::Filtered const& tracks) { runPtFlucAnalysis(collision, candidatesDplus, tracks); } From 6243aa7aadeedab73288f92b68d2dc07a18182cc Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Wed, 6 May 2026 16:39:54 +0200 Subject: [PATCH 062/449] [PWGCF] Fix in femto framework (#16124) --- PWGCF/Femto/Tasks/femtoPairEfficiency.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx index 49816c6b409..d3cffb80f0b 100644 --- a/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx +++ b/PWGCF/Femto/Tasks/femtoPairEfficiency.cxx @@ -486,8 +486,9 @@ struct FemtoPairEfficiency { { float mass1 = o2::analysis::femto::utils::getPdgMass(std::abs(TrackSel1.pdgCode.value)); float mass2 = o2::analysis::femto::utils::getPdgMass(std::abs(TrackSel2.pdgCode.value)); + bool foundPair = false; - for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsUpperIndexPolicy(tracks, tracks))) { + for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { bool order1 = checkTrackMC(p1, TrackSel1) && checkTrackMC(p2, TrackSel2) && std::abs(p1.pdgCode()) == std::abs(TrackSel1.pdgCode.value) && @@ -525,9 +526,9 @@ struct FemtoPairEfficiency { if (kstar > kStarMax.value) { continue; } - return true; + foundPair = true; } - return false; + return foundPair; } template From 34a8a7daff2145ec2c81ae32380ebe3207ccbf71 Mon Sep 17 00:00:00 2001 From: akyadav1963 <84583181+akyadav1963@users.noreply.github.com> Date: Wed, 6 May 2026 20:14:58 +0530 Subject: [PATCH 063/449] [PWGLF] Added tracktype axis for MC reco in pp and PbPb (#16125) Co-authored-by: ALICE Action Bot --- .../GlobalEventProperties/ptmultCorr.cxx | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx index 667a10519b1..e41a4055458 100644 --- a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx @@ -190,7 +190,7 @@ struct PtmultCorr { histos.add("hPbPbRecMCvtxz", "hPbPbRecMCvtxz", kTH1D, {axisVtxZ}, false); histos.add("hPbPbRecMCvtxzcent", "hPbPbRecMCvtxzcent", kTH2D, {axisVtxZ, centAxis}, false); histos.add("hPbPbRecMCcent", "hPbPbRecMCcent", kTH1D, {axisCent}, false); - histos.add("hPbPbRecMCdndpt", "hPbPbRecMCdndpt", kTHnSparseD, {axisVtxZ, centAxis, axisPt, axisPhi, axisRecTrkType}, false); + histos.add("hPbPbRecMCdndpt", "hPbPbRecMCdndpt", kTHnSparseD, {axisVtxZ, centAxis, axisPt, axisPhi, axisRecTrkType, axisTrackType}, false); histos.add("hPbPbEtaReso", "hPbPbEtaReso", kTH2D, {axisPt, axisDeltaPt}); } @@ -201,7 +201,7 @@ struct PtmultCorr { histos.add("hppGenMCAssoRecdndpt", "hppGenMCAssoRecdndpt", kTHnSparseD, {axisVtxZ, axisPt, axisPhi, axisGenTrkType, axisGenPtVary}, false); histos.add("hppRecMCvtxz", "hppRecMCvtxz", kTH1D, {axisVtxZ}, false); - histos.add("hppRecMCdndpt", "hppRecMCdndpt", kTHnSparseD, {axisVtxZ, axisPt, axisPhi, axisRecTrkType}, false); + histos.add("hppRecMCdndpt", "hppRecMCdndpt", kTHnSparseD, {axisVtxZ, axisPt, axisPhi, axisRecTrkType, axisTrackType}, false); histos.add("hppEtaReso", "hppEtaReso", kTH2D, {axisPt, axisDeltaPt}); } @@ -445,14 +445,20 @@ struct PtmultCorr { if (!isTrackSelected(Rectrack)) { continue; } - histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll)); + auto trkType = Rectrack.hasTPC() ? kGlobalonly : kITSonly; + + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll), kGlobalplusITS); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll), trkType); + if (Rectrack.has_mcParticle()) { int pid = 0; auto mcpart = Rectrack.mcParticle(); histos.fill(HIST("hPbPbEtaReso"), Rectrack.pt(), Rectrack.pt() - mcpart.pt()); - histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc)); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc), kGlobalplusITS); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc), trkType); if (mcpart.isPhysicalPrimary()) { - histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary)); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary), kGlobalplusITS); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary), trkType); switch (std::abs(mcpart.pdgCode())) { case PDG_t::kPiPlus: pid = kRecoPion; @@ -480,9 +486,11 @@ struct PtmultCorr { pid = kRecoFake; } mclabels.push_back(Rectrack.mcParticleId()); - histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(pid)); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(pid), kGlobalplusITS); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), mcpart.pt(), mcpart.phi(), static_cast(pid), trkType); } else { - histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg)); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg), kGlobalplusITS); + histos.fill(HIST("hPbPbRecMCdndpt"), RecCol.posZ(), RecCol.centFT0C(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg), trkType); } } // track (mcrec) loop } // collision loop @@ -551,14 +559,18 @@ struct PtmultCorr { if (!isTrackSelected(Rectrack)) { continue; } - histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll)); + auto trkType = Rectrack.hasTPC() ? kGlobalonly : kITSonly; + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll), kGlobalplusITS); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoAll), trkType); if (Rectrack.has_mcParticle()) { int pid = 0; auto mcpart = Rectrack.mcParticle(); histos.fill(HIST("hppEtaReso"), Rectrack.pt(), Rectrack.pt() - mcpart.pt()); - histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc)); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc), kGlobalplusITS); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoHasmc), trkType); if (mcpart.isPhysicalPrimary()) { - histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary)); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary), kGlobalplusITS); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(kRecoPrimary), trkType); switch (std::abs(mcpart.pdgCode())) { case PDG_t::kPiPlus: pid = kRecoPion; @@ -586,9 +598,11 @@ struct PtmultCorr { pid = kRecoFake; } mclabels.push_back(Rectrack.mcParticleId()); - histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(pid)); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(pid), kGlobalplusITS); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), mcpart.pt(), mcpart.phi(), static_cast(pid), trkType); } else { - histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg)); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg), kGlobalplusITS); + histos.fill(HIST("hppRecMCdndpt"), RecCol.posZ(), Rectrack.pt(), Rectrack.phi(), static_cast(kRecoBkg), trkType); } } // track (mcrec) loop } // collision loop From c78a1b80c6447413e24e3a7c669bf0f049cc3c49 Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Wed, 6 May 2026 16:51:50 +0200 Subject: [PATCH 064/449] [PWGHF] taskFlow.cxx : correction of a typo, add QA plots, add new correlation axis (#16122) --- PWGHF/HFC/Tasks/taskFlow.cxx | 181 ++++++++++++++++++++++++++++------- 1 file changed, 144 insertions(+), 37 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 437fe9dcad9..f41fd055852 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -202,6 +202,7 @@ struct HfTaskFlow { struct : ConfigurableGroup { std::string prefix = "ConfigTask_group"; Configurable centralityBinsForMc{"centralityBinsForMc", false, "falsce = OFF, true = ON for data like multiplicity/centrality bins for MC steps"}; + Configurable doEtaDependentFlow{"doEtaDependentFlow", false, "Flag to know if eta dependent flow should be done"}; Configurable doHeavyFlavor{"doHeavyFlavor", false, "Flag to know we in the heavy flavor case or not"}; Configurable doReferenceFlow{"doReferenceFlow", false, "Flag to know if reference flow should be done"}; Configurable isReadoutCenter{"isReadoutCenter", false, "Enable Readout Center"}; @@ -379,6 +380,7 @@ struct HfTaskFlow { ConfigurableAxis axisMass{"axisMass", {1, 1.5848, 2.1848}, "axis of invariant mass of candidates"}; ConfigurableAxis binsMixingMultiplicity{"binsMixingMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity bins for event mixing"}; ConfigurableAxis binsMixingVertex{"binsMixingVertex", {20, -10, 10}, "vertex bins for event mixing"}; + ConfigurableAxis axisNClusters{"axisNClusters", {9, 1, 10}, "axis for number of clusters of MFT tracks"}; ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {1, -1.0, 1.0}, "eta axis for efficiency histograms"}; ConfigurableAxis axisEtaAssociated{"axisEtaAssociated", {48, -4, -2}, "eta axis for MFT histograms"}; ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {48, -1, 1}, "eta axis for TPC histograms"}; @@ -465,6 +467,8 @@ struct HfTaskFlow { } registry.add("Data/Mft/hPtMft", "", {HistType::kTH1D, {configAxis.axisPt}}); + registry.add("Data/Mft/hPtVsClustersLTF", "", {HistType::kTH2D, {configAxis.axisPt, configAxis.axisNClusters}}); + registry.add("Data/Mft/hPtVsClustersCA", "", {HistType::kTH2D, {configAxis.axisPt, configAxis.axisNClusters}}); registry.add("Data/Mft/hNMftTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); registry.add("Data/Mft/hNBestCollisionFwd", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); } @@ -547,6 +551,12 @@ struct HfTaskFlow { {configAxis.axisMultiplicity, "multiplicity"}, {configAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, {configAxis.axisVertex, "z-vtx (cm)"}}; + std::vector const corrAxisEta = {{configAxis.axisDeltaEta, "#Delta#eta"}, + {configAxis.axisEtaAssociated, "#eta_{associated}"}, + {configAxis.axisEtaTrigger, "#eta_{trigger}"}, + {configAxis.axisMultiplicity, "multiplicity"}, + {configAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, + {configAxis.axisVertex, "z-vtx (cm)"}}; std::vector const effAxis = {{configAxis.axisEtaEfficiency, "#eta"}, {configAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, {configAxis.axisVertexEfficiency, "z-vtx (cm)"}}; @@ -562,8 +572,13 @@ struct HfTaskFlow { if (doprocessSameTpcTpcChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } if (doprocessSameTpcTpcD0Ch) { @@ -588,8 +603,13 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } if (doprocessSameTpcMftD0Ch || doprocessSameTpcMftD0ChReassociated) { @@ -615,8 +635,13 @@ struct HfTaskFlow { if (doprocessSameTpcFv0aChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } if (doprocessSameTpcFv0aD0Ch) { @@ -642,8 +667,13 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } // ========================= @@ -655,8 +685,13 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } if (doprocessSameTpcFt0aD0Ch) { @@ -687,8 +722,13 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } // ========================= @@ -700,8 +740,13 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } if (doprocessSameTpcFt0cD0Ch) { @@ -731,8 +776,13 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + if (!configTask.doEtaDependentFlow) { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else { + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } } } // End of init() function @@ -939,7 +989,7 @@ struct HfTaskFlow { LOGF(fatal, "Cor Index %d out of range", fitType); } registry.fill(HIST("Data/FT0Amp"), rID, amplitude); - amplitude = amplitude / cstFT0RelGain[iCh]; + amplitude = amplitude / cstFT0RelGain[id]; registry.fill(HIST("Data/FT0AmpCorr"), rID, amplitude); } @@ -1153,6 +1203,7 @@ struct HfTaskFlow { if (mftTrack.isCA()) { if (fillHistograms) { registry.fill(HIST("Data/Mft/hMftTracksSelection"), MftTrackSelectionStep::IsCA); + registry.fill(HIST("Data/Mft/hPtVsClustersCA"), mftTrack.pt(), mftTrack.nClusters()); } if (configMft.useOnlyLTFTracks) { @@ -1162,6 +1213,7 @@ struct HfTaskFlow { } else { if (fillHistograms) { registry.fill(HIST("Data/Mft/hMftTracksSelection"), MftTrackSelectionStep::IsLTF); + registry.fill(HIST("Data/Mft/hPtVsClustersLTF"), mftTrack.pt(), mftTrack.nClusters()); } if (configMft.useOnlyCATracks) { @@ -1242,8 +1294,12 @@ struct HfTaskFlow { } // fill single-track distributions - if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + if (!fillingHFcontainer) { // if not HF-h case + if (!configTask.doEtaDependentFlow) { // if not eta-differential flow, fill vs pt, otherwise fill vs eta + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + } else { + target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + } } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1370,8 +1426,13 @@ struct HfTaskFlow { if (!fillingHFcontainer) { // fill pair correlations - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } } else { target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); @@ -1445,7 +1506,11 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + if (!configTask.doEtaDependentFlow) { + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + } else { + target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + } } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1556,8 +1621,13 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } } else { target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); @@ -1635,7 +1705,11 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + if (!configTask.doEtaDependentFlow) { + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + } else { + target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + } } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1697,8 +1771,13 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } } else { target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); @@ -1745,8 +1824,13 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - amplitude * triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } } else { target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, amplitude * triggerWeight * associatedWeight); @@ -1837,7 +1921,11 @@ struct HfTaskFlow { float phi1 = reassociatedMftTrack.phi(); o2::math_utils::bringTo02Pi(phi1); - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + if (!configTask.doEtaDependentFlow) { + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + } else { + target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + } // FILL QA PLOTS for trigger particle if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1861,8 +1949,13 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } // FILL QA PLOTS for associated particle if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1894,8 +1987,13 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - amplitude * triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } // FILL QA PLOTS for associated particle if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1927,7 +2025,11 @@ struct HfTaskFlow { auto phiA = getPhiFT0(channelIdA, isFT0A); auto etaA = getEtaFT0(channelIdA, isFT0A); - target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, amplitude * triggerWeight); + if (!configTask.doEtaDependentFlow) { + target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, amplitude * triggerWeight); + } else { + target->getTriggerHist()->Fill(step, etaA, multiplicity, posZ, amplitude * triggerWeight); + } if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { fillTriggerQa(multiplicity, etaA, phiA, 0.f); @@ -1943,8 +2045,13 @@ struct HfTaskFlow { auto etaC = getEtaFT0(channelIdC, isFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); - target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, - amplitude * triggerWeight * associatedWeight); + if (!configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, etaA - etaC, etaC, etaA, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { fillAssociatedQa(multiplicity, etaC, phiC); From b73ee48f45036e3bb2b6d38466290d199deb3635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Wed, 6 May 2026 17:17:43 +0200 Subject: [PATCH 065/449] [PWGDQ] Fix includes (#16089) --- PWGDQ/Core/AnalysisCut.h | 1 + PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 2 ++ PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 1 + PWGDQ/Tasks/qaMatching.cxx | 6 ++---- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Core/AnalysisCut.h b/PWGDQ/Core/AnalysisCut.h index f5144227868..990de29abb4 100644 --- a/PWGDQ/Core/AnalysisCut.h +++ b/PWGDQ/Core/AnalysisCut.h @@ -22,6 +22,7 @@ #include +#include #include #include diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index 59d0d15930d..bebfe8ac6a0 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -25,6 +25,7 @@ #include "Common/Core/PID/PIDTOFParamService.h" #include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" @@ -59,6 +60,7 @@ #include +#include #include #include #include diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx index bf2f976da91..9df32a2871a 100644 --- a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -52,6 +52,7 @@ #include +#include #include #include #include diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 0aa06352326..5c831c19772 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -57,9 +58,7 @@ #include #include #include -#include - -#include +#include #include #include @@ -67,7 +66,6 @@ #include #include #include -#include #include #include #include From 4f831d5f4026ff4437990be2ddfaa2f029acfe58 Mon Sep 17 00:00:00 2001 From: nivram-phy Date: Wed, 6 May 2026 17:37:04 +0200 Subject: [PATCH 066/449] [PWGDQ] make qaMatching AO2D index merger-safe (#16129) Co-authored-by: Niveditha Ramasubramanian --- PWGDQ/Tasks/qaMatching.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 5c831c19772..9455bbc86c7 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -119,12 +119,13 @@ DECLARE_SOA_TABLE(QaMatchingEvents, "AOD", "QAMEVT", namespace qamatching { -DECLARE_SOA_INDEX_COLUMN_FULL(ReducedEvent, reducedEvent, int32_t, o2::aod::QaMatchingEvents, ""); +DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(ReducedEvent, reducedEvent, int32_t, o2::aod::QaMatchingEvents, "QAMEVTs", ""); } // namespace qamatching namespace o2::aod { DECLARE_SOA_TABLE(QaMatchingMCHTrack, "AOD", "QAMCHTRK", + o2::soa::Index<>, qamatching::ReducedEventId, qamatching::TrackId, qamatching::TrackType, @@ -140,6 +141,7 @@ DECLARE_SOA_TABLE(QaMatchingMCHTrack, "AOD", "QAMCHTRK", qamatching::PyAtVtx, qamatching::PzAtVtx); DECLARE_SOA_TABLE(QaMatchingCandidates, "AOD", "QAMCAND", + o2::soa::Index<>, qamatching::ReducedEventId, qamatching::MatchLabel, qamatching::TrackId, From e4eaee9b6f057b7869ced0a6ce206afdc1d13f77 Mon Sep 17 00:00:00 2001 From: creetz16 <79141119+creetz16@users.noreply.github.com> Date: Wed, 6 May 2026 17:42:53 +0200 Subject: [PATCH 067/449] [PWGLF] Add mother MC label to decay3bodybuilder output table (#16126) --- PWGLF/DataModel/Vtx3BodyTables.h | 51 +++++++++---------- .../Nuspex/decay3bodybuilder.cxx | 35 +++++-------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h index e18efbe2ddc..6f59323efe3 100644 --- a/PWGLF/DataModel/Vtx3BodyTables.h +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -112,31 +112,30 @@ DECLARE_SOA_COLUMN(CovDeuteron, covDeuteron, float[21]); //! covariance matrix e DECLARE_SOA_COLUMN(VtxCovMat, vtxCovMat, float[21]); //! covariance matrix elements of candidate // Monte Carlo info -DECLARE_SOA_COLUMN(GenPx, genPx, float); // generated Px of the hypertriton in GeV/c -DECLARE_SOA_COLUMN(GenPy, genPy, float); // generated Py of the hypertriton in GeV/c -DECLARE_SOA_COLUMN(GenPz, genPz, float); // generated Pz of the hypertriton in GeV/c -DECLARE_SOA_COLUMN(GenX, genX, float); // generated decay vtx position X of the hypertriton -DECLARE_SOA_COLUMN(GenY, genY, float); // generated decay vtx position Y of the hypertriton -DECLARE_SOA_COLUMN(GenZ, genZ, float); // generated decay vtx position Z of the hypertriton -DECLARE_SOA_COLUMN(GenCt, genCt, float); // generated Ct of the hypertriton -DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // generated Phi of the hypertriton -DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton -DECLARE_SOA_COLUMN(GenRap, genRap, float); // generated rapidity of the hypertriton -DECLARE_SOA_COLUMN(GenPPr, genPPr, float); //! generated momentum proton daughter particle -DECLARE_SOA_COLUMN(GenPPi, genPPi, float); //! generated momentum pion daughter particle -DECLARE_SOA_COLUMN(GenPDe, genPDe, float); //! generated momentum deuteron daughter particle -DECLARE_SOA_COLUMN(GenPtPr, genPtPr, float); //! generated transverse momentum proton daughter particle -DECLARE_SOA_COLUMN(GenPtPi, genPtPi, float); //! generated transverse momentum pion daughter particle -DECLARE_SOA_COLUMN(GenPtDe, genPtDe, float); //! generated transverse momentum deuteron daughter particle -DECLARE_SOA_COLUMN(IsTrueH3L, isTrueH3l, bool); //! flag for true hypertriton candidate -DECLARE_SOA_COLUMN(IsTrueAntiH3L, isTrueAntiH3l, bool); //! flag for true anti-hypertriton candidate -DECLARE_SOA_COLUMN(MotherPdgCode, motherPdgCode, int); //! PDG code of the mother particle -DECLARE_SOA_COLUMN(PrPdgCode, prPdgCode, int); //! MC particle proton PDG code -DECLARE_SOA_COLUMN(PiPdgCode, piPdgCode, int); //! MC particle pion PDG code -DECLARE_SOA_COLUMN(DePdgCode, dePdgCode, int); //! MC particle deuteron PDG code -DECLARE_SOA_COLUMN(IsDePrimary, isDePrimary, bool); //! flag for deuteron daughter primary -DECLARE_SOA_COLUMN(IsSurvEvSel, isSurvEvSel, int); //! flag if reco collision survived event selection -DECLARE_SOA_COLUMN(IsReco, isreco, int); //! flag if candidate was reconstructed +DECLARE_SOA_COLUMN(GenPx, genPx, float); // generated Px of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenPy, genPy, float); // generated Py of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenPz, genPz, float); // generated Pz of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenX, genX, float); // generated decay vtx position X of the hypertriton +DECLARE_SOA_COLUMN(GenY, genY, float); // generated decay vtx position Y of the hypertriton +DECLARE_SOA_COLUMN(GenZ, genZ, float); // generated decay vtx position Z of the hypertriton +DECLARE_SOA_COLUMN(GenCt, genCt, float); // generated Ct of the hypertriton +DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // generated Phi of the hypertriton +DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton +DECLARE_SOA_COLUMN(GenRap, genRap, float); // generated rapidity of the hypertriton +DECLARE_SOA_COLUMN(GenPPr, genPPr, float); //! generated momentum proton daughter particle +DECLARE_SOA_COLUMN(GenPPi, genPPi, float); //! generated momentum pion daughter particle +DECLARE_SOA_COLUMN(GenPDe, genPDe, float); //! generated momentum deuteron daughter particle +DECLARE_SOA_COLUMN(GenPtPr, genPtPr, float); //! generated transverse momentum proton daughter particle +DECLARE_SOA_COLUMN(GenPtPi, genPtPi, float); //! generated transverse momentum pion daughter particle +DECLARE_SOA_COLUMN(GenPtDe, genPtDe, float); //! generated transverse momentum deuteron daughter particle +DECLARE_SOA_COLUMN(MotherPdgCode, motherPdgCode, int); //! PDG code of the mother particle +DECLARE_SOA_COLUMN(PrPdgCode, prPdgCode, int); //! MC particle proton PDG code +DECLARE_SOA_COLUMN(PiPdgCode, piPdgCode, int); //! MC particle pion PDG code +DECLARE_SOA_COLUMN(DePdgCode, dePdgCode, int); //! MC particle deuteron PDG code +DECLARE_SOA_COLUMN(IsDePrimary, isDePrimary, bool); //! flag for deuteron daughter primary +DECLARE_SOA_COLUMN(IsSurvEvSel, isSurvEvSel, int); //! flag if reco collision survived event selection +DECLARE_SOA_COLUMN(IsReco, isreco, int); //! flag if candidate was reconstructed +DECLARE_SOA_COLUMN(MotherLabel, motherLabel, int); //! label of the mother particle (signal: MC index, bkg: negative value) // Derived expressions // Momenta @@ -287,8 +286,8 @@ DECLARE_SOA_TABLE(McVtx3BodyDatas, "AOD", "MC3BODYDATA", //! vtx3body::GenPhi, vtx3body::GenEta, vtx3body::GenRap, vtx3body::GenPPr, vtx3body::GenPPi, vtx3body::GenPDe, vtx3body::GenPtPr, vtx3body::GenPtPi, vtx3body::GenPtDe, - vtx3body::IsTrueH3L, vtx3body::IsTrueAntiH3L, vtx3body::IsReco, + vtx3body::MotherLabel, vtx3body::MotherPdgCode, vtx3body::PrPdgCode, vtx3body::PiPdgCode, vtx3body::DePdgCode, vtx3body::IsDePrimary, diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index 38b1a130027..3b7205ca27c 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -232,9 +232,8 @@ struct decay3bodyBuilder { float genPtProton; float genPtPion; float genPtDeuteron; - bool isTrueH3L; - bool isTrueAntiH3L; bool isReco; + int motherLabel; int motherPdgCode; int daughterPrPdgCode; int daughterPiPdgCode; @@ -807,7 +806,7 @@ struct decay3bodyBuilder { if (!doStoreMcBkg) { continue; // if not storing MC background, skip candidates where at least one daughter is not matched to MC particle } else { - this3BodyMCInfo.label = -5; // at least one non-matched daughter + this3BodyMCInfo.motherLabel = -5; // at least one non-matched daughter // fill analysis table (only McVtx3BodyDatas is filled here) fillAnalysisTables(); } @@ -830,16 +829,16 @@ struct decay3bodyBuilder { this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); // daughters are matched to MC, now we check if reco mother is true H3L/Anti-H3l and decayed via three-body decay - this3BodyMCInfo.label = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron); // returns global index of mother if true H3L/Anti-H3L mother decaying via three-body decay, otherwise negative value + this3BodyMCInfo.motherLabel = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron); // returns global index of mother if true H3L/Anti-H3L mother decaying via three-body decay, otherwise negative value for background // if not storing MC background, skip candidates where mother is not true H3L/Anti-H3L decaying via three-body decay - if (!doStoreMcBkg && this3BodyMCInfo.label <= 0) { + if (!doStoreMcBkg && this3BodyMCInfo.motherLabel <= 0) { continue; } // get generated mother MC info for matched candidates - if (this3BodyMCInfo.label > -1) { - auto mcTrackH3L = mcParticles.rawIteratorAt(this3BodyMCInfo.label); + if (this3BodyMCInfo.motherLabel > 0) { + auto mcTrackH3L = mcParticles.rawIteratorAt(this3BodyMCInfo.motherLabel); this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode(); this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; @@ -847,8 +846,6 @@ struct decay3bodyBuilder { this3BodyMCInfo.genPhi = mcTrackH3L.phi(); this3BodyMCInfo.genEta = mcTrackH3L.eta(); this3BodyMCInfo.genRapidity = mcTrackH3L.y(); - this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false; - this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false; } // fill analysis tables (only McVtx3BodyDatas is filled here) @@ -856,8 +853,8 @@ struct decay3bodyBuilder { } // end of check if daughters have MC particle // mark mcParticle as reconstructed - if (this3BodyMCInfo.label > -1) { - mcParticleIsReco[this3BodyMCInfo.label] = true; + if (this3BodyMCInfo.motherLabel > 0) { + mcParticleIsReco[this3BodyMCInfo.motherLabel] = true; } } // constexpr requires mcParticles check } // decay3body loop @@ -904,11 +901,6 @@ struct decay3bodyBuilder { // check if hypertriton decayed via 3-body decay and is particle or anti-particle if ((haveProton && haveAntiPion && haveDeuteron && !(haveAntiProton || havePion || haveAntiDeuteron)) || (haveAntiProton && havePion && haveAntiDeuteron && !(haveProton || haveAntiPion || haveDeuteron))) { - if (mcparticle.pdgCode() > 0) { - this3BodyMCInfo.isTrueH3L = true; - } else if (mcparticle.pdgCode() < 0) { - this3BodyMCInfo.isTrueAntiH3L = true; - } // get daughters for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { // proton @@ -964,9 +956,9 @@ struct decay3bodyBuilder { mcparticle.phi(), mcparticle.eta(), mcparticle.y(), this3BodyMCInfo.genMomProton, this3BodyMCInfo.genMomPion, this3BodyMCInfo.genMomDeuteron, this3BodyMCInfo.genPtProton, this3BodyMCInfo.genPtPion, this3BodyMCInfo.genPtDeuteron, - this3BodyMCInfo.isTrueH3L, this3BodyMCInfo.isTrueAntiH3L, this3BodyMCInfo.isReco, - mcparticle.pdgCode(), + mcparticle.globalIndex(), // motherLabel + mcparticle.pdgCode(), // motherPdgCode this3BodyMCInfo.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, this3BodyMCInfo.isDeuteronPrimary, this3BodyMCInfo.survivedEventSel); @@ -1156,8 +1148,8 @@ struct decay3bodyBuilder { this3BodyMCInfo.genPhi, this3BodyMCInfo.genEta, this3BodyMCInfo.genRapidity, this3BodyMCInfo.genMomProton, this3BodyMCInfo.genMomPion, this3BodyMCInfo.genMomDeuteron, this3BodyMCInfo.genPtProton, this3BodyMCInfo.genPtPion, this3BodyMCInfo.genPtDeuteron, - this3BodyMCInfo.isTrueH3L, this3BodyMCInfo.isTrueAntiH3L, this3BodyMCInfo.isReco, + this3BodyMCInfo.motherLabel, this3BodyMCInfo.motherPdgCode, this3BodyMCInfo.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, this3BodyMCInfo.isDeuteronPrimary, @@ -1267,16 +1259,15 @@ struct decay3bodyBuilder { // function to reset MCInfo void resetMCInfo(mc3Bodyinfo& mcInfo) { - mcInfo.label = -1; + mcInfo.motherLabel = -999; mcInfo.genMomentum[0] = -1., mcInfo.genMomentum[1] = -1., mcInfo.genMomentum[2] = -1.; mcInfo.genDecVtx[0] = -1., mcInfo.genDecVtx[1] = -1., mcInfo.genDecVtx[2] = -1.; mcInfo.genCt = -1.; mcInfo.genPhi = -1., mcInfo.genEta = -1., mcInfo.genRapidity = -1.; mcInfo.genMomProton = -1., mcInfo.genMomPion = -1., mcInfo.genMomDeuteron = -1.; mcInfo.genPtProton = -1., mcInfo.genPtPion = -1., mcInfo.genPtDeuteron = -1.; - mcInfo.isTrueH3L = false, mcInfo.isTrueAntiH3L = false; mcInfo.isReco = false; - mcInfo.motherPdgCode = -1; + mcInfo.motherPdgCode = 0; mcInfo.daughterPrPdgCode = -1, mcInfo.daughterPiPdgCode = -1, mcInfo.daughterDePdgCode = -1; mcInfo.isDeuteronPrimary = false; return; From a6c574a0cfbcaf277d4048cdb1c3829ffdc953f8 Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Wed, 6 May 2026 20:34:52 +0200 Subject: [PATCH 068/449] [PWGLF] added a linked table for time (#16135) Co-authored-by: Prottay Das --- PWGLF/DataModel/ZDCCalTables.h | 16 +++++++++++++++ PWGLF/TableProducer/Common/zdcvector.cxx | 25 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/PWGLF/DataModel/ZDCCalTables.h b/PWGLF/DataModel/ZDCCalTables.h index 40b5fbdd575..097fb57e16c 100644 --- a/PWGLF/DataModel/ZDCCalTables.h +++ b/PWGLF/DataModel/ZDCCalTables.h @@ -85,5 +85,21 @@ DECLARE_SOA_TABLE(ZDCEnergyTables, "AOD", "ZDCENERGY", using ZDCEnergyTable = ZDCEnergyTables::iterator; +// Extra optional linked table for time information. +// It only stores timestamp and relative time, linked back to ZDCCalTables. +namespace zdctimetable +{ +DECLARE_SOA_INDEX_COLUMN(ZDCCalTable, zdcCalTable); + +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); // bc.timestamp(), in ms +DECLARE_SOA_COLUMN(TimeMin, timeMin, float); // time from first event seen in this run, in minutes +} // namespace zdctimetable + +DECLARE_SOA_TABLE(ZDCTimeTables, "AOD", "ZDCTIME", + zdctimetable::ZDCCalTableId, + zdctimetable::Timestamp, + zdctimetable::TimeMin); + +using ZDCTimeTable = ZDCTimeTables::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_ZDCCALTABLES_H_ diff --git a/PWGLF/TableProducer/Common/zdcvector.cxx b/PWGLF/TableProducer/Common/zdcvector.cxx index dd1b9860d05..b6b5407156f 100644 --- a/PWGLF/TableProducer/Common/zdcvector.cxx +++ b/PWGLF/TableProducer/Common/zdcvector.cxx @@ -44,7 +44,9 @@ #include #include #include +#include #include +#include #include using namespace o2; @@ -59,6 +61,7 @@ struct zdcvector { Produces zdccaltable; Produces zdcenergytable; + Produces zdctimetable; // Configurables. struct : ConfigurableGroup { @@ -100,8 +103,10 @@ struct zdcvector { } rctCut; Configurable storeZdcEnergy{"storeZdcEnergy", true, "Store ZDC tower/common energies in a linked extra table"}; + Configurable storeZdcTime{"storeZdcTime", true, "Store timestamp and time from first event of run"}; RCTFlagsChecker rctChecker; + std::unordered_map runStartTime; void init(o2::framework::InitContext&) { @@ -194,6 +199,17 @@ struct zdcvector { float znc3 = 0.f; auto bc = collision.foundBC_as(); + const uint64_t timestampzdc = bc.timestamp(); // in milliseconds + + float timeInMinutes = 0.f; + + auto itStart = runStartTime.find(currentRunNumber); + if (itStart == runStartTime.end()) { + runStartTime[currentRunNumber] = timestampzdc; + timeInMinutes = 0.f; + } else { + timeInMinutes = static_cast(timestampzdc - itStart->second) / 60000.f; + } // Helper to keep your early-return structure unchanged. // Every time ZDCCalTables is filled, the optional linked energy table is also filled. @@ -213,8 +229,10 @@ struct zdcvector { qyA, qyC); + auto zdcCalIndex = zdccaltable.lastIndex(); + if (storeZdcEnergy) { - zdcenergytable(zdccaltable.lastIndex(), + zdcenergytable(zdcCalIndex, znaEnergycommon, zncEnergycommon, zna0, @@ -226,6 +244,11 @@ struct zdcvector { znc2, znc3); } + if (storeZdcTime) { + zdctimetable(zdcCalIndex, + timestampzdc, + timeInMinutes); + } }; if (!bc.has_zdc()) { From e2b0b108f5aa7099fe670c237e8542dcc00c3c23 Mon Sep 17 00:00:00 2001 From: Antonio Palasciano <52152842+apalasciano@users.noreply.github.com> Date: Wed, 6 May 2026 21:59:14 +0200 Subject: [PATCH 069/449] [PWGHF] Fix DCA sel and derived data in hiddenCharm workflow (#16134) --- .../dataCreatorHiddenCharmReduced.cxx | 81 +++++++++++++------ PWGHF/D2H/Tasks/taskHiddenCharm.cxx | 38 +++++---- 2 files changed, 80 insertions(+), 39 deletions(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx index ef0171a7fd9..5d28bd3b4dc 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx @@ -76,9 +76,10 @@ struct HfDataCreatorHiddenCharmReduced { Produces hfTrackLite; struct : ConfigurableGroup { - // track quality Configurable fillHistograms{"fillHistograms", true, "Fill proton QA histograms"}; + Configurable fillSparses{"fillSparses", false, "Flag to enable sparse filling"}; Configurable selectProtons{"selectProtons", true, "Select protons"}; + // track quality Configurable itsNClsMin{"itsNClsMin", 5, "Minimum number of ITS clusters"}; Configurable tpcNClsFoundMin{"tpcNClsFoundMin", 50, "Minimum number of found TPC clusters"}; Configurable tpcNClsCrossedRowsMin{"tpcNClsCrossedRowsMin", 80, "Minimum number of crossed TPC rows"}; @@ -90,6 +91,7 @@ struct HfDataCreatorHiddenCharmReduced { Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "Track pT bin limits for DCA cuts"}; Configurable> cutsTrack{"cutsTrack", {hf_cuts_single_track::CutsTrack[0], hf_cuts_single_track::NBinsPtTrack, hf_cuts_single_track::NCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track DCA selections per pT bin"}; // DCA + Configurable applyPtDependentDcaTrackSelection{"applyPtDependentDcaTrackSelection", false, "Flag to enable pT-dependent DCAxy and DCAz selection on single tracks"}; Configurable> paramsDCAxyPtDep{"paramsDCAxyPtDep", std::vector{0.0010, 0.0080, 0.73}, "Parameters for pT-dependent DCAxy cut: p0, p1, p2 for cut = p0 + p1/pt^p2"}; Configurable> paramsDCAzPtDep{"paramsDCAzPtDep", std::vector{-0.0044, 0.0152, 0.47}, "Parameters for pT-dependent DCAz cut: p0, p1, p2 for cut = p0 + p1/pt^p2"}; // PID @@ -147,17 +149,30 @@ struct HfDataCreatorHiddenCharmReduced { const AxisSpec axisPt{360, 0., 36., "#it{p}_{T}^{proton} (GeV/#it{c})"}; const AxisSpec axisEta{100, -1., 1., "#eta"}; const AxisSpec axisDca{400, -2., 2., "DCA_{xy} to primary vertex (cm)"}; - const AxisSpec axisNSigma{100, -5., 5., "n#sigma"}; + const AxisSpec axisNSigmaTPC{100, -5., 5., "n#sigma_{TPC}"}; + const AxisSpec axisNSigmaTOF{100, -5., 5., "n#sigma_{TOF}"}; + const AxisSpec axisMass{100, 2.85, 3.25, "p#overline{p} invariant mass (GeV/#it{c}^{2})"}; registry.add("hPzVtx", "Z position of primary vertex for selected tracks;z_{vtx} (cm);entries", {HistType::kTH1D, {AxisSpec{200, -20., 20., "z_{vtx} (cm)"}}}); registry.add("hPtNoCuts", "All associated tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); registry.add("hPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); registry.add("hEtaCutsProton", "Selected proton tracks;#eta;entries", {HistType::kTH1D, {axisEta}}); registry.add("hDCAToPrimXYVsPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});DCA_{xy} to primary vertex (cm)", {HistType::kTH2D, {axisPt, axisDca}}); - registry.add("hNSigmaTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TPC}", {HistType::kTH2D, {axisPt, axisNSigma}}); - registry.add("hNSigmaTOFProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TOF}", {HistType::kTH2D, {axisPt, axisNSigma}}); - registry.add("hInvMass", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});invariant mass with other tracks (GeV/#it{c}^{2})", {HistType::kTH2D, {axisPt, AxisSpec{100, 2.85, 3.25, "invariant mass with other tracks (GeV/#it{c}^{2})"}}}); + registry.add("hNSigmaTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TPC}^{p}", {HistType::kTH2D, {axisPt, axisNSigmaTPC}}); + registry.add("hNSigmaTOFProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TOF}^{p}", {HistType::kTH2D, {axisPt, axisNSigmaTOF}}); + registry.add("hNSigmaTPCKaon", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); n#sigma_{TPC}^{K}", {HistType::kTH2D, {axisPt, axisNSigmaTPC}}); + registry.add("hNSigmaTOFKaon", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); n#sigma_{TOF}^{K}", {HistType::kTH2D, {axisPt, axisNSigmaTOF}}); + registry.add("hNSigmaTPCPion", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", {HistType::kTH2D, {axisPt, axisNSigmaTPC}}); + registry.add("hNSigmaTOFPion", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", {HistType::kTH2D, {axisPt, axisNSigmaTOF}}); + registry.add("hTpcNClsFound", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); TpcNClsFound", {HistType::kTH2D, {axisPt, {200, 0., 200, "TpcNClsFound"}}}); + registry.add("hTpcNClsCrossedRows", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); TpcNClsCrossedRows", {HistType::kTH2D, {axisPt, {200, 0., 200, "TpcNClsCrossedRows"}}}); + registry.add("hTpcChi2NCl", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); TpcChi2NCl", {HistType::kTH2D, {axisPt, {10, 0., 10, "TpcChi2NCl"}}}); + registry.add("hItsNCls", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});ItsNCls", {HistType::kTH2D, {axisPt, {7, 0, 7, "ItsNCls"}}}); + registry.add("hItsChi2NCl", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); ItsChi2NCl", {HistType::kTH2D, {axisPt, {10, 0., 10, "ItsChi2NCl"}}}); + registry.add("hInvMass", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});", {HistType::kTH2D, {axisPt, axisMass}}); + registry.add("hInvMassSparse", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});", {HistType::kTH2D, {axisPt, axisMass}}); registry.add("hDeDxTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});TPC dE/dx (a.u.)", {HistType::kTH2D, {axisPt, AxisSpec{100, 0., 200., "TPC dE/dx (a.u.)"}}}); + registry.add("hMassPtCutVars", "Charmonia candidates;#it{M} (p#overline{p}) (GeV/#it{c}^{2});#it{p}_{T}(cc) (GeV/#it{c}); n#sigma_{TPC}^{p1}; n#sigma_{TOF}^{p1}; dca_{xy}^{p1}; n#sigma_{TPC}^{p2}; n#sigma_{TOF}^{p2}; dca_{xy}^{p2}", {HistType::kTHnSparseF, {axisMass, axisPt, axisNSigmaTPC, axisNSigmaTOF, axisDca, axisNSigmaTPC, axisNSigmaTOF, axisDca}}); } // init HF event selection helper @@ -266,8 +281,10 @@ struct HfDataCreatorHiddenCharmReduced { if (!isSelectedTrackDca(config.binsPtTrack, config.cutsTrack, track.pt(), track.dcaXY(), track.dcaZ())) { return false; } - if (dcaSigma(track.pt(), config.paramsDCAxyPtDep.value[0], config.paramsDCAxyPtDep.value[1], config.paramsDCAxyPtDep.value[2]) > std::abs(dcaXY) || dcaSigma(track.pt(), config.paramsDCAzPtDep.value[0], config.paramsDCAzPtDep.value[1], config.paramsDCAzPtDep.value[2]) > std::abs(dcaZ)) { - return false; + if (config.applyPtDependentDcaTrackSelection.value) { + if (std::abs(dcaXY) > dcaSigma(track.pt(), config.paramsDCAxyPtDep.value[0], config.paramsDCAxyPtDep.value[1], config.paramsDCAxyPtDep.value[2]) || std::abs(dcaZ) > dcaSigma(track.pt(), config.paramsDCAzPtDep.value[0], config.paramsDCAzPtDep.value[1], config.paramsDCAzPtDep.value[2])) { + return false; + } } return isSelectedPid(track); } @@ -304,37 +321,55 @@ struct HfDataCreatorHiddenCharmReduced { if (!isSelectedTrack(trk)) { continue; } - std::array pVecProton{trk.pVector()}; - hfTrackLite(trk.globalIndex(), collision.globalIndex(), pVecProton[0], pVecProton[1], pVecProton[2], trk.sign(), static_cast(TrackType::Proton)); - selectedTrackIds.push_back(trk.globalIndex()); + selectedTrackIds.push_back(trkId.trackId()); + if (config.fillHistograms) { registry.fill(HIST("hPtCutsProton"), trk.pt()); registry.fill(HIST("hEtaCutsProton"), trk.eta()); registry.fill(HIST("hDCAToPrimXYVsPtCutsProton"), trk.pt(), trk.dcaXY()); registry.fill(HIST("hNSigmaTPCProton"), trk.pt(), trk.tpcNSigmaPr()); - registry.fill(HIST("hDeDxTPCProton"), trk.pt(), trk.tpcSignal()); + registry.fill(HIST("hNSigmaTPCPion"), trk.pt(), trk.tpcNSigmaPi()); + registry.fill(HIST("hNSigmaTPCKaon"), trk.pt(), trk.tpcNSigmaKa()); if (trk.hasTOF()) { registry.fill(HIST("hNSigmaTOFProton"), trk.pt(), trk.tofNSigmaPr()); + registry.fill(HIST("hNSigmaTOFPion"), trk.pt(), trk.tofNSigmaPi()); + registry.fill(HIST("hNSigmaTOFKaon"), trk.pt(), trk.tofNSigmaKa()); } + registry.fill(HIST("hTpcNClsFound"), trk.pt(), trk.tpcNClsFound()); + registry.fill(HIST("hTpcNClsCrossedRows"), trk.pt(), trk.tpcNClsCrossedRows()); + registry.fill(HIST("hTpcChi2NCl"), trk.pt(), trk.tpcChi2NCl()); + registry.fill(HIST("hItsNCls"), trk.pt(), trk.itsNCls()); + registry.fill(HIST("hItsChi2NCl"), trk.pt(), trk.itsChi2NCl()); } } + // skip event if not at least a pair of tracks skimming selection if (selectedTrackIds.size() < NDaughtersCharmMeson) { continue; } hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); - for (size_t i = 0; i < selectedTrackIds.size(); ++i) { - auto t1 = tracks.rawIteratorAt(selectedTrackIds[i]); - std::array pVec1{t1.pVector()}; - for (size_t j = i + 1; j < selectedTrackIds.size(); ++j) { - auto t2 = tracks.rawIteratorAt(selectedTrackIds[j]); - if (t1.sign() * t2.sign() > 0) { - continue; - } - std::array pVec2{t2.pVector()}; - float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); - float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); - if (config.fillHistograms) { + + auto reducedEventId = hfReducedCollision.lastIndex(); + for (const auto& trkId : selectedTrackIds) { + auto track = tracks.rawIteratorAt(trkId); + std::array pVec{track.pVector()}; + hfTrackLite(track.globalIndex(), reducedEventId, pVec[0], pVec[1], pVec[2], track.sign(), static_cast(TrackType::Proton)); + } + + if (config.fillHistograms.value) { + for (size_t i = 0; i < selectedTrackIds.size(); ++i) { + auto t1 = tracks.rawIteratorAt(selectedTrackIds[i]); + std::array pVec1{t1.pVector()}; + for (size_t j = i + 1; j < selectedTrackIds.size(); ++j) { + auto t2 = tracks.rawIteratorAt(selectedTrackIds[j]); + if (t1.sign() * t2.sign() > 0) + continue; + std::array pVec2{t2.pVector()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); + float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); registry.fill(HIST("hInvMass"), ptEtac, invMass); + if (config.fillSparses.value) { + registry.fill(HIST("hMassPtCutVars"), invMass, ptEtac, t1.tpcNSigmaPr(), t1.tofNSigmaPr(), t1.dcaXY(), t2.tpcNSigmaPr(), t2.tofNSigmaPr(), t2.dcaXY()); + } } } } diff --git a/PWGHF/D2H/Tasks/taskHiddenCharm.cxx b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx index 70fa6f717f2..4ca56330285 100644 --- a/PWGHF/D2H/Tasks/taskHiddenCharm.cxx +++ b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx @@ -52,8 +52,8 @@ struct HfTaskHiddenCharm { Configurable centEstimator{"centEstimator", 0, "Centrality estimation (None: 0, FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; Configurable centralityMin{"centralityMin", 0.f, "Minimum accepted centrality"}; Configurable centralityMax{"centralityMax", 100.f, "Maximum accepted centrality"}; - Configurable fillOnlyUnlikeSign{"fillOnlyUnlikeSign", true, "Fill only unlike-sign proton pairs"}; - Configurable fillOnlyLikeSign{"fillOnlyLikeSign", true, "Fill only like-sign proton pairs"}; + Configurable fillUnlikeSign{"fillUnlikeSign", true, "Fill unlike-sign proton pairs"}; + Configurable fillLikeSign{"fillLikeSign", true, "Fill like-sign proton pairs"}; SliceCache cache; @@ -94,7 +94,7 @@ struct HfTaskHiddenCharm { void fillEtac(TCollisions const& collision, TProtonIds const& protonIds) { - float cent{-1.f}; + float cent{0.f}; if constexpr (CentEstimator != o2::hf_centrality::CentralityEstimator::None) { cent = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (cent < centralityMin || cent >= centralityMax) { @@ -102,26 +102,32 @@ struct HfTaskHiddenCharm { } } - for (const auto& proton1 : protonIds) { - for (const auto& proton2 : protonIds) { - if (proton1.trackId() >= proton2.trackId()) { - continue; // avoid double counting and self-pairs - } + for (auto it1 = protonIds.begin(); it1 != protonIds.end(); ++it1) { + for (auto it2 = it1 + 1; it2 != protonIds.end(); ++it2) { + + const auto& proton1 = *it1; + const auto& proton2 = *it2; const int sign = (proton1.sign() * proton2.sign() > 0) ? 1 : -1; - if ((sign == 1 && !fillOnlyLikeSign) || (sign == -1 && !fillOnlyUnlikeSign)) { + + if (sign == 1 && !fillLikeSign) continue; - } + if (sign == -1 && !fillUnlikeSign) + continue; + std::array pVec1{proton1.px(), proton1.py(), proton1.pz()}; std::array pVec2{proton2.px(), proton2.py(), proton2.pz()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); - float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); - registry.fill(HIST("hSparseHiddenCharm"), invMass, ptEtac, sign, cent); + float pt = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); + + registry.fill(HIST("hSparseHiddenCharm"), invMass, pt, sign, cent); if (sign == 1) { - registry.fill(HIST("hPtVsInvMassLikeSign"), invMass, ptEtac); - } else if (sign == -1) { - registry.fill(HIST("hPtVsInvMassUnlikeSign"), invMass, ptEtac); - registry.fill(HIST("hPtVsInvMassAllSign"), invMass, ptEtac); + registry.fill(HIST("hPtVsInvMassLikeSign"), invMass, pt); + } else { + registry.fill(HIST("hPtVsInvMassUnlikeSign"), invMass, pt); } + + registry.fill(HIST("hPtVsInvMassAllSign"), invMass, pt); } } } From ea3875628d34e196f878d18d00f5672fb203b572 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Wed, 6 May 2026 22:49:19 +0200 Subject: [PATCH 070/449] [Common] Add combined A + C side information in bc process function (#16130) --- Common/Tasks/centralityStudy.cxx | 777 ++++++++++++++++++------------- 1 file changed, 457 insertions(+), 320 deletions(-) diff --git a/Common/Tasks/centralityStudy.cxx b/Common/Tasks/centralityStudy.cxx index 20ab15ba873..892756cc68e 100644 --- a/Common/Tasks/centralityStudy.cxx +++ b/Common/Tasks/centralityStudy.cxx @@ -71,69 +71,92 @@ struct centralityStudy { // Configurables Configurable applyVertexZEqualization{"applyVertexZEqualization", false, "0 - no, 1 - yes"}; - - Configurable do2DPlots{"do2DPlots", true, "0 - no, 1 - yes"}; - Configurable doOccupancyStudyVsCentrality2d{"doOccupancyStudyVsCentrality2d", true, "0 - no, 1 - yes"}; - Configurable doOccupancyStudyVsRawValues2d{"doOccupancyStudyVsRawValues2d", true, "0 - no, 1 - yes"}; - Configurable doOccupancyStudyVsCentrality3d{"doOccupancyStudyVsCentrality3d", false, "0 - no, 1 - yes"}; - Configurable doOccupancyStudyVsRawValues3d{"doOccupancyStudyVsRawValues3d", false, "0 - no, 1 - yes"}; - Configurable doTimeStudies{"doTimeStudies", true, "0 - no, 1 - yes"}; - Configurable doTimeStudyFV0AOuterVsFT0A3d{"doTimeStudyFV0AOuterVsFT0A3d", false, "0 - no, 1 - yes"}; - Configurable doNGlobalTracksVsRawSignals{"doNGlobalTracksVsRawSignals", true, "0 - no, 1 - yes"}; - Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; - Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; - - // Apply extra event selections - Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border"}; - Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border"}; - Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track"}; - Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", false, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference"}; - Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF"}; - Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; - Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; - Configurable rejectIsFlangeEvent{"rejectIsFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; - - Configurable rejectITSinROFpileupStandard{"rejectITSinROFpileupStandard", false, "reject collisions in case of in-ROF ITS pileup (standard)"}; - Configurable rejectITSinROFpileupStrict{"rejectITSinROFpileupStrict", false, "reject collisions in case of in-ROF ITS pileup (strict)"}; - Configurable rejectCollInTimeRangeNarrow{"rejectCollInTimeRangeNarrow", false, "reject if extra colls in time range (narrow)"}; - Configurable rejectZNAC{"rejectZNAC", false, "reject if !(kIsBBZNA && kIsBBZNC)"}; - - Configurable selectUPCcollisions{"selectUPCcollisions", false, "select collisions tagged with UPC flag"}; - - Configurable selectCollidingBCs{"selectCollidingBCs", true, "BC analysis: select colliding BCs"}; - Configurable selectTVX{"selectTVX", true, "BC analysis: select TVX"}; - Configurable selectFV0OrA{"selectFV0OrA", true, "BC analysis: select FV0OrA"}; - Configurable vertexZwithT0{"vertexZwithT0", 1000.0f, "require a certain vertex-Z in BC analysis"}; - Configurable minTimeDelta{"minTimeDelta", -1.0f, "reject collision if another collision is this close or less in time"}; - Configurable minFT0CforVertexZ{"minFT0CforVertexZ", -1.0f, "minimum FT0C for vertex-Z profile calculation"}; - - Configurable scaleSignalFT0A{"scaleSignalFT0A", 1.00f, "scale FT0A signal for convenience"}; - Configurable scaleSignalFT0C{"scaleSignalFT0C", 1.00f, "scale FT0C signal for convenience"}; - Configurable scaleSignalFT0M{"scaleSignalFT0M", 1.00f, "scale FT0M signal for convenience"}; - Configurable scaleSignalFV0A{"scaleSignalFV0A", 1.00f, "scale FV0A signal for convenience"}; Configurable ccdbURL{"ccdbURL", "http://alice-ccdb.cern.ch", "ccdb url"}; Configurable pathGRPECSObject{"pathGRPECSObject", "GLO/Config/GRPECS", "Path to GRPECS object"}; Configurable pathVertexZ{"pathVertexZ", "Users/d/ddobrigk/Centrality/Calibration", "Path to vertexZ profiles"}; Configurable irSource{"irSource", "ZNC hadronic", "Source of the interaction rate: (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; Configurable irCrashOnNull{"irCrashOnNull", false, "Flag to avoid CTP RateFetcher crash."}; - Configurable irDoRateVsTime{"irDoRateVsTime", true, "Do IR plots"}; + + // _______________________________________ + // Configurable group + struct : ConfigurableGroup { + std::string prefix = "studies"; + Configurable do2DPlots{"do2DPlots", true, "0 - no, 1 - yes"}; + Configurable doRunByRunHistograms{"doRunByRunHistograms", false, "0 - no, 1 - yes"}; + Configurable doOccupancyStudyVsCentrality2d{"doOccupancyStudyVsCentrality2d", true, "0 - no, 1 - yes"}; + Configurable doOccupancyStudyVsRawValues2d{"doOccupancyStudyVsRawValues2d", true, "0 - no, 1 - yes"}; + Configurable doOccupancyStudyVsCentrality3d{"doOccupancyStudyVsCentrality3d", false, "0 - no, 1 - yes"}; + Configurable doOccupancyStudyVsRawValues3d{"doOccupancyStudyVsRawValues3d", false, "0 - no, 1 - yes"}; + Configurable doTimeStudies{"doTimeStudies", false, "0 - no, 1 - yes"}; + Configurable doNGlobalTracksVsRawSignals{"doNGlobalTracksVsRawSignals", true, "0 - no, 1 - yes"}; + } studies; + + // _______________________________________ + // Event selection + struct : ConfigurableGroup { + std::string prefix = "evsel"; + Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; + Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; + Configurable selectUPCcollisions{"selectUPCcollisions", false, "select collisions tagged with UPC flag"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border"}; + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", false, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference"}; + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable rejectIsFlangeEvent{"rejectIsFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; + Configurable rejectITSinROFpileupStandard{"rejectITSinROFpileupStandard", false, "reject collisions in case of in-ROF ITS pileup (standard)"}; + Configurable rejectITSinROFpileupStrict{"rejectITSinROFpileupStrict", false, "reject collisions in case of in-ROF ITS pileup (strict)"}; + Configurable rejectUpc{"rejectUpc", false, "Reject upc events based on forward signals. Configurable group: upcRejection"}; + Configurable rejectCollInTimeRangeNarrow{"rejectCollInTimeRangeNarrow", false, "reject if extra colls in time range (narrow)"}; + Configurable maxVtxZ{"maxVtxZ", 10.0f, "max vertex z distance from ip"}; + } evsel; + + // _______________________________________ + // BC Selection + struct : ConfigurableGroup { + std::string prefix = "bcsel"; + Configurable rejectZNAC{"rejectZNAC", false, "reject if !(kIsBBZNA && kIsBBZNC)"}; + Configurable selectCollidingBCs{"selectCollidingBCs", true, "BC analysis: select colliding BCs"}; + Configurable selectTVX{"selectTVX", true, "BC analysis: select TVX"}; + Configurable selectFV0OrA{"selectFV0OrA", true, "BC analysis: select FV0OrA"}; + Configurable rejectUpc{"rejectUpc", false, "Reject upc events based on forward signals. Configurable group: upcRejection"}; + Configurable vertexZwithT0{"vertexZwithT0", 1000.0f, "require a certain vertex-Z in BC analysis"}; + Configurable rejectIsFlangeEvent{"rejectIsFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; + Configurable minFT0CforVertexZ{"minFT0CforVertexZ", -1.0f, "minimum FT0C for vertex-Z profile calculation"}; + + } bcsel; // _______________________________________ // upc rejection criteria // reject low zna/c struct : ConfigurableGroup { + std::string prefix = "upcRejection"; Configurable minZNACsignal{"minZNACsignal", -999999.0f, "min zna/c signal"}; Configurable maxFT0CforZNACselection{"maxFT0CforZNACselection", -99999.0f, "max ft0c signal for minZNACsignal to work"}; - Configurable minFV0Asignal{"minFV0Asignal", -999999.0f, "min fv0a signal"}; Configurable maxFT0CforFV0Aselection{"maxFT0CforFV0Aselection", -99999.0f, "max ft0c signal for minFV0Asignal to work"}; - Configurable minFDDAsignal{"minFDDAsignal", -999999.0f, "min fdda signal"}; Configurable maxFT0CforFDDAselection{"maxFT0CforFDDAselection", -99999.0f, "max ft0c signal for minFDDAsignal to work"}; } upcRejection; + // _______________________________________ + // Scaling + struct : ConfigurableGroup { + std::string prefix = "scale"; + Configurable factorFT0A{"factorFT0A", 1.00f, "scale the raw FT0A signal for convenience"}; + Configurable factorFT0C{"factorFT0C", 1.00f, "scale the raw FT0C signal for convenience"}; + Configurable factorFV0A{"factorFV0A", 1.00f, "scale the raw FV0A signal for convenience"}; + Configurable factorFT0M{"factorFT0M", 1.00f, "scale the raw FT0M signal for convenience"}; + Configurable factorFV0AT0C{"factorFV0AT0C", 1.00f, "scale the raw FV0A+FT0C signal for convenience"}; + Configurable normFT0A{"normFT0A", 1.00f, "scale the self-normalised FT0A signal; scale.normFT0A * FT0A / "}; + Configurable normFT0C{"normFT0C", 1.00f, "scale the self-normalised FT0C signal; scale.normFT0C * FT0C / "}; + Configurable normFV0A{"normFV0A", 1.00f, "scale the self-normalised FV0A signal; scale.normFV0A * FV0A / "}; + } scale; + // Configurable Axes for 2d plots, etc ConfigurableAxis axisMultFV0A{"axisMultFV0A", {1000, 0, 100000}, "FV0A amplitude"}; ConfigurableAxis axisMultFT0A{"axisMultFT0A", {1000, 0, 100000}, "FT0A amplitude"}; @@ -145,15 +168,17 @@ struct centralityStudy { ConfigurableAxis axisMultGlobalTracks{"axisMultGlobalTracks", {500, 0, 5000}, "Number of global tracks"}; ConfigurableAxis axisMultMFTTracks{"axisMultMFTTracks", {500, 0, 5000}, "Number of MFT tracks"}; ConfigurableAxis axisMultMCCounts{"axisMultMCCounts", {1000, 0, 5000}, "N_{ch}"}; - ConfigurableAxis axisTrackOccupancy{"axisTrackOccupancy", {50, 0, 5000}, "Track occupancy"}; ConfigurableAxis axisFT0COccupancy{"axisFT0COccupancy", {50, 0, 80000}, "FT0C occupancy"}; // For one-dimensional plots, where binning is no issue ConfigurableAxis axisMultUltraFineFV0A{"axisMultUltraFineFV0A", {60000, 0, 60000}, "FV0A amplitude"}; - ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; ConfigurableAxis axisMultUltraFineFT0C{"axisMultUltraFineFT0C", {60000, 0, 60000}, "FT0C amplitude"}; ConfigurableAxis axisMultUltraFineFT0A{"axisMultUltraFineFT0A", {60000, 0, 60000}, "FT0A amplitude"}; + ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; + ConfigurableAxis axisMultUltraFineFV0AT0C{"axisMultUltraFineFV0AT0C", {60000, 0, 60000}, "FV0A + FT0C amplitude"}; + ConfigurableAxis axisMultUltraFineScaledFT0M{"axisMultUltraFineScaledFT0M", {40000, 0, 40}, "a*FT0A/ + b*FT0C/"}; + ConfigurableAxis axisMultUltraFineScaledFV0AT0C{"axisMultUltraFineScaledFV0AT0C", {40000, 0, 40}, "a*FV0A/ + b*FT0C/"}; ConfigurableAxis axisMultUltraFinePVContributors{"axisMultUltraFinePVContributors", {10000, 0, 10000}, "Number of PV Contributors"}; ConfigurableAxis axisMultUltraFineGlobalTracks{"axisMultUltraFineGlobalTracks", {5000, 0, 5000}, "Number of global tracks"}; ConfigurableAxis axisMultUltraFineMFTTracks{"axisMultUltraFineMFTTracks", {5000, 0, 5000}, "Number of MFT tracks"}; @@ -187,8 +212,12 @@ struct centralityStudy { hVtxZFDDA = nullptr; hVtxZFDDC = nullptr; + ccdb->setURL(ccdbURL); + // ccdb->setCaching(true); + // ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + if (doprocessCollisions || doprocessCollisionsWithCentrality) { - const AxisSpec axisCollisions{100, -0.5f, 99.5f, "Number of collisions"}; histos.add("hCollisionSelection", "hCollisionSelection", kTH1D, {{20, -0.5f, +19.5f}}); histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); @@ -216,11 +245,76 @@ struct centralityStudy { histos.add("hNMFTTracks", "hNMFTTracks", kTH1D, {axisMultUltraFineMFTTracks}); histos.add("hNPVContributors", "hNPVContributors", kTH1D, {axisMultUltraFinePVContributors}); - histos.add("hFT0CvsPVz_Collisions_All", "hFT0CvsPVz_Collisions_All", kTProfile, {axisPVz}); histos.add("hFT0CvsPVz_Collisions", "hFT0CvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hFT0AvsPVz_Collisions", "hFT0AvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hFV0AvsPVz_Collisions", "hFV0AvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hNGlobalTracksvsPVz_Collisions", "hNGlobalTracksvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hNMFTTracksvsPVz_Collisions", "hNMFTTracksvsPVz_Collisions", kTProfile, {axisPVz}); + + if (studies.do2DPlots) { + histos.add("hNContribsVsFT0C", "hNContribsVsFT0C", kTH2F, {axisMultFT0C, axisMultPVContributors}); + histos.add("hNContribsVsFV0A", "hNContribsVsFV0A", kTH2F, {axisMultFV0A, axisMultPVContributors}); + histos.add("hMatchedVsITSOnly", "hMatchedVsITSOnly", kTH2F, {axisMultITSOnly, axisMultITSTPC}); + + // 2d correlation of fit signals + histos.add("hFT0AVsFT0C", "hFT0AVsFT0C", kTH2F, {axisMultFT0C, axisMultFT0A}); + histos.add("hFV0AVsFT0C", "hFV0AVsFT0C", kTH2F, {axisMultFT0C, axisMultFV0A}); + histos.add("hFDDAVsFT0C", "hFDDAVsFT0C", kTH2F, {axisMultFT0C, axisMultFDDA}); + histos.add("hFDDCVsFT0C", "hFDDCVsFT0C", kTH2F, {axisMultFT0C, axisMultFDDC}); + } + + if (studies.doNGlobalTracksVsRawSignals) { + histos.add("hNGlobalTracksVsFT0A", "hNGlobalTracksVsFT0A", kTH2F, {axisMultFT0A, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsFT0C", "hNGlobalTracksVsFT0C", kTH2F, {axisMultFT0C, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsFT0M", "hNGlobalTracksVsFT0M", kTH2F, {axisMultFT0M, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsFV0A", "hNGlobalTracksVsFV0A", kTH2F, {axisMultFV0A, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsFDDA", "hNGlobalTracksVsFDDA", kTH2F, {axisMultFDDA, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsFDDC", "hNGlobalTracksVsFDDC", kTH2F, {axisMultFDDC, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsZNA", "hNGlobalTracksVsZNA", kTH2F, {axisZN, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsZNC", "hNGlobalTracksVsZNC", kTH2F, {axisZN, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsNMFTTracks", "hNGlobalTracksVsNMFTTracks", kTH2F, {axisMultMFTTracks, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsNTPV", "hNGlobalTracksVsNTPV", kTH2F, {axisMultPVContributors, axisMultGlobalTracks}); + } + + if (studies.doOccupancyStudyVsRawValues2d) { + histos.add("hNcontribsProfileVsTrackOccupancyVsFT0C", "hNcontribsProfileVsTrackOccupancyVsFT0C", kTProfile2D, {axisTrackOccupancy, axisMultFT0C}); + histos.add("hNGlobalTracksProfileVsTrackOccupancyVsFT0C", "hNGlobalTracksProfileVsTrackOccupancyVsFT0C", kTProfile2D, {axisTrackOccupancy, axisMultFT0C}); + histos.add("hNcontribsProfileVsFT0COccupancyVsFT0C", "hNcontribsProfileVsFT0COccupancyVsFT0C", kTProfile2D, {axisFT0COccupancy, axisMultFT0C}); + histos.add("hNGlobalTracksProfileVsFT0COccupancyVsFT0C", "hNGlobalTracksProfileVsFT0COccupancyVsFT0C", kTProfile2D, {axisFT0COccupancy, axisMultFT0C}); + } + + if (studies.doOccupancyStudyVsRawValues3d) { + histos.add("hTrackOccupancyVsNContribsVsFT0C", "hTrackOccupancyVsNContribsVsFT0C", kTH3F, {axisTrackOccupancy, axisMultPVContributors, axisMultFT0C}); + histos.add("hTrackOccupancyVsNGlobalTracksVsFT0C", "hTrackOccupancyVsNGlobalTracksVsFT0C", kTH3F, {axisTrackOccupancy, axisMultGlobalTracks, axisMultFT0C}); + histos.add("hFT0COccupancyVsNContribsVsFT0C", "hFT0COccupancyVsNContribsVsFT0C", kTH3F, {axisFT0COccupancy, axisMultPVContributors, axisMultFT0C}); + histos.add("hFT0COccupancyVsNGlobalTracksVsFT0C", "hFT0COccupancyVsNGlobalTracksVsFT0C", kTH3F, {axisFT0COccupancy, axisMultGlobalTracks, axisMultFT0C}); + } + + if (doprocessCollisionsWithCentrality) { + // in case requested: do vs centrality debugging + histos.add("hCentrality", "hCentrality", kTH1F, {axisCentrality}); + histos.add("hNContribsVsCentrality", "hNContribsVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); + histos.add("hNITSTPCTracksVsCentrality", "hNITSTPCTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); + histos.add("hNITSOnlyTracksVsCentrality", "hNITSOnlyTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); + histos.add("hNGlobalTracksVsCentrality", "hNGlobalTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); + histos.add("hNMFTTracksVsCentrality", "hNMFTTracksVsCentrality", kTH2F, {axisCentrality, axisMultMFTTracks}); + histos.add("hPVChi2VsCentrality", "hPVChi2VsCentrality", kTH2F, {axisCentrality, axisPVChi2}); + histos.add("hDeltaTimeVsCentrality", "hDeltaTimeVsCentrality", kTH2F, {axisCentrality, axisDeltaTime}); + + if (studies.doOccupancyStudyVsCentrality2d) { + histos.add("hNcontribsProfileVsTrackOccupancyVsCentrality", "hNcontribsProfileVsTrackOccupancyVsCentrality", kTProfile2D, {axisTrackOccupancy, axisCentrality}); + histos.add("hNGlobalTracksProfileVsTrackOccupancyVsCentrality", "hNGlobalTracksProfileVsTrackOccupancyVsCentrality", kTProfile2D, {axisTrackOccupancy, axisCentrality}); + histos.add("hNcontribsProfileVsFT0COccupancyVsCentrality", "hNcontribsProfileVsFT0COccupancyVsCentrality", kTProfile2D, {axisFT0COccupancy, axisCentrality}); + histos.add("hNGlobalTracksProfileVsFT0COccupancyVsCentrality", "hNGlobalTracksProfileVsFT0COccupancyVsCentrality", kTProfile2D, {axisFT0COccupancy, axisCentrality}); + } + + if (studies.doOccupancyStudyVsCentrality3d) { + histos.add("hTrackOccupancyVsNContribsVsCentrality", "hTrackOccupancyVsNContribsVsCentrality", kTH3F, {axisTrackOccupancy, axisMultPVContributors, axisCentrality}); + histos.add("hTrackOccupancyVsNGlobalTracksVsCentrality", "hTrackOccupancyVsNGlobalTracksVsCentrality", kTH3F, {axisTrackOccupancy, axisMultGlobalTracks, axisCentrality}); + histos.add("hFT0COccupancyVsNContribsVsCentrality", "hFT0COccupancyVsNContribsVsCentrality", kTH3F, {axisFT0COccupancy, axisMultPVContributors, axisCentrality}); + histos.add("hFT0COccupancyVsNGlobalTracksVsCentrality", "hFT0COccupancyVsNGlobalTracksVsCentrality", kTH3F, {axisFT0COccupancy, axisMultGlobalTracks, axisCentrality}); + } + } } if (doprocessBCs) { @@ -229,42 +323,29 @@ struct centralityStudy { histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(2, "Colliding BCs"); histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(3, "TVX"); histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(4, "FV0OrA"); - histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(5, "upc rej"); - histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(6, "zdc rej"); + histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(5, "FT0PosZ"); + histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(6, "upc rej"); + histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(7, "zdc rej"); + histos.get(HIST("hBCSelection"))->GetXaxis()->SetBinLabel(8, "isFlangeEvent"); histos.add("hFT0C_BCs", "hFT0C_BCs", kTH1D, {axisMultUltraFineFT0C}); + histos.add("hFT0A_BCs", "hFT0A_BCs", kTH1D, {axisMultUltraFineFT0A}); histos.add("hFT0M_BCs", "hFT0M_BCs", kTH1D, {axisMultUltraFineFT0M}); histos.add("hFV0A_BCs", "hFV0A_BCs", kTH1D, {axisMultUltraFineFV0A}); + histos.add("hFV0AT0C_BCs", "hFV0AT0C_BCs", kTH1D, {axisMultUltraFineFV0AT0C}); + histos.add("hScaledFT0M_BCs", "hScaledFT0M_BCs", kTH1D, {axisMultUltraFineScaledFT0M}); + histos.add("hScaledFV0AT0C_BCs", "hScaledFV0AT0C_BCs", kTH1D, {axisMultUltraFineScaledFV0AT0C}); + histos.add("hFT0CvsPVz_BCs_All", "hFT0CvsPVz_BCs_All", kTProfile, {axisPVz}); histos.add("hFT0CvsPVz_BCs", "hFT0CvsPVz_BCs", kTProfile, {axisPVz}); histos.add("hVertexZ_BCvsCO", "hVertexZ_BCvsCO", kTH2F, {axisPVz, axisPVz}); histos.add("hZNAvsFT0C_BCs", "hZNAvsFT0C_BCs", kTH2F, {axisMultFT0C, axisZN}); histos.add("hZNCvsFT0C_BCs", "hZNCvsFT0C_BCs", kTH2F, {axisMultFT0C, axisZN}); - } - - if (do2DPlots) { - histos.add("hNContribsVsFT0C", "hNContribsVsFT0C", kTH2F, {axisMultFT0C, axisMultPVContributors}); - histos.add("hNContribsVsFV0A", "hNContribsVsFV0A", kTH2F, {axisMultFV0A, axisMultPVContributors}); - histos.add("hMatchedVsITSOnly", "hMatchedVsITSOnly", kTH2F, {axisMultITSOnly, axisMultITSTPC}); - // 2d correlation of fit signals - histos.add("hFT0AVsFT0C", "hFT0AVsFT0C", kTH2F, {axisMultFT0C, axisMultFT0A}); - histos.add("hFV0AVsFT0C", "hFV0AVsFT0C", kTH2F, {axisMultFT0C, axisMultFV0A}); - histos.add("hFDDAVsFT0C", "hFDDAVsFT0C", kTH2F, {axisMultFT0C, axisMultFDDA}); - histos.add("hFDDCVsFT0C", "hFDDCVsFT0C", kTH2F, {axisMultFT0C, axisMultFDDC}); - } - - if (doNGlobalTracksVsRawSignals) { - histos.add("hNGlobalTracksVsFT0A", "hNGlobalTracksVsFT0A", kTH2F, {axisMultFT0A, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsFT0C", "hNGlobalTracksVsFT0C", kTH2F, {axisMultFT0C, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsFT0M", "hNGlobalTracksVsFT0M", kTH2F, {axisMultFT0M, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsFV0A", "hNGlobalTracksVsFV0A", kTH2F, {axisMultFV0A, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsFDDA", "hNGlobalTracksVsFDDA", kTH2F, {axisMultFDDA, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsFDDC", "hNGlobalTracksVsFDDC", kTH2F, {axisMultFDDC, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsZNA", "hNGlobalTracksVsZNA", kTH2F, {axisZN, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsZNC", "hNGlobalTracksVsZNC", kTH2F, {axisZN, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsNMFTTracks", "hNGlobalTracksVsNMFTTracks", kTH2F, {axisMultMFTTracks, axisMultGlobalTracks}); - histos.add("hNGlobalTracksVsNTPV", "hNGlobalTracksVsNTPV", kTH2F, {axisMultPVContributors, axisMultGlobalTracks}); + if (studies.do2DPlots) { + histos.add("hFT0AVsFT0C_BCs", "hFT0AVsFT0C_BCs", kTH2F, {axisMultFT0C, axisMultFT0A}); + histos.add("hFV0AVsFT0C_BCs", "hFV0AVsFT0C_BCs", kTH2F, {axisMultFT0C, axisMultFV0A}); + } } if (doprocessCollisionsWithResolutionStudy) { @@ -282,56 +363,6 @@ struct centralityStudy { histos.add("hImpactParameterVsMCFT0M", "hImpactParameterVsMCFT0M", kTH2F, {axisMultMCCounts, axisImpactParameter}); histos.add("hImpactParameterVsMCFV0A", "hImpactParameterVsMCFV0A", kTH2F, {axisMultMCCounts, axisImpactParameter}); } - - if (doOccupancyStudyVsRawValues2d) { - histos.add("hNcontribsProfileVsTrackOccupancyVsFT0C", "hNcontribsProfileVsTrackOccupancyVsFT0C", kTProfile2D, {axisTrackOccupancy, axisMultFT0C}); - histos.add("hNGlobalTracksProfileVsTrackOccupancyVsFT0C", "hNGlobalTracksProfileVsTrackOccupancyVsFT0C", kTProfile2D, {axisTrackOccupancy, axisMultFT0C}); - histos.add("hNcontribsProfileVsFT0COccupancyVsFT0C", "hNcontribsProfileVsFT0COccupancyVsFT0C", kTProfile2D, {axisFT0COccupancy, axisMultFT0C}); - histos.add("hNGlobalTracksProfileVsFT0COccupancyVsFT0C", "hNGlobalTracksProfileVsFT0COccupancyVsFT0C", kTProfile2D, {axisFT0COccupancy, axisMultFT0C}); - } - - if (doOccupancyStudyVsRawValues3d) { - histos.add("hTrackOccupancyVsNContribsVsFT0C", "hTrackOccupancyVsNContribsVsFT0C", kTH3F, {axisTrackOccupancy, axisMultPVContributors, axisMultFT0C}); - histos.add("hTrackOccupancyVsNGlobalTracksVsFT0C", "hTrackOccupancyVsNGlobalTracksVsFT0C", kTH3F, {axisTrackOccupancy, axisMultGlobalTracks, axisMultFT0C}); - histos.add("hFT0COccupancyVsNContribsVsFT0C", "hFT0COccupancyVsNContribsVsFT0C", kTH3F, {axisFT0COccupancy, axisMultPVContributors, axisMultFT0C}); - histos.add("hFT0COccupancyVsNGlobalTracksVsFT0C", "hFT0COccupancyVsNGlobalTracksVsFT0C", kTH3F, {axisFT0COccupancy, axisMultGlobalTracks, axisMultFT0C}); - } - - if (doprocessCollisionsWithCentrality) { - // in case requested: do vs centrality debugging - histos.add("hCentrality", "hCentrality", kTH1F, {axisCentrality}); - histos.add("hNContribsVsCentrality", "hNContribsVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); - histos.add("hNITSTPCTracksVsCentrality", "hNITSTPCTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); - histos.add("hNITSOnlyTracksVsCentrality", "hNITSOnlyTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); - histos.add("hNGlobalTracksVsCentrality", "hNGlobalTracksVsCentrality", kTH2F, {axisCentrality, axisMultPVContributors}); - histos.add("hNMFTTracksVsCentrality", "hNMFTTracksVsCentrality", kTH2F, {axisCentrality, axisMultMFTTracks}); - histos.add("hPVChi2VsCentrality", "hPVChi2VsCentrality", kTH2F, {axisCentrality, axisPVChi2}); - histos.add("hDeltaTimeVsCentrality", "hDeltaTimeVsCentrality", kTH2F, {axisCentrality, axisDeltaTime}); - - if (doOccupancyStudyVsCentrality2d) { - histos.add("hNcontribsProfileVsTrackOccupancyVsCentrality", "hNcontribsProfileVsTrackOccupancyVsCentrality", kTProfile2D, {axisTrackOccupancy, axisCentrality}); - histos.add("hNGlobalTracksProfileVsTrackOccupancyVsCentrality", "hNGlobalTracksProfileVsTrackOccupancyVsCentrality", kTProfile2D, {axisTrackOccupancy, axisCentrality}); - histos.add("hNcontribsProfileVsFT0COccupancyVsCentrality", "hNcontribsProfileVsFT0COccupancyVsCentrality", kTProfile2D, {axisFT0COccupancy, axisCentrality}); - histos.add("hNGlobalTracksProfileVsFT0COccupancyVsCentrality", "hNGlobalTracksProfileVsFT0COccupancyVsCentrality", kTProfile2D, {axisFT0COccupancy, axisCentrality}); - } - - if (doOccupancyStudyVsCentrality3d) { - histos.add("hTrackOccupancyVsNContribsVsCentrality", "hTrackOccupancyVsNContribsVsCentrality", kTH3F, {axisTrackOccupancy, axisMultPVContributors, axisCentrality}); - histos.add("hTrackOccupancyVsNGlobalTracksVsCentrality", "hTrackOccupancyVsNGlobalTracksVsCentrality", kTH3F, {axisTrackOccupancy, axisMultGlobalTracks, axisCentrality}); - histos.add("hFT0COccupancyVsNContribsVsCentrality", "hFT0COccupancyVsNContribsVsCentrality", kTH3F, {axisFT0COccupancy, axisMultPVContributors, axisCentrality}); - histos.add("hFT0COccupancyVsNGlobalTracksVsCentrality", "hFT0COccupancyVsNGlobalTracksVsCentrality", kTH3F, {axisFT0COccupancy, axisMultGlobalTracks, axisCentrality}); - } - } - - if (doTimeStudies) { - ccdb->setURL(ccdbURL); - // ccdb->setCaching(true); - // ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - if (doTimeStudyFV0AOuterVsFT0A3d) { - histos.add((histPath + "h3dFV0AVsTime").c_str(), "", {kTH3F, {{axisDeltaTimestamp, axisMultCoarseFV0A, axisMultCoarseFV0A}}}); - } - } } template @@ -368,8 +399,11 @@ struct centralityStudy { } } - histPath = std::format("Run_{}/", mRunNumber); + if (!studies.doRunByRunHistograms) { + return; + } + histPath = std::format("Run_{}/", mRunNumber); if (doprocessCollisions || doprocessCollisionsWithCentrality) { histPointers.insert({histPath + "hCollisionSelection", histos.add((histPath + "hCollisionSelection").c_str(), "hCollisionSelection", {kTH1D, {{20, -0.5f, +19.5f}}})}); getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(1, "All collisions"); @@ -407,16 +441,15 @@ struct centralityStudy { histPointers.insert({histPath + "hNPVContributors_Unequalized", histos.add((histPath + "hNPVContributors_Unequalized").c_str(), "hNPVContributors_Unequalized", {kTH1D, {{axisMultUltraFinePVContributors}}})}); } - histPointers.insert({histPath + "hFT0CvsPVz_Collisions_All", histos.add((histPath + "hFT0CvsPVz_Collisions_All").c_str(), "hFT0CvsPVz_Collisions_All", {kTProfile, {{axisPVz}}})}); - histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFT0CvsPVz_Collisions", histos.add((histPath + "hFT0CvsPVz_Collisions").c_str(), "hFT0CvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFV0AvsPVz_Collisions", histos.add((histPath + "hFV0AvsPVz_Collisions").c_str(), "hFV0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hNGlobalTracksvsPVz_Collisions", histos.add((histPath + "hNGlobalTracksvsPVz_Collisions").c_str(), "hNGlobalTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hNMFTTracksvsPVz_Collisions", histos.add((histPath + "hNMFTTracksvsPVz_Collisions").c_str(), "hNMFTTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hNTPVvsPVz_Collisions", histos.add((histPath + "hNTPVvsPVz_Collisions").c_str(), "hNTPVvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); } - if (do2DPlots) { + if (studies.do2DPlots) { histPointers.insert({histPath + "hNContribsVsFT0C", histos.add((histPath + "hNContribsVsFT0C").c_str(), "hNContribsVsFT0C", {kTH2F, {{axisMultFT0C, axisMultPVContributors}}})}); histPointers.insert({histPath + "hNContribsVsFV0A", histos.add((histPath + "hNContribsVsFV0A").c_str(), "hNContribsVsFV0A", {kTH2F, {{axisMultFV0A, axisMultPVContributors}}})}); histPointers.insert({histPath + "hMatchedVsITSOnly", histos.add((histPath + "hMatchedVsITSOnly").c_str(), "hMatchedVsITSOnly", {kTH2F, {{axisMultITSOnly, axisMultITSTPC}}})}); @@ -440,7 +473,7 @@ struct centralityStudy { histPointers.insert({histPath + "hDeltaTimeVsCentrality", histos.add((histPath + "hDeltaTimeVsCentrality").c_str(), "hDeltaTimeVsCentrality", {kTH2F, {{axisCentrality, axisDeltaTime}}})}); } - if (doNGlobalTracksVsRawSignals) { + if (studies.doNGlobalTracksVsRawSignals) { histPointers.insert({histPath + "hNGlobalTracksVsFT0A", histos.add((histPath + "hNGlobalTracksVsFT0A").c_str(), "hNGlobalTracksVsFT0A", {kTH2F, {{axisMultFT0A, axisMultGlobalTracks}}})}); histPointers.insert({histPath + "hNGlobalTracksVsFT0C", histos.add((histPath + "hNGlobalTracksVsFT0C").c_str(), "hNGlobalTracksVsFT0C", {kTH2F, {{axisMultFT0C, axisMultGlobalTracks}}})}); histPointers.insert({histPath + "hNGlobalTracksVsFT0M", histos.add((histPath + "hNGlobalTracksVsFT0M").c_str(), "hNGlobalTracksVsFT0M", {kTH2F, {{axisMultFT0M, axisMultGlobalTracks}}})}); @@ -449,7 +482,7 @@ struct centralityStudy { histPointers.insert({histPath + "hNGlobalTracksVsNTPV", histos.add((histPath + "hNGlobalTracksVsNTPV").c_str(), "hNGlobalTracksVsNTPV", {kTH2F, {{axisMultPVContributors, axisMultGlobalTracks}}})}); } - if (doTimeStudies) { + if (studies.doTimeStudies) { histPointers.insert({histPath + "hFT0AVsTime", histos.add((histPath + "hFT0AVsTime").c_str(), "hFT0AVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0A}}})}); histPointers.insert({histPath + "hFT0CVsTime", histos.add((histPath + "hFT0CVsTime").c_str(), "hFT0CVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0C}}})}); histPointers.insert({histPath + "hFT0MVsTime", histos.add((histPath + "hFT0MVsTime").c_str(), "hFT0MVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0M}}})}); @@ -460,9 +493,7 @@ struct centralityStudy { histPointers.insert({histPath + "hNTPVContributorsVsTime", histos.add((histPath + "hNTPVContributorsVsTime").c_str(), "hNTPVContributorsVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultPVContributors}}})}); histPointers.insert({histPath + "hPVzProfileCoVsTime", histos.add((histPath + "hPVzProfileCoVsTime").c_str(), "hPVzProfileCoVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); histPointers.insert({histPath + "hPVzProfileBcVsTime", histos.add((histPath + "hPVzProfileBcVsTime").c_str(), "hPVzProfileBcVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); - if (irDoRateVsTime) { - histPointers.insert({histPath + "hIRProfileVsTime", histos.add((histPath + "hIRProfileVsTime").c_str(), "hIRProfileVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); - } + histPointers.insert({histPath + "hIRProfileVsTime", histos.add((histPath + "hIRProfileVsTime").c_str(), "hIRProfileVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); } } @@ -472,12 +503,18 @@ struct centralityStudy { { initRun(collision); histos.fill(HIST("hCollisionSelection"), 0); // all collisions - getHist(TH1, histPath + "hCollisionSelection")->Fill(0); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(0); + } - if (applySel8 && !collision.multSel8()) + if (evsel.applySel8 && !collision.multSel8()) { return; + } + histos.fill(HIST("hCollisionSelection"), 1); - getHist(TH1, histPath + "hCollisionSelection")->Fill(1); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(1); + } // calculate vertex-Z-equalized quantities if desired float multFV0A = collision.multFV0A(); @@ -515,82 +552,97 @@ struct centralityStudy { } } - bool passRejectITSROFBorder = !(rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)); - bool passRejectTFBorder = !(rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)); - bool passRequireIsVertexITSTPC = !(requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)); - bool passRequireIsGoodZvtxFT0VsPV = !(requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)); - bool passRequireIsVertexTOFmatched = !(requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)); - bool passRequireIsVertexTRDmatched = !(requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)); - bool passRejectSameBunchPileup = !(rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); - bool passRejectITSinROFpileupStandard = !(rejectITSinROFpileupStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)); - bool passRejectITSinROFpileupStrict = !(rejectITSinROFpileupStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)); - bool passSelectUPCcollisions = !(selectUPCcollisions && collision.flags() < 1); - bool passRejectCollInTimeRangeNarrow = !(rejectCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)); + bool passRejectITSROFBorder = !(evsel.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)); + bool passRejectTFBorder = !(evsel.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)); + bool passRequireIsVertexITSTPC = !(evsel.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)); + bool passRequireIsGoodZvtxFT0VsPV = !(evsel.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)); + bool passRequireIsVertexTOFmatched = !(evsel.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)); + bool passRequireIsVertexTRDmatched = !(evsel.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)); + bool passRejectSameBunchPileup = !(evsel.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); + bool passRejectITSinROFpileupStandard = !(evsel.rejectITSinROFpileupStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)); + bool passRejectITSinROFpileupStrict = !(evsel.rejectITSinROFpileupStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)); + bool passSelectUPCcollisions = !(evsel.selectUPCcollisions && collision.flags() < 1); + bool passRejectCollInTimeRangeNarrow = !(evsel.rejectCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)); + // _______________________________________________________ // sidestep vertex-Z rejection for vertex-Z profile histograms - if (passRejectITSROFBorder && passRejectTFBorder && passRequireIsVertexITSTPC && passRequireIsGoodZvtxFT0VsPV && - passRequireIsVertexTOFmatched && passRequireIsVertexTRDmatched && passRejectSameBunchPileup && passRejectITSinROFpileupStandard && passRejectITSinROFpileupStrict && - passSelectUPCcollisions && passRejectCollInTimeRangeNarrow) { - getHist(TProfile, histPath + "hFT0CvsPVz_Collisions_All")->Fill(collision.multPVz(), multFT0C * scaleSignalFT0C); - getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C * scaleSignalFT0C); - getHist(TProfile, histPath + "hFT0AvsPVz_Collisions")->Fill(collision.multPVz(), multFT0A * scaleSignalFT0C); - getHist(TProfile, histPath + "hFV0AvsPVz_Collisions")->Fill(collision.multPVz(), multFV0A * scaleSignalFV0A); - getHist(TProfile, histPath + "hNGlobalTracksvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksGlobal); - getHist(TProfile, histPath + "hNMFTTracksvsPVz_Collisions")->Fill(collision.multPVz(), mftNtracks); - getHist(TProfile, histPath + "hNTPVvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksPV); + if (studies.doRunByRunHistograms) { + if (passRejectITSROFBorder && passRejectTFBorder && passRequireIsVertexITSTPC && passRequireIsGoodZvtxFT0VsPV && + passRequireIsVertexTOFmatched && passRequireIsVertexTRDmatched && passRejectSameBunchPileup && passRejectITSinROFpileupStandard && passRejectITSinROFpileupStrict && + passSelectUPCcollisions && passRejectCollInTimeRangeNarrow) { + getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C * scale.factorFT0C); + getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C * scale.factorFT0C); + getHist(TProfile, histPath + "hFT0AvsPVz_Collisions")->Fill(collision.multPVz(), multFT0A * scale.factorFT0C); + getHist(TProfile, histPath + "hFV0AvsPVz_Collisions")->Fill(collision.multPVz(), multFV0A * scale.factorFV0A); + getHist(TProfile, histPath + "hNGlobalTracksvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksGlobal); + getHist(TProfile, histPath + "hNMFTTracksvsPVz_Collisions")->Fill(collision.multPVz(), mftNtracks); + getHist(TProfile, histPath + "hNTPVvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksPV); + } } // _______________________________________________________ - - if (applyVtxZ && TMath::Abs(collision.multPVz()) > 10) + if (evsel.applyVtxZ && TMath::Abs(collision.multPVz()) > evsel.maxVtxZ) { return; + } + histos.fill(HIST("hCollisionSelection"), 2); - getHist(TH1, histPath + "hCollisionSelection")->Fill(2); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(2); + } // _______________________________________________________ // Extra event selections start here if (!passRejectITSROFBorder) { return; } + histos.fill(HIST("hCollisionSelection"), 3 /* Not at ITS ROF border */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(3); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(3); + } if (!passRejectTFBorder) { return; } histos.fill(HIST("hCollisionSelection"), 4 /* Not at TF border */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(4); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(4); + } if (!passRequireIsVertexITSTPC) { return; } histos.fill(HIST("hCollisionSelection"), 5 /* Contains at least one ITS-TPC track */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(5); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(5); + } if (!passRequireIsGoodZvtxFT0VsPV) { return; } histos.fill(HIST("hCollisionSelection"), 6 /* PV position consistency check */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(6); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(6); + } if (!passRequireIsVertexTOFmatched) { return; } histos.fill(HIST("hCollisionSelection"), 7 /* PV with at least one contributor matched with TOF */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(7); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(7); + } if (!passRequireIsVertexTRDmatched) { return; } histos.fill(HIST("hCollisionSelection"), 8 /* PV with at least one contributor matched with TRD */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(8); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(8); + } if (!passRejectSameBunchPileup) { return; } histos.fill(HIST("hCollisionSelection"), 9 /* Not at same bunch pile-up */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(9); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(9); + } // do this only if information is available if constexpr (requires { collision.timeToNext(); }) { float timeToNeighbour = TMath::Min( @@ -600,51 +652,61 @@ struct centralityStudy { if (timeToNeighbour < minTimeDelta) { return; } - histos.fill(HIST("hCollisionSelection"), 10 /* has suspicious neighbour */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(10); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(10); + } } + histos.fill(HIST("hCollisionSelection"), 10 /* has suspicious neighbour */); if (!passRejectITSinROFpileupStandard) { return; } histos.fill(HIST("hCollisionSelection"), 11 /* Not ITS ROF pileup (standard) */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(11); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(11); + } if (!passRejectITSinROFpileupStrict) { return; } histos.fill(HIST("hCollisionSelection"), 12 /* Not ITS ROF pileup (strict) */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(12); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(12); + } if (!passSelectUPCcollisions) { // if zero then NOT upc, otherwise UPC return; } histos.fill(HIST("hCollisionSelection"), 13 /* is UPC event */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(13); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(13); + } if (!passRejectCollInTimeRangeNarrow) { return; } histos.fill(HIST("hCollisionSelection"), 14 /* Reject collision in narrow time range */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(14); - - if (collision.multFT0C() < upcRejection.maxFT0CforZNACselection && - collision.multZNA() < upcRejection.minZNACsignal && - collision.multZNC() < upcRejection.minZNACsignal) { - return; - } - if (collision.multFT0C() < upcRejection.maxFT0CforFV0Aselection && - collision.multFV0A() < upcRejection.minFV0Asignal) { - return; + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(14); } - if (collision.multFT0C() < upcRejection.maxFT0CforFDDAselection && - collision.multFDDA() < upcRejection.minFDDAsignal) { - return; + + if (evsel.rejectUpc) { + if (collision.multFT0C() < upcRejection.maxFT0CforZNACselection && + collision.multZNA() < upcRejection.minZNACsignal && + collision.multZNC() < upcRejection.minZNACsignal) { + return; + } + if (collision.multFT0C() < upcRejection.maxFT0CforFV0Aselection && + collision.multFV0A() < upcRejection.minFV0Asignal) { + return; + } + if (collision.multFT0C() < upcRejection.maxFT0CforFDDAselection && + collision.multFDDA() < upcRejection.minFDDAsignal) { + return; + } } histos.fill(HIST("hCollisionSelection"), 15 /* pass em/upc rejection */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(15); - - if (rejectIsFlangeEvent) { + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(15); + } + if (evsel.rejectIsFlangeEvent) { if constexpr (requires { collision.ft0TriggerMask(); }) { constexpr int IsFlangeEventId = 7; std::bitset<8> ft0TriggerMask = collision.ft0TriggerMask(); @@ -654,74 +716,79 @@ struct centralityStudy { } } histos.fill(HIST("hCollisionSelection"), 16 /* reject flange events */); - getHist(TH1, histPath + "hCollisionSelection")->Fill(16); - + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCollisionSelection")->Fill(16); + } // if we got here, we also finally fill the FT0C histogram, please histos.fill(HIST("hNPVContributors"), collision.multNTracksPV()); - histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A() * scaleSignalFT0C); - histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C() * scaleSignalFT0C); - histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C()) * scaleSignalFT0M); - histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A() * scaleSignalFV0A); + histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A() * scale.factorFT0C); + histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C() * scale.factorFT0C); + histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C()) * scale.factorFT0M); + histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A() * scale.factorFV0A); histos.fill(HIST("hNGlobalTracks"), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracks"), collision.mftNtracks()); - histos.fill(HIST("hFT0CvsPVz_Collisions_All"), collision.multPVz(), collision.multFT0C() * scaleSignalFT0C); - histos.fill(HIST("hFV0AvsPVz_Collisions"), collision.multPVz(), collision.multFV0A() * scaleSignalFV0A); + histos.fill(HIST("hFT0CvsPVz_Collisions"), collision.multPVz(), collision.multFT0C() * scale.factorFT0C); + histos.fill(HIST("hFT0AvsPVz_Collisions"), collision.multPVz(), collision.multFT0A() * scale.factorFT0A); + histos.fill(HIST("hFV0AvsPVz_Collisions"), collision.multPVz(), collision.multFV0A() * scale.factorFV0A); histos.fill(HIST("hNGlobalTracksvsPVz_Collisions"), collision.multPVz(), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracksvsPVz_Collisions"), collision.multPVz(), collision.mftNtracks()); // save vertex-Z equalized - getHist(TH1, histPath + "hNPVContributors")->Fill(multNTracksPV); - getHist(TH1, histPath + "hFT0A_Collisions")->Fill(multFT0A * scaleSignalFT0A); - getHist(TH1, histPath + "hFT0C_Collisions")->Fill(multFT0C * scaleSignalFT0C); - getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C) * scaleSignalFT0M); - getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A * scaleSignalFV0A); - getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); - getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hNPVContributors")->Fill(multNTracksPV); + getHist(TH1, histPath + "hFT0A_Collisions")->Fill(multFT0A * scale.factorFT0A); + getHist(TH1, histPath + "hFT0C_Collisions")->Fill(multFT0C * scale.factorFT0C); + getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C) * scale.factorFT0M); + getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A * scale.factorFV0A); + getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); + getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); + if (applyVertexZEqualization.value) { + // save unequalized for cross-checks + getHist(TH1, histPath + "hNPVContributors_Unequalized")->Fill(collision.multNTracksPV()); + getHist(TH1, histPath + "hFT0C_Collisions_Unequalized")->Fill(collision.multFT0C() * scale.factorFT0C); + getHist(TH1, histPath + "hFT0M_Collisions_Unequalized")->Fill((collision.multFT0A() + collision.multFT0C()) * scale.factorFT0M); + getHist(TH1, histPath + "hFV0A_Collisions_Unequalized")->Fill(collision.multFV0A() * scale.factorFV0A); + getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); + getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); + } + } - if (applyVertexZEqualization.value) { - // save unequalized for cross-checks - getHist(TH1, histPath + "hNPVContributors_Unequalized")->Fill(collision.multNTracksPV()); - getHist(TH1, histPath + "hFT0C_Collisions_Unequalized")->Fill(collision.multFT0C() * scaleSignalFT0C); - getHist(TH1, histPath + "hFT0M_Collisions_Unequalized")->Fill((collision.multFT0A() + collision.multFT0C()) * scaleSignalFT0M); - getHist(TH1, histPath + "hFV0A_Collisions_Unequalized")->Fill(collision.multFV0A() * scaleSignalFV0A); - getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); - getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); - } - - if (do2DPlots) { - histos.fill(HIST("hNContribsVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multPVTotalContributors()); - histos.fill(HIST("hNContribsVsFV0A"), collision.multFV0A() * scaleSignalFV0A, collision.multPVTotalContributors()); + if (studies.do2DPlots) { + histos.fill(HIST("hNContribsVsFT0C"), collision.multFT0C() * scale.factorFT0C, collision.multPVTotalContributors()); + histos.fill(HIST("hNContribsVsFV0A"), collision.multFV0A() * scale.factorFV0A, collision.multPVTotalContributors()); histos.fill(HIST("hMatchedVsITSOnly"), collision.multNTracksITSOnly(), collision.multNTracksITSTPC()); - getHist(TH2, histPath + "hNContribsVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multPVTotalContributors()); - getHist(TH2, histPath + "hNContribsVsFV0A")->Fill(collision.multFV0A() * scaleSignalFV0A, collision.multPVTotalContributors()); - getHist(TH2, histPath + "hMatchedVsITSOnly")->Fill(collision.multNTracksITSOnly(), collision.multNTracksITSTPC()); - // correlate also FIT detector signals - histos.fill(HIST("hFT0AVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFT0A()); - histos.fill(HIST("hFV0AVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFV0A()); - histos.fill(HIST("hFDDAVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFDDA()); - histos.fill(HIST("hFDDCVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFDDC()); - getHist(TH2, histPath + "hFT0AVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFT0A()); - getHist(TH2, histPath + "hFV0AVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFV0A()); - getHist(TH2, histPath + "hFDDAVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFDDA()); - getHist(TH2, histPath + "hFDDCVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFDDC()); + histos.fill(HIST("hFT0AVsFT0C"), collision.multFT0C() * scale.factorFT0C, collision.multFT0A()); + histos.fill(HIST("hFV0AVsFT0C"), collision.multFT0C() * scale.factorFT0C, collision.multFV0A()); + histos.fill(HIST("hFDDAVsFT0C"), collision.multFT0C() * scale.factorFT0C, collision.multFDDA()); + histos.fill(HIST("hFDDCVsFT0C"), collision.multFT0C() * scale.factorFT0C, collision.multFDDC()); + if (studies.doRunByRunHistograms) { + getHist(TH2, histPath + "hNContribsVsFT0C")->Fill(collision.multFT0C() * scale.factorFT0C, collision.multPVTotalContributors()); + getHist(TH2, histPath + "hNContribsVsFV0A")->Fill(collision.multFV0A() * scale.factorFV0A, collision.multPVTotalContributors()); + getHist(TH2, histPath + "hMatchedVsITSOnly")->Fill(collision.multNTracksITSOnly(), collision.multNTracksITSTPC()); + // correlate also FIT detector signals + getHist(TH2, histPath + "hFT0AVsFT0C")->Fill(collision.multFT0C() * scale.factorFT0C, collision.multFT0A()); + getHist(TH2, histPath + "hFV0AVsFT0C")->Fill(collision.multFT0C() * scale.factorFT0C, collision.multFV0A()); + getHist(TH2, histPath + "hFDDAVsFT0C")->Fill(collision.multFT0C() * scale.factorFT0C, collision.multFDDA()); + getHist(TH2, histPath + "hFDDCVsFT0C")->Fill(collision.multFT0C() * scale.factorFT0C, collision.multFDDC()); + } } - if (doOccupancyStudyVsCentrality2d) { + if (studies.doOccupancyStudyVsCentrality2d) { histos.fill(HIST("hNcontribsProfileVsTrackOccupancyVsFT0C"), collision.trackOccupancyInTimeRange(), collision.multFT0C(), collision.multPVTotalContributors()); histos.fill(HIST("hNGlobalTracksProfileVsTrackOccupancyVsFT0C"), collision.trackOccupancyInTimeRange(), collision.multFT0C(), collision.multNTracksGlobal()); histos.fill(HIST("hNcontribsProfileVsFT0COccupancyVsFT0C"), collision.ft0cOccupancyInTimeRange(), collision.multFT0C(), collision.multPVTotalContributors()); histos.fill(HIST("hNGlobalTracksProfileVsFT0COccupancyVsFT0C"), collision.ft0cOccupancyInTimeRange(), collision.multFT0C(), collision.multNTracksGlobal()); } - if (doOccupancyStudyVsRawValues3d) { + if (studies.doOccupancyStudyVsRawValues3d) { histos.fill(HIST("hTrackOccupancyVsNContribsVsFT0C"), collision.trackOccupancyInTimeRange(), collision.multPVTotalContributors(), collision.multFT0C()); histos.fill(HIST("hTrackOccupancyVsNGlobalTracksVsFT0C"), collision.trackOccupancyInTimeRange(), collision.multNTracksGlobal(), collision.multFT0C()); histos.fill(HIST("hFT0COccupancyVsNContribsVsFT0C"), collision.ft0cOccupancyInTimeRange(), collision.multPVTotalContributors(), collision.multFT0C()); histos.fill(HIST("hFT0COccupancyVsNGlobalTracksVsFT0C"), collision.ft0cOccupancyInTimeRange(), collision.multNTracksGlobal(), collision.multFT0C()); } - if (doNGlobalTracksVsRawSignals) { + if (studies.doNGlobalTracksVsRawSignals) { histos.fill(HIST("hNGlobalTracksVsFT0A"), multFT0A, multNTracksGlobal); histos.fill(HIST("hNGlobalTracksVsFT0C"), multFT0C, multNTracksGlobal); histos.fill(HIST("hNGlobalTracksVsFT0M"), (multFT0A + multFT0C), multNTracksGlobal); @@ -730,12 +797,14 @@ struct centralityStudy { histos.fill(HIST("hNGlobalTracksVsNTPV"), multNTracksPV, multNTracksGlobal); // per run - getHist(TH2, histPath + "hNGlobalTracksVsFT0A")->Fill(multFT0A, multNTracksGlobal); - getHist(TH2, histPath + "hNGlobalTracksVsFT0C")->Fill(multFT0C, multNTracksGlobal); - getHist(TH2, histPath + "hNGlobalTracksVsFT0M")->Fill(multFT0A + multFT0C, multNTracksGlobal); - getHist(TH2, histPath + "hNGlobalTracksVsFV0A")->Fill(multFV0A, multNTracksGlobal); - getHist(TH2, histPath + "hNGlobalTracksVsNMFTTracks")->Fill(mftNtracks, multNTracksGlobal); - getHist(TH2, histPath + "hNGlobalTracksVsNTPV")->Fill(multNTracksPV, multNTracksGlobal); + if (studies.doRunByRunHistograms) { + getHist(TH2, histPath + "hNGlobalTracksVsFT0A")->Fill(multFT0A, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFT0C")->Fill(multFT0C, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFT0M")->Fill(multFT0A + multFT0C, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFV0A")->Fill(multFV0A, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsNMFTTracks")->Fill(mftNtracks, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsNTPV")->Fill(multNTracksPV, multNTracksGlobal); + } } if constexpr (requires { collision.multMCExtraId(); }) { @@ -766,22 +835,23 @@ struct centralityStudy { histos.fill(HIST("hNGlobalTracksVsCentrality"), collision.centFT0C(), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracksVsCentrality"), collision.centFT0C(), collision.mftNtracks()); histos.fill(HIST("hPVChi2VsCentrality"), collision.centFT0C(), collision.multPVChi2()); - getHist(TH1, histPath + "hCentrality")->Fill(collision.centFT0C()); - getHist(TH2, histPath + "hNContribsVsCentrality")->Fill(collision.centFT0C(), collision.multPVTotalContributors()); - getHist(TH2, histPath + "hNITSTPCTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSTPC()); - getHist(TH2, histPath + "hNITSOnlyTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSOnly()); - getHist(TH2, histPath + "hNGlobalTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksGlobal()); - getHist(TH2, histPath + "hNMFTTracksVsCentrality")->Fill(collision.centFT0C(), collision.mftNtracks()); - getHist(TH2, histPath + "hPVChi2VsCentrality")->Fill(collision.centFT0C(), collision.multPVChi2()); - - if (doOccupancyStudyVsCentrality2d) { + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hCentrality")->Fill(collision.centFT0C()); + getHist(TH2, histPath + "hNContribsVsCentrality")->Fill(collision.centFT0C(), collision.multPVTotalContributors()); + getHist(TH2, histPath + "hNITSTPCTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSTPC()); + getHist(TH2, histPath + "hNITSOnlyTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSOnly()); + getHist(TH2, histPath + "hNGlobalTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksGlobal()); + getHist(TH2, histPath + "hNMFTTracksVsCentrality")->Fill(collision.centFT0C(), collision.mftNtracks()); + getHist(TH2, histPath + "hPVChi2VsCentrality")->Fill(collision.centFT0C(), collision.multPVChi2()); + } + if (studies.doOccupancyStudyVsCentrality2d) { histos.fill(HIST("hNcontribsProfileVsTrackOccupancyVsCentrality"), collision.trackOccupancyInTimeRange(), collision.centFT0C(), collision.multPVTotalContributors()); histos.fill(HIST("hNGlobalTracksProfileVsTrackOccupancyVsCentrality"), collision.trackOccupancyInTimeRange(), collision.centFT0C(), collision.multNTracksGlobal()); histos.fill(HIST("hNcontribsProfileVsFT0COccupancyVsCentrality"), collision.ft0cOccupancyInTimeRange(), collision.centFT0C(), collision.multPVTotalContributors()); histos.fill(HIST("hNGlobalTracksProfileVsFT0COccupancyVsCentrality"), collision.ft0cOccupancyInTimeRange(), collision.centFT0C(), collision.multNTracksGlobal()); } - if (doOccupancyStudyVsCentrality3d) { + if (studies.doOccupancyStudyVsCentrality3d) { histos.fill(HIST("hTrackOccupancyVsNContribsVsCentrality"), collision.trackOccupancyInTimeRange(), collision.multPVTotalContributors(), collision.centFT0C()); histos.fill(HIST("hTrackOccupancyVsNGlobalTracksVsCentrality"), collision.trackOccupancyInTimeRange(), collision.multNTracksGlobal(), collision.centFT0C()); histos.fill(HIST("hFT0COccupancyVsNContribsVsCentrality"), collision.ft0cOccupancyInTimeRange(), collision.multPVTotalContributors(), collision.centFT0C()); @@ -790,28 +860,24 @@ struct centralityStudy { } if constexpr (requires { collision.has_multBC(); }) { - if (doTimeStudies && collision.has_multBC()) { + if (collision.has_multBC()) { initRun(collision); auto multbc = collision.template multBC_as(); uint64_t bcTimestamp = multbc.timestamp(); - float hoursAfterStartOfRun = static_cast(bcTimestamp - startOfRunTimestamp) / 3600000.0; - - getHist(TH2, histPath + "hFT0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0A()); - getHist(TH2, histPath + "hFT0CVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0C()); - getHist(TH2, histPath + "hFT0MVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0M()); - getHist(TH2, histPath + "hFV0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0A()); - getHist(TH2, histPath + "hFV0AOuterVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0AOuter()); - getHist(TH2, histPath + "hMFTTracksVsTime")->Fill(hoursAfterStartOfRun, collision.mftNtracks()); - getHist(TH2, histPath + "hNGlobalVsTime")->Fill(hoursAfterStartOfRun, collision.multNTracksGlobal()); - getHist(TH2, histPath + "hNTPVContributorsVsTime")->Fill(hoursAfterStartOfRun, collision.multPVTotalContributors()); - getHist(TProfile, histPath + "hPVzProfileCoVsTime")->Fill(hoursAfterStartOfRun, collision.multPVz()); - getHist(TProfile, histPath + "hPVzProfileBcVsTime")->Fill(hoursAfterStartOfRun, multbc.multFT0PosZ()); - if (doTimeStudyFV0AOuterVsFT0A3d) { - histos.fill(HIST("h3dFV0AVsTime"), hoursAfterStartOfRun, collision.multFV0A(), collision.multFV0AOuter()); - } - - if (irDoRateVsTime) { - float interactionRate = mRateFetcher.fetch(ccdb.service, bcTimestamp, mRunNumber, irSource.value, irCrashOnNull) / 1000.; // kHz + const float hoursAfterStartOfRun = static_cast(bcTimestamp - startOfRunTimestamp) / 3600000.0; + const float interactionRate = mRateFetcher.fetch(ccdb.service, bcTimestamp, mRunNumber, irSource.value, irCrashOnNull) / 1000.; // kHz + + if (studies.doTimeStudies && studies.doRunByRunHistograms) { + getHist(TH2, histPath + "hFT0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0A()); + getHist(TH2, histPath + "hFT0CVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0C()); + getHist(TH2, histPath + "hFT0MVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0M()); + getHist(TH2, histPath + "hFV0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0A()); + getHist(TH2, histPath + "hFV0AOuterVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0AOuter()); + getHist(TH2, histPath + "hMFTTracksVsTime")->Fill(hoursAfterStartOfRun, collision.mftNtracks()); + getHist(TH2, histPath + "hNGlobalVsTime")->Fill(hoursAfterStartOfRun, collision.multNTracksGlobal()); + getHist(TH2, histPath + "hNTPVContributorsVsTime")->Fill(hoursAfterStartOfRun, collision.multPVTotalContributors()); + getHist(TProfile, histPath + "hPVzProfileCoVsTime")->Fill(hoursAfterStartOfRun, collision.multPVz()); + getHist(TProfile, histPath + "hPVzProfileBcVsTime")->Fill(hoursAfterStartOfRun, multbc.multFT0PosZ()); getHist(TProfile, histPath + "hIRProfileVsTime")->Fill(hoursAfterStartOfRun, interactionRate); } } @@ -838,73 +904,144 @@ struct centralityStudy { genericProcessCollision(collision); } - void processBCs(soa::Join::iterator const& multbc, soa::Join const&) + template + bool selectedBC(const TBunchCrossing& bc, bool fillHistograms = false) { - // process BCs, calculate FT0C distribution // conditionals suggested by FIT team (Jacek O. et al) - histos.fill(HIST("hBCSelection"), 0); // all BCs + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 0); // all BCs + } - if (selectCollidingBCs && !multbc.multCollidingBC()) - return; - histos.fill(HIST("hBCSelection"), 1); // colliding + if (bcsel.selectCollidingBCs && !bc.multCollidingBC()) { + return false; + } - if (selectTVX && !multbc.multTVX()) - return; - histos.fill(HIST("hBCSelection"), 2); // TVX + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 1); // colliding + } - if (selectFV0OrA && !multbc.multFV0OrA()) - return; - histos.fill(HIST("hBCSelection"), 3); // FV0OrA + if (bcsel.selectTVX && !bc.multTVX()) { + return false; + } - if (vertexZwithT0 < 100.0f) { - if (!multbc.multFT0PosZValid()) - return; - if (TMath::Abs(multbc.multFT0PosZ()) > vertexZwithT0) - return; + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 2); // TVX } - histos.fill(HIST("hBCSelection"), 4); // FT0PosZ - if (multbc.multFT0C() < upcRejection.maxFT0CforZNACselection && - multbc.multZNA() < upcRejection.minZNACsignal && - multbc.multZNC() < upcRejection.minZNACsignal) { - return; + if (bcsel.selectFV0OrA && !bc.multFV0OrA()) { + return false; } - if (multbc.multFT0C() < upcRejection.maxFT0CforFV0Aselection && - multbc.multFV0A() < upcRejection.minFV0Asignal) { - return; + + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 3); // FV0OrA } - if (multbc.multFT0C() < upcRejection.maxFT0CforFDDAselection && - multbc.multFDDA() < upcRejection.minFDDAsignal) { - return; + + if (bcsel.vertexZwithT0 < 100.0f) { + if (!bc.multFT0PosZValid()) { + return false; + } + if (TMath::Abs(bc.multFT0PosZ()) > bcsel.vertexZwithT0) { + return false; + } } - histos.fill(HIST("hBCSelection"), 5); // znac amp - if (rejectZNAC && !multbc.selection_bit(o2::aod::evsel::kIsBBZNA) && !multbc.selection_bit(o2::aod::evsel::kIsBBZNC)) { - return; + + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 4); // FT0PosZ } - histos.fill(HIST("hBCSelection"), 6); // znac time - // if we got here, we also finally fill the FT0C histogram, please - histos.fill(HIST("hFT0C_BCs"), multbc.multFT0C() * scaleSignalFT0C); + if (bcsel.rejectUpc) { + if (bc.multFT0C() < upcRejection.maxFT0CforZNACselection && + bc.multZNA() < upcRejection.minZNACsignal && + bc.multZNC() < upcRejection.minZNACsignal) { + return false; + } + if (bc.multFT0C() < upcRejection.maxFT0CforFV0Aselection && + bc.multFV0A() < upcRejection.minFV0Asignal) { + return false; + } + if (bc.multFT0C() < upcRejection.maxFT0CforFDDAselection && + bc.multFDDA() < upcRejection.minFDDAsignal) { + return false; + } + } + + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 5); // znac amp + } + + if (bcsel.rejectZNAC && !bc.selection_bit(o2::aod::evsel::kIsBBZNA) && !bc.selection_bit(o2::aod::evsel::kIsBBZNC)) { + return false; + } - // ZN signals - histos.fill(HIST("hZNAvsFT0C_BCs"), multbc.multFT0C() * scaleSignalFT0C, multbc.multZNA()); - histos.fill(HIST("hZNCvsFT0C_BCs"), multbc.multFT0C() * scaleSignalFT0C, multbc.multZNC()); + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 6); // znac time + } - histos.fill(HIST("hFT0M_BCs"), (multbc.multFT0A() + multbc.multFT0C()) * scaleSignalFT0M); - histos.fill(HIST("hFV0A_BCs"), multbc.multFV0A() * scaleSignalFV0A); - if (multbc.multFT0PosZValid()) { - histos.fill(HIST("hFT0CvsPVz_BCs_All"), multbc.multFT0PosZ(), multbc.multFT0C() * scaleSignalFT0C); - if (multbc.multFT0C() > minFT0CforVertexZ) { - histos.fill(HIST("hFT0CvsPVz_BCs"), multbc.multFT0PosZ(), multbc.multFT0C() * scaleSignalFT0C); + if (bcsel.rejectIsFlangeEvent) { + constexpr int IsFlangeEventId = 7; + std::bitset<8> ft0TriggerMask = bc.multT0triggerBits(); + if (ft0TriggerMask[IsFlangeEventId]) { + return false; } } - if (multbc.has_ft0Mult()) { - auto multco = multbc.ft0Mult_as>(); + if (fillHistograms) { + histos.fill(HIST("hBCSelection"), 7); // isFlangeEvent + } + + return true; + } + + void processBCs(soa::Join const& multbcs, soa::Join const&) + { + // process BCs, calculate FT0C distribution + for (const auto& multbc : multbcs) { + if (!selectedBC(multbc, true)) { + continue; + } + + // if we got here, we also finally fill the FT0C histogram, please + histos.fill(HIST("hFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C); + histos.fill(HIST("hFT0A_BCs"), multbc.multFT0A() * scale.factorFT0A); + histos.fill(HIST("hFT0M_BCs"), (multbc.multFT0A() + multbc.multFT0C()) * scale.factorFT0M); + histos.fill(HIST("hFV0A_BCs"), multbc.multFV0A() * scale.factorFV0A); + histos.fill(HIST("hFV0AT0C_BCs"), (multbc.multFV0A() + multbc.multFT0C()) * scale.factorFV0AT0C); + + if (studies.do2DPlots) { + histos.fill(HIST("hFT0AVsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multFT0A() * scale.factorFT0A); + histos.fill(HIST("hFV0AVsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multFV0A() * scale.factorFV0A); + } + + // ZN signals + histos.fill(HIST("hZNAvsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multZNA()); + histos.fill(HIST("hZNCvsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multZNC()); + if (multbc.multFT0PosZValid()) { - histos.fill(HIST("hVertexZ_BCvsCO"), multco.multPVz(), multbc.multFT0PosZ()); + histos.fill(HIST("hFT0CvsPVz_BCs_All"), multbc.multFT0PosZ(), multbc.multFT0C() * scale.factorFT0C); + if (multbc.multFT0C() > bcsel.minFT0CforVertexZ) { + histos.fill(HIST("hFT0CvsPVz_BCs"), multbc.multFT0PosZ(), multbc.multFT0C() * scale.factorFT0C); + } + } + + if (multbc.has_ft0Mult()) { + auto multco = multbc.ft0Mult_as>(); + if (multbc.multFT0PosZValid()) { + histos.fill(HIST("hVertexZ_BCvsCO"), multco.multPVz(), multbc.multFT0PosZ()); + } } } + + for (const auto& multbc : multbcs) { + if (!selectedBC(multbc, false)) { + continue; + } + + const float selfNormFV0A = scale.normFT0A * multbc.multFV0A() / histos.get(HIST("hFT0A_BCs"))->GetMean(); + const float selfNormFT0A = scale.normFV0A * multbc.multFT0A() / histos.get(HIST("hFT0C_BCs"))->GetMean(); + const float selfNormFT0C = scale.normFT0C * multbc.multFT0C() / histos.get(HIST("hFV0A_BCs"))->GetMean(); + histos.fill(HIST("hScaledFT0M_BCs"), selfNormFT0A + selfNormFT0C); + histos.fill(HIST("hScaledFV0AT0C_BCs"), selfNormFV0A + selfNormFT0C); + } } PROCESS_SWITCH(centralityStudy, processCollisions, "per-collision analysis", false); From dae60f5339d2ed4842f18e6fb2becfd7be9ba707 Mon Sep 17 00:00:00 2001 From: CyF1rmiana <3326561594@qq.com> Date: Thu, 7 May 2026 13:59:12 +0800 Subject: [PATCH 071/449] [PWGCF] Add plots for Q-vector check (#16137) Co-authored-by: Shiqi Wang --- PWGCF/Flow/Tasks/flowEseTask.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEseTask.cxx b/PWGCF/Flow/Tasks/flowEseTask.cxx index 185ba488672..a4d66a46944 100644 --- a/PWGCF/Flow/Tasks/flowEseTask.cxx +++ b/PWGCF/Flow/Tasks/flowEseTask.cxx @@ -157,8 +157,8 @@ struct FlowEseTask { ConfigurableAxis multAxis{"multAxis", {300, 0, 2700}, "multiplicity"}; ConfigurableAxis qvecAxis{"qvecAxis", {300, -1, 1}, "range of Qvector component"}; ConfigurableAxis qvec2Axis{"qvec2Axis", {600, 0, 600}, "range of Qvector Module"}; - ConfigurableAxis lowerQAxis = {"lowerQAxis", {900, 0.0, 900.0}, "range of lowerQ QAplots"}; - ConfigurableAxis upperQAxis = {"upperQAxis", {200, 0.0, 20.0}, "range of upperQ QAplots"}; + ConfigurableAxis lowerQAxis = {"lowerQAxis", {800, 0.0, 800.0}, "range of lowerQ QAplots"}; + ConfigurableAxis upperQAxis = {"upperQAxis", {300, 0.0, 6.0}, "range of upperQ QAplots"}; ConfigurableAxis lowerQAxisTPC = {"lowerQAxisTPC", {150, 0.0, 150.0}, "range of lowerQTPC QAplots"}; ConfigurableAxis upperQAxisTPC = {"upperQAxisTPC", {100, 0.0, 10.0}, "range of upperQTPC QAplots"}; @@ -234,6 +234,7 @@ struct FlowEseTask { AxisSpec basisAxis = {20, 0, 20, "basis"}; histos.add(Form("histQvecV2"), "", {HistType::kTH3F, {qvecAxis, qvecAxis, centAxis}}); + histos.add(Form("histQvecCent"), "", {HistType::kTH3F, {lowerQAxis, upperQAxis, centQaAxis}}); histos.add(Form("histMultCor"), "", {HistType::kTH2F, {multAxis, centAxis}}); histos.add(Form("histMultUncor"), "", {HistType::kTH2F, {multAxis, centAxis}}); histos.add(Form("histLowerQvecCentCor"), "", {HistType::kTH2F, {lowerQAxis, centQaAxis}}); @@ -733,6 +734,8 @@ struct FlowEseTask { } } + histos.fill(HIST("histQvecCent"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), + std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]), centrality); histos.fill(HIST("histLowerQvecCentCor"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * collision.sumAmplFT0C() / std::sqrt(collision.multFT0C()), centrality); histos.fill(HIST("histLowerQvecCentUncor"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), centrality); histos.fill(HIST("histUpperQvecCent"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]), centrality); From 865d6dc227baacfd50460aabfb23734dd87a6d34 Mon Sep 17 00:00:00 2001 From: jaimenorman Date: Thu, 7 May 2026 08:39:22 +0100 Subject: [PATCH 072/449] [PWGJE] add event selection (#16123) --- PWGJE/Tasks/jetFinderQA.cxx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index 45110192fa8..0a8cc908ad6 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -953,6 +953,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -972,6 +975,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -991,6 +997,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1008,6 +1017,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1025,6 +1037,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1045,6 +1060,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (const auto& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1071,6 +1089,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1088,6 +1109,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1161,6 +1185,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1191,6 +1218,9 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; From 2da53ff7eb65ba5e58ceaa1076cbf82a88ad49ff Mon Sep 17 00:00:00 2001 From: Kegang Xiong Date: Thu, 7 May 2026 17:18:58 +0800 Subject: [PATCH 073/449] [PWGCF] Save the zdc tree (#16139) Co-authored-by: kegangxiong Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowZdcEnergy.cxx | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx index 742fd5248c0..e1366124622 100644 --- a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx +++ b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx @@ -42,6 +42,36 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +namespace o2::aod +{ +namespace zdctree +{ +DECLARE_SOA_COLUMN(Znac, znac, float); +DECLARE_SOA_COLUMN(Zna1, zna1, float); +DECLARE_SOA_COLUMN(Zna2, zna2, float); +DECLARE_SOA_COLUMN(Zna3, zna3, float); +DECLARE_SOA_COLUMN(Zna4, zna4, float); +DECLARE_SOA_COLUMN(Zncc, zncc, float); +DECLARE_SOA_COLUMN(Znc1, znc1, float); +DECLARE_SOA_COLUMN(Znc2, znc2, float); +DECLARE_SOA_COLUMN(Znc3, znc3, float); +DECLARE_SOA_COLUMN(Znc4, znc4, float); +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +} // namespace zdctree +DECLARE_SOA_TABLE(ZdcTree, "AOD", "ZDCTREE", + zdctree::Znac, + zdctree::Zna1, + zdctree::Zna2, + zdctree::Zna3, + zdctree::Zna4, + zdctree::Zncc, + zdctree::Znc1, + zdctree::Znc2, + zdctree::Znc3, + zdctree::Znc4, + zdctree::Multiplicity); +} // namespace o2::aod + #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct FlowZdcEnergy { @@ -73,6 +103,7 @@ struct FlowZdcEnergy { Service ccdb; HistogramRegistry registry{"registry"}; + Produces zdcTree; Filter trackFilter = nabs(aod::track::eta) < cfgEtaMax && aod::track::pt > cfgPtMin&& aod::track::pt < cfgPtMax&& nabs(aod::track::dcaXY) < cfgDcaXYMax&& nabs(aod::track::dcaZ) < cfgDcaZMax; using UsedTracks = soa::Filtered>; @@ -204,6 +235,18 @@ struct FlowZdcEnergy { const float energySectorZNC3 = zdc.energySectorZNC()[2]; const float energySectorZNC4 = zdc.energySectorZNC()[3]; + zdcTree(energyCommonZNA, + energySectorZNA1, + energySectorZNA2, + energySectorZNA3, + energySectorZNA4, + energyCommonZNC, + energySectorZNC1, + energySectorZNC2, + energySectorZNC3, + energySectorZNC4, + multiTPC); + const float sumEnergyZNA = energySectorZNA1 + energySectorZNA2 + energySectorZNA3 + energySectorZNA4; const float sumEnergyZNC = energySectorZNC1 + energySectorZNC2 + energySectorZNC3 + energySectorZNC4; From 85f34766d9ffc24d9b883452f6c081f3f884491e Mon Sep 17 00:00:00 2001 From: rolavick Date: Thu, 7 May 2026 12:34:23 +0200 Subject: [PATCH 074/449] [PWGUD] New personal task to run over forward tracks (#16140) Co-authored-by: ALICE Action Bot --- .../upcCandProducerGlobalMuon.cxx | 9 +- PWGUD/Tasks/CMakeLists.txt | 5 + PWGUD/Tasks/upcFwdJpsiRl.cxx | 571 ++++++++++++++++++ 3 files changed, 581 insertions(+), 4 deletions(-) create mode 100644 PWGUD/Tasks/upcFwdJpsiRl.cxx diff --git a/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx b/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx index 76d6412249b..58a6654d4fe 100644 --- a/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx +++ b/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx @@ -143,10 +143,11 @@ struct UpcCandProducerGlobalMuon { // NEW: Add histograms for global track monitoring const AxisSpec axisTrackType{5, -0.5, 4.5, "Track Type"}; histRegistry.add("hTrackTypes", "Track type distribution", kTH1F, {axisTrackType}); - histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(1, "MuonStandalone"); - histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(2, "MCHStandalone"); - histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(3, "GlobalMuon"); - histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(4, "GlobalFwd"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(1, "GlobalMuonTrack"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(2, "GlobalMuonTrackOtherMatch"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(3, "GlobalForwardTrack"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(4, "MuonStandaloneTrack"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(5, "MCHStandaloneTrack"); const AxisSpec axisEta{100, -4.0, -2.0, "#eta"}; histRegistry.add("hEtaGlobal", "Global track eta", kTH1F, {axisEta}); diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 3f5c41c0c25..5fe01ad5980 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -204,6 +204,11 @@ o2physics_add_dpl_workflow(fwd-muons-upc PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(upc-fwd-jpsi-rl + SOURCES upcFwdJpsiRl.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc-event-itsrof-counter SOURCES upcEventITSROFcounter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB diff --git a/PWGUD/Tasks/upcFwdJpsiRl.cxx b/PWGUD/Tasks/upcFwdJpsiRl.cxx new file mode 100644 index 00000000000..8f42e1e8cb4 --- /dev/null +++ b/PWGUD/Tasks/upcFwdJpsiRl.cxx @@ -0,0 +1,571 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file UpcFwdJpsiRl.cxx +/// \brief UPC forward J/psi analysis with configurable track-type candidate selection +/// \author Roman Lavicka, roman.lavicka@cern.ch +/// \since 07.05.2026 +/// +/// Candidate types (configured via candidateType): +/// 0 = GlobalMuon-GlobalMuon: both tracks are GlobalMuonTrack (enum 0) or GlobalMuonTrackOtherMatch (enum 1) +/// 1 = Mixed: at least one GlobalMuonTrack (enum 0,1) and the other MuonStandaloneTrack (enum 3) +/// 2 = MuonStandalone-MuonStandalone: both tracks are MuonStandaloneTrack (enum 3) + +/// executable name o2-analysis-ud-upc-fwd-jpsi-rl + +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +// table for saving tree with info on data +namespace jpsirl +{ +// dimuon +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Px, px, float); +DECLARE_SOA_COLUMN(Py, py, float); +DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(PhiAv, phiAv, float); +DECLARE_SOA_COLUMN(PhiCh, phiCh, float); +// tracks positive (p) and negative (n) +DECLARE_SOA_COLUMN(EnergyP, energyP, float); +DECLARE_SOA_COLUMN(Pxp, pxp, float); +DECLARE_SOA_COLUMN(Pyp, pyp, float); +DECLARE_SOA_COLUMN(Pzp, pzp, float); +DECLARE_SOA_COLUMN(Ptp, ptp, float); +DECLARE_SOA_COLUMN(Etap, etap, float); +DECLARE_SOA_COLUMN(Phip, phip, float); +DECLARE_SOA_COLUMN(TrackTypep, trackTypep, int); +DECLARE_SOA_COLUMN(EnergyN, energyN, float); +DECLARE_SOA_COLUMN(Pxn, pxn, float); +DECLARE_SOA_COLUMN(Pyn, pyn, float); +DECLARE_SOA_COLUMN(Pzn, pzn, float); +DECLARE_SOA_COLUMN(Ptn, ptn, float); +DECLARE_SOA_COLUMN(Etan, etan, float); +DECLARE_SOA_COLUMN(Phin, phin, float); +DECLARE_SOA_COLUMN(TrackTypen, trackTypen, int); +// zn +DECLARE_SOA_COLUMN(Tzna, tzna, float); +DECLARE_SOA_COLUMN(Ezna, ezna, float); +DECLARE_SOA_COLUMN(Tznc, tznc, float); +DECLARE_SOA_COLUMN(Eznc, eznc, float); +DECLARE_SOA_COLUMN(Nclass, nclass, int); +} // namespace jpsirl + +namespace o2::aod +{ +DECLARE_SOA_TABLE(JpsiRL, "AOD", "JPSI", + jpsirl::RunNumber, + jpsirl::M, jpsirl::Energy, jpsirl::Px, jpsirl::Py, jpsirl::Pz, jpsirl::Pt, jpsirl::Rap, jpsirl::Phi, + jpsirl::PhiAv, jpsirl::PhiCh, + jpsirl::EnergyP, jpsirl::Pxp, jpsirl::Pyp, jpsirl::Pzp, jpsirl::Ptp, jpsirl::Etap, jpsirl::Phip, jpsirl::TrackTypep, + jpsirl::EnergyN, jpsirl::Pxn, jpsirl::Pyn, jpsirl::Pzn, jpsirl::Ptn, jpsirl::Etan, jpsirl::Phin, jpsirl::TrackTypen, + jpsirl::Tzna, jpsirl::Ezna, jpsirl::Tznc, jpsirl::Eznc, jpsirl::Nclass); +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::fwdtrack; + +// constants used in the track selection +const float kRAbsMin = 17.6; +const float kRAbsMid = 26.5; +const float kRAbsMax = 89.5; +const float kPDca1 = 200.; +const float kPDca2 = 200.; +const float kEtaMin = -4.0; +const float kEtaMax = -2.5; +const float kPtMin = 0.; + +const float kMaxAmpV0A = 100.; +const float kMaxZDCTime = 2.; +const float kMaxZDCTimeHisto = 10.; +const float kInvalidFloat = -999.; +const int kMaxRelBCsV0A = 1; +const int kNMuons = 2; + +struct UpcFwdJpsiRl { + + using CandidatesFwd = soa::Join; + using ForwardTracks = soa::Join; + + Produces dimuSel; + + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry reg0n0n{"reg0n0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXn0n{"regXn0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXnXn{"regXnXn", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // CONFIGURABLES + static constexpr double Pi = o2::constants::math::PI; + // candidate type selection + // 0 = GlobalMuon-GlobalMuon (both tracks enum 0 or 1) + // 1 = Mixed (one GlobalMuon enum 0,1 + one MuonStandalone enum 3) + // 2 = MuonStandalone-MuonStandalone (both tracks enum 3) + Configurable candidateType{"candidateType", 0, "Candidate type: 0=GlobalMuon-GlobalMuon, 1=Mixed, 2=MuonStandalone-MuonStandalone"}; + // pT of muon pairs + Configurable nBinsPt{"nBinsPt", 250, "N bins in pT histo"}; + Configurable lowPt{"lowPt", 0., "lower limit in pT histo"}; + Configurable highPt{"highPt", 2, "upper limit in pT histo"}; + // mass of muon pairs + Configurable nBinsMass{"nBinsMass", 500, "N bins in mass histo"}; + Configurable lowMass{"lowMass", 0., "lower limit in mass histo"}; + Configurable highMass{"highMass", 10., "upper limit in mass histo"}; + // eta of muon pairs + Configurable nBinsEta{"nBinsEta", 600, "N bins in eta histo"}; + Configurable lowEta{"lowEta", -10., "lower limit in eta histo"}; + Configurable highEta{"highEta", -2., "upper limit in eta histo"}; + // rapidity of muon pairs + Configurable nBinsRapidity{"nBinsRapidity", 250, "N bins in rapidity histo"}; + Configurable lowRapidity{"lowRapidity", -4.5, "lower limit in rapidity histo"}; + Configurable highRapidity{"highRapidity", -2., "upper limit in rapidity histo"}; + // phi of muon pairs + Configurable nBinsPhi{"nBinsPhi", 600, "N bins in phi histo"}; + Configurable lowPhi{"lowPhi", -Pi, "lower limit in phi histo"}; + Configurable highPhi{"highPhi", Pi, "upper limit in phi histo"}; + // pT of single muons + Configurable nBinsPtSingle{"nBinsPtSingle", 500, "N bins in pT histo single muon"}; + Configurable lowPtSingle{"lowPtSingle", 0., "lower limit in pT histo single muon"}; + Configurable highPtSingle{"highPtSingle", 2., "upper limit in pT histo single muon"}; + // eta of single muons + Configurable nBinsEtaSingle{"nBinsEtaSingle", 250, "N bins in eta histo single muon"}; + Configurable lowEtaSingle{"lowEtaSingle", -4.5, "lower limit in eta histo single muon"}; + Configurable highEtaSingle{"highEtaSingle", -2., "upper limit in eta histo single muon"}; + // phi of single muons + Configurable nBinsPhiSingle{"nBinsPhiSingle", 600, "N bins in phi histo single muon"}; + Configurable lowPhiSingle{"lowPhiSingle", -Pi, "lower limit in phi histo single muon"}; + Configurable highPhiSingle{"highPhiSingle", Pi, "upper limit in phi histo single muon"}; + // ZDC + Configurable nBinsZDCen{"nBinsZDCen", 200, "N bins in ZN energy"}; + Configurable lowEnZN{"lowEnZN", -50., "lower limit in ZN energy histo"}; + Configurable highEnZN{"highEnZN", 250., "upper limit in ZN energy histo"}; + + void init(InitContext&) + { + // binning of pT axis for fit + std::vector ptFitBinning = { + 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, + 0.11, 0.12, 0.13, 0.14, 0.15, 0.175, 0.20, 0.25, 0.30, 0.40, 0.50, + 0.60, 0.70, 0.80, 0.90, 1.00, 1.20, 1.40, 1.60, 1.80, 2.00, 2.50, + 3.00, 3.50}; + + std::vector ptFitBinningHalfWidth = { + 0.00, 0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05, + 0.055, 0.06, 0.065, 0.07, 0.075, 0.08, 0.085, 0.09, 0.095, 0.10, + 0.105, 0.11, 0.115, 0.12, 0.125, 0.13, 0.135, 0.14, 0.145, 0.15, + 0.1625, 0.175, 0.1875, 0.20, 0.225, 0.25, 0.275, 0.30, 0.35, 0.40, + 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, + 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.25, + 2.50, 2.75, 3.00, 3.25, 3.50}; + + // axes + const AxisSpec axisPt{nBinsPt, lowPt, highPt, "#it{p}_{T} GeV/#it{c}"}; + const AxisSpec axisPtFit = {ptFitBinning, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisPtFit2 = {ptFitBinningHalfWidth, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisMass{nBinsMass, lowMass, highMass, "m_{#mu#mu} GeV/#it{c}^{2}"}; + const AxisSpec axisEta{nBinsEta, lowEta, highEta, "#eta"}; + const AxisSpec axisRapidity{nBinsRapidity, lowRapidity, highRapidity, "Rapidity"}; + const AxisSpec axisPhi{nBinsPhi, lowPhi, highPhi, "#varphi"}; + const AxisSpec axisPtSingle{nBinsPtSingle, lowPtSingle, highPtSingle, "#it{p}_{T}_{ trk} GeV/#it{c}"}; + const AxisSpec axisTimeZN{200, -10, 10, "ZDC time (ns)"}; + const AxisSpec axisEnergyZNA{nBinsZDCen, lowEnZN, highEnZN, "ZNA energy (TeV)"}; + const AxisSpec axisEnergyZNC{nBinsZDCen, lowEnZN, highEnZN, "ZNC energy (TeV)"}; + const AxisSpec axisEtaSingle{nBinsEtaSingle, lowEtaSingle, highEtaSingle, "#eta_{trk}"}; + const AxisSpec axisPhiSingle{nBinsPhiSingle, lowPhiSingle, highPhiSingle, "#varphi_{trk}"}; + + // histos + registry.add("hMass", "Invariant mass of muon pairs;;#counts", kTH1D, {axisMass}); + registry.add("hPt", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPt}); + registry.add("hPtFit", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit}); + registry.add("hPtFit2", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit2}); + registry.add("hEta", "Pseudorapidty of muon pairs;;#counts", kTH1D, {axisEta}); + registry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {axisRapidity}); + registry.add("hPhi", "#varphi of muon pairs;;#counts", kTH1D, {axisPhi}); + registry.add("hCharge", "Charge;;;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hContrib", "hContrib;;#counts", kTH1D, {{6, -0.5, 5.5}}); + registry.add("hEvSign", "Sum of the charges of all the tracks in each event;;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hPtTrkPos", "Pt of positive muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hPtTrkNeg", "Pt of negative muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hEtaTrkPos", "#eta of positive muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hEtaTrkNeg", "#eta of negative muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hPhiTrkPos", "#varphi of positive muons;;#counts", kTH1D, {axisPhiSingle}); + registry.add("hPhiTrkNeg", "#varphi of negative muons;;#counts", kTH1D, {axisPhiSingle}); + registry.add("hSameSign", "hSameSign;;#counts", kTH1D, {{6, -0.5, 5.5}}); + registry.add("hPhiCharge", "#phi #it{charge}", kTH1D, {axisPhi}); + registry.add("hPhiAverage", "#phi #it{average}", kTH1D, {axisPhi}); + + // ZDC + registry.add("hTimeZNA", "ZNA Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hTimeZNC", "ZNC Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hEnergyZN", "ZNA vs ZNC energy", kTH2D, {axisEnergyZNA, axisEnergyZNC}); + + // neutron classes + reg0n0n.add("hMass", "Invariant mass of muon pairs - 0n0n;;#counts", kTH1D, {axisMass}); + reg0n0n.add("hPt", "Transverse momentum of muon pairs - 0n0n;;#counts", kTH1D, {axisPt}); + reg0n0n.add("hEta", "Pseudorapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisEta}); + reg0n0n.add("hRapidity", "Rapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisRapidity}); + reg0n0n.add("hPtFit", "Transverse momentum of muon pairs - 0n0n;;#counts", kTH1D, {axisPtFit}); + + regXn0n.add("hMass", "Invariant mass of muon pairs - Xn0n;;#counts", kTH1D, {axisMass}); + regXn0n.add("hPt", "Transverse momentum of muon pairs - Xn0n;;#counts", kTH1D, {axisPt}); + regXn0n.add("hEta", "Pseudorapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisEta}); + regXn0n.add("hRapidity", "Rapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisRapidity}); + regXn0n.add("hPtFit", "Transverse momentum of muon pairs - Xn0n;;#counts", kTH1D, {axisPtFit}); + + regXnXn.add("hMass", "Invariant mass of muon pairs - XnXn;;#counts", kTH1D, {axisMass}); + regXnXn.add("hPt", "Transverse momentum of muon pairs - XnXn;;#counts", kTH1D, {axisPt}); + regXnXn.add("hEta", "Pseudorapidty of muon pairs - XnXn;;#counts", kTH1D, {axisEta}); + regXnXn.add("hRapidity", "Rapidty of muon pairs - XnXn;;#counts", kTH1D, {axisRapidity}); + regXnXn.add("hPtFit", "Transverse momentum of muon pairs - XnXn;;#counts", kTH1D, {axisPtFit}); + } + + // FUNCTIONS + + using LorentzVec = ROOT::Math::PxPyPzMVector; + + // check if track is a GlobalMuonTrack (enum 0 or 1) + template + bool isGlobalMuon(const TTrack& track) + { + return track.trackType() == ForwardTrackTypeEnum::GlobalMuonTrack || + track.trackType() == ForwardTrackTypeEnum::GlobalMuonTrackOtherMatch; + } + + // check if track is a MuonStandaloneTrack (enum 3) + template + bool isMuonStandalone(const TTrack& track) + { + return track.trackType() == ForwardTrackTypeEnum::MuonStandaloneTrack; + } + + // check if the track pair matches the selected candidate type + template + bool passCandidateType(const TTrack& tr1, const TTrack& tr2) + { + bool isGlobal1 = isGlobalMuon(tr1); + bool isGlobal2 = isGlobalMuon(tr2); + bool isStandalone1 = isMuonStandalone(tr1); + bool isStandalone2 = isMuonStandalone(tr2); + + switch (static_cast(candidateType)) { + case 0: // both GlobalMuon + return isGlobal1 && isGlobal2; + case 1: // mixed: one GlobalMuon + one MuonStandalone + return (isGlobal1 && isStandalone2) || (isStandalone1 && isGlobal2); + case 2: // both MuonStandalone + return isStandalone1 && isStandalone2; + default: + return false; + } + } + + // collect tracks per candidate into a map + template + void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + { + for (const auto& tr : tracks) { + int32_t candId = tr.udCollisionId(); + if (candId < 0) { + continue; + } + tracksPerCand[candId].push_back(tr.globalIndex()); + } + } + + // struct used to store the ZDC info + struct ZDCinfo { + float timeA; + float timeC; + float enA; + float enC; + }; + + // collect ZDC info per candidate + void collectCandZDCInfo(std::unordered_map& zdcPerCand, o2::aod::UDZdcsReduced const& ZDCs) + { + for (const auto& zdc : ZDCs) { + int32_t candId = zdc.udCollisionId(); + if (candId < 0) { + continue; + } + + zdcPerCand[candId].timeA = zdc.timeZNA(); + zdcPerCand[candId].timeC = zdc.timeZNC(); + zdcPerCand[candId].enA = zdc.energyCommonZNA(); + zdcPerCand[candId].enC = zdc.energyCommonZNC(); + + if (std::isinf(zdcPerCand[candId].timeA)) + zdcPerCand[candId].timeA = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].timeC)) + zdcPerCand[candId].timeC = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].enA)) + zdcPerCand[candId].enA = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].enC)) + zdcPerCand[candId].enC = kInvalidFloat; + } + } + + // muon track selection + template + bool isMuonSelected(const TTrack& fwdTrack) + { + float rAbs = fwdTrack.rAtAbsorberEnd(); + float pDca = fwdTrack.pDca(); + auto mMu = o2::constants::physics::MassMuon; + LorentzVec p(fwdTrack.px(), fwdTrack.py(), fwdTrack.pz(), mMu); + float eta = p.Eta(); + float pt = p.Pt(); + float pDcaMax = rAbs < kRAbsMid ? kPDca1 : kPDca2; + + if (eta < kEtaMin || eta > kEtaMax) + return false; + if (pt < kPtMin) + return false; + if (rAbs < kRAbsMin || rAbs > kRAbsMax) + return false; + if (pDca > pDcaMax) + return false; + return true; + } + + // compute phi for azimuth anisotropy + void computePhiAnis(LorentzVec p1, LorentzVec p2, int sign1, float& phiAverage, float& phiCharge) + { + auto tSum = p1 + p2; + float halfUnity = 0.5; + decltype(tSum) tDiffCh, tDiffAv; + if (sign1 > 0) { + tDiffCh = p1 - p2; + if (gRandom->Rndm() > halfUnity) + tDiffAv = p1 - p2; + else + tDiffAv = p2 - p1; + } else { + tDiffCh = p2 - p1; + if (gRandom->Rndm() > halfUnity) + tDiffAv = p2 - p1; + else + tDiffAv = p1 - p2; + } + + phiAverage = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffAv); + phiCharge = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffCh); + } + + // process a single candidate + void processCand(CandidatesFwd::iterator const& cand, + ForwardTracks::iterator const& tr1, ForwardTracks::iterator const& tr2, + ZDCinfo const& zdc) + { + // candidate type selection + if (!passCandidateType(tr1, tr2)) + return; + + // V0 selection + const auto& ampsV0A = cand.amplitudesV0A(); + const auto& ampsRelBCsV0A = cand.ampRelBCsV0A(); + for (unsigned int i = 0; i < ampsV0A.size(); ++i) { + if (std::abs(ampsRelBCsV0A[i]) <= kMaxRelBCsV0A) { + if (ampsV0A[i] > kMaxAmpV0A) + return; + } + } + + // select opposite charge events only + if (cand.netCharge() != 0) { + registry.fill(HIST("hSameSign"), cand.numContrib()); + return; + } + + // MCH-MID match selection: both tracks must have MCH-MID match + int nMIDs = 0; + if (tr1.chi2MatchMCHMID() > 0) + nMIDs++; + if (tr2.chi2MatchMCHMID() > 0) + nMIDs++; + if (nMIDs != kNMuons) + return; + + // track selection + if (!isMuonSelected(tr1)) + return; + if (!isMuonSelected(tr2)) + return; + + // form Lorentz vectors + auto mMu = o2::constants::physics::MassMuon; + LorentzVec p1(tr1.px(), tr1.py(), tr1.pz(), mMu); + LorentzVec p2(tr2.px(), tr2.py(), tr2.pz(), mMu); + auto p = p1 + p2; + + // cut on pair kinematics + if (p.M() < lowMass || p.M() > highMass) + return; + if (p.Pt() < lowPt || p.Pt() > highPt) + return; + if (p.Rapidity() < lowRapidity || p.Rapidity() > highRapidity) + return; + + // compute phi for azimuth anisotropy + float phiAverage = 0; + float phiCharge = 0; + computePhiAnis(p1, p2, tr1.sign(), phiAverage, phiCharge); + + // zdc info + if (std::abs(zdc.timeA) < kMaxZDCTimeHisto) + registry.fill(HIST("hTimeZNA"), zdc.timeA); + if (std::abs(zdc.timeC) < kMaxZDCTimeHisto) + registry.fill(HIST("hTimeZNC"), zdc.timeC); + registry.fill(HIST("hEnergyZN"), zdc.enA, zdc.enC); + + // neutron classes + bool neutronA = std::abs(zdc.timeA) < kMaxZDCTime && !std::isinf(zdc.timeA); + bool neutronC = std::abs(zdc.timeC) < kMaxZDCTime && !std::isinf(zdc.timeC); + int znClass = -1; + + if (!neutronC && !neutronA) { + znClass = 1; + reg0n0n.fill(HIST("hMass"), p.M()); + reg0n0n.fill(HIST("hPt"), p.Pt()); + reg0n0n.fill(HIST("hPtFit"), p.Pt()); + reg0n0n.fill(HIST("hEta"), p.Eta()); + reg0n0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutronA ^ neutronC) { + znClass = neutronA ? 2 : 3; + regXn0n.fill(HIST("hMass"), p.M()); + regXn0n.fill(HIST("hPt"), p.Pt()); + regXn0n.fill(HIST("hPtFit"), p.Pt()); + regXn0n.fill(HIST("hEta"), p.Eta()); + regXn0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutronA && neutronC) { + znClass = 4; + regXnXn.fill(HIST("hMass"), p.M()); + regXnXn.fill(HIST("hPt"), p.Pt()); + regXnXn.fill(HIST("hPtFit"), p.Pt()); + regXnXn.fill(HIST("hEta"), p.Eta()); + regXnXn.fill(HIST("hRapidity"), p.Rapidity()); + } + + // fill inclusive histos + registry.fill(HIST("hContrib"), cand.numContrib()); + registry.fill(HIST("hPtTrkPos"), p1.Pt()); + registry.fill(HIST("hPtTrkNeg"), p2.Pt()); + registry.fill(HIST("hEtaTrkPos"), p1.Eta()); + registry.fill(HIST("hEtaTrkNeg"), p2.Eta()); + registry.fill(HIST("hPhiTrkPos"), p1.Phi()); + registry.fill(HIST("hPhiTrkNeg"), p2.Phi()); + registry.fill(HIST("hEvSign"), cand.netCharge()); + registry.fill(HIST("hMass"), p.M()); + registry.fill(HIST("hPt"), p.Pt()); + registry.fill(HIST("hPtFit"), p.Pt()); + registry.fill(HIST("hPtFit2"), p.Pt()); + registry.fill(HIST("hEta"), p.Eta()); + registry.fill(HIST("hRapidity"), p.Rapidity()); + registry.fill(HIST("hPhi"), p.Phi()); + registry.fill(HIST("hCharge"), tr1.sign()); + registry.fill(HIST("hCharge"), tr2.sign()); + registry.fill(HIST("hPhiAverage"), phiAverage); + registry.fill(HIST("hPhiCharge"), phiCharge); + + // store the event to save it into a tree + // order tracks so that positive is first + if (tr1.sign() > 0) { + dimuSel(cand.runNumber(), + p.M(), p.E(), p.Px(), p.Py(), p.Pz(), p.Pt(), p.Rapidity(), p.Phi(), + phiAverage, phiCharge, + p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.Eta(), p1.Phi(), static_cast(tr1.trackType()), + p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.Eta(), p2.Phi(), static_cast(tr2.trackType()), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + } else { + dimuSel(cand.runNumber(), + p.M(), p.E(), p.Px(), p.Py(), p.Pz(), p.Pt(), p.Rapidity(), p.Phi(), + phiAverage, phiCharge, + p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.Eta(), p2.Phi(), static_cast(tr2.trackType()), + p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.Eta(), p1.Phi(), static_cast(tr1.trackType()), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + } + } + + // PROCESS FUNCTION + void processData(CandidatesFwd const& eventCandidates, + o2::aod::UDZdcsReduced const& ZDCs, + ForwardTracks const& fwdTracks) + { + // map with the tracks + std::unordered_map> tracksPerCand; + collectCandIDs(tracksPerCand, fwdTracks); + + // map with the ZDC info + std::unordered_map zdcPerCand; + collectCandZDCInfo(zdcPerCand, ZDCs); + + // loop over the candidates and all track pairs + for (const auto& item : tracksPerCand) { + const auto& trkIds = item.second; + int32_t candID = item.first; + auto cand = eventCandidates.iteratorAt(candID); + + ZDCinfo zdc; + if (zdcPerCand.count(candID) != 0) { + zdc = zdcPerCand.at(candID); + } else { + zdc.timeA = kInvalidFloat; + zdc.timeC = kInvalidFloat; + zdc.enA = kInvalidFloat; + zdc.enC = kInvalidFloat; + } + + for (size_t i = 0; i < trkIds.size(); ++i) { + for (size_t j = i + 1; j < trkIds.size(); ++j) { + auto tr1 = fwdTracks.iteratorAt(trkIds[i]); + auto tr2 = fwdTracks.iteratorAt(trkIds[j]); + processCand(cand, tr1, tr2, zdc); + } + } + } + } + + PROCESS_SWITCH(UpcFwdJpsiRl, processData, "", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 10eadf09a4db6fba58e8566f6c20ec2a759c353f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Thu, 7 May 2026 13:09:20 +0200 Subject: [PATCH 075/449] [PWGCF] Remove unused file (#16099) --- PWGCF/FemtoWorld/Core/FemtoWorldUtils.h | 106 ------------------------ 1 file changed, 106 deletions(-) delete mode 100644 PWGCF/FemtoWorld/Core/FemtoWorldUtils.h diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h b/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h deleted file mode 100644 index b3f7a654ccd..00000000000 --- a/PWGCF/FemtoWorld/Core/FemtoWorldUtils.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file CFFilter.cxx -/// \brief Utilities for the FemtoWorld framework -/// -/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch - -#ifndef PWGCF_FEMTOWORLD_CORE_FEMTOWORLDUTILS_H_ -#define PWGCF_FEMTOWORLD_CORE_FEMTOWORLDUTILS_H_ - -#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" - -#include - -#include -#include -#include - -namespace o2::analysis::femtoWorld -{ - -enum kPIDselection { - k3d5sigma = 0, - k3sigma = 1, - k2d5sigma = 2 -}; - -enum kDetector { - kTPC = 0, - kTPCTOF = 1, - kNdetectors = 2 -}; - -/// internal function that returns the kPIDselection element corresponding to a specifica n-sigma value -/// \param nSigma number of sigmas for PID -/// \param vNsigma vector with the number of sigmas of interest -/// \return kPIDselection corresponding to n-sigma -kPIDselection getPIDselection(const float nSigma, const std::vector& vNsigma) -{ - for (int i = 0; i < (int)vNsigma.size(); i++) { - if (abs(nSigma - vNsigma[i]) < 1e-3) { - return static_cast(i); - } - } - LOG(info) << "Invalid value of nSigma: " << nSigma << ". Standard 3 sigma returned." << std::endl; - return kPIDselection::k3sigma; -} - -/// function that checks whether the PID selection specified in the vectors is fulfilled -/// \param pidcut Bit-wise container for the PID -/// \param vSpecies vector with ID corresponding to the selected species (output from cutculator) -/// \param nSpecies number of available selected species (output from cutculator) -/// \param nSigma number of sigma selection fo PID -/// \param vNsigma vector with available n-sigma selections for PID -/// \param kDetector enum corresponding to the PID technique -/// \return Whether the PID selection specified in the vectors is fulfilled -bool isPIDSelected(aod::femtoworldparticle::cutContainerType const& pidcut, std::vector const& vSpecies, int nSpecies, float nSigma, const std::vector& vNsigma, const kDetector iDet = kDetector::kTPC) -{ - bool pidSelection = true; - kPIDselection iNsigma = getPIDselection(nSigma, vNsigma); - for (auto iSpecies : vSpecies) { - //\todo we also need the possibility to specify whether the bit is true/false ->std>>vector> - // if (!((pidcut >> it.first) & it.second)) { - int bit_to_check = nSpecies * kDetector::kNdetectors * iNsigma + iSpecies * kDetector::kNdetectors + iDet; - if (!(pidcut & (1UL << bit_to_check))) { - pidSelection = false; - } - } - return pidSelection; -}; - -/// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted -/// \param pidcut Bit-wise container for the PID -/// \param momentum Momentum of the track -/// \param pidThresh Momentum threshold that separates between TPC and TPC+TOF PID -/// \param vSpecies Vector with the species of interest (number returned by the CutCulator) -/// \param nSpecies number of available selected species (output from cutculator) -/// \param nSigmaTPC Number of TPC sigmas for selection -/// \param nSigmaTPCTOF Number of TPC+TOF sigmas for selection (circular selection) -/// \return Whether the PID selection is fulfilled -bool isFullPIDSelected(aod::femtoworldparticle::cutContainerType const& pidCut, float const momentum, float const pidThresh, std::vector const& vSpecies, int nSpecies, const std::vector& vNsigma = {3.5, 3., 2.5}, const float nSigmaTPC = 3.5, const float nSigmaTPCTOF = 3.5) -{ - bool pidSelection = true; - if (momentum < pidThresh) { - /// TPC PID only - pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPC, vNsigma, kDetector::kTPC); - } else { - /// TPC + TOF PID - pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPCTOF, vNsigma, kDetector::kTPCTOF); - } - return pidSelection; -}; - -} // namespace o2::analysis::femtoWorld - -#endif // PWGCF_FEMTOWORLD_CORE_FEMTOWORLDUTILS_H_ From 81a8e7e6e6c19eb21659cc2100b48cf3580a7419 Mon Sep 17 00:00:00 2001 From: vojmach <137265951+vojmach@users.noreply.github.com> Date: Thu, 7 May 2026 13:13:17 +0200 Subject: [PATCH 076/449] [PWGCF] add RCT flags and pt-depended DCAz (#16080) --- PWGCF/Flow/Tasks/flowTask.cxx | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index b71bc85dc75..b67a72bd13e 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -21,6 +21,7 @@ #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" @@ -75,10 +76,11 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::genericframework; +using namespace o2::aod::rctsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; static constexpr double LongArrayDouble[4][2] = {{-2.0, -2.0}, {-2.0, -2.0}, {-2.0, -2.0}, {-2.0, -2.0}}; -static constexpr float TrackCutArray[6][2] = {{2.5f, 2.5f}, {50.0f, 50.0f}, {70.0f, 70.0f}, {5.0f, 5.0f}, {2.0f, 2.0f}, {7.0f, 7.0f}}; +static constexpr float TrackCutArray[7][2] = {{2.5f, 2.5f}, {50.0f, 50.0f}, {70.0f, 70.0f}, {5.0f, 5.0f}, {2.0f, 2.0f}, {7.0f, 7.0f}, {0.f, 0.f}}; struct FlowTask { @@ -97,7 +99,7 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgEtaVnPt, float, 0.4, "eta range for pt in vn-pt correlations") Configurable> cfgPtPtGaps{"cfgPtPtGaps", {LongArrayDouble[0], 4, 2, {"subevent 1", "subevent 2", "subevent 3", "subevent 4"}, {"etamin", "etamax"}}, "{etamin,etamax} for all ptpt-subevents"}; O2_DEFINE_CONFIGURABLE(cfgEtaGapPtPtEnabled, bool, false, "switch of subevent pt-pt correlations") - Configurable> cfgTrackCuts{"cfgTrackCuts", {TrackCutArray[0], 6, 2, {"chi2 per TPCcls", "TPC cluster", "TPC crossed rows", "ITS cluster", "DCAz", "DCAxy Nsigma"}, {"Nch", "Observable"}}, "separate Nch and observable track selections"}; + Configurable> cfgTrackCuts{"cfgTrackCuts", {TrackCutArray[0], 7, 2, {"chi2 per TPCcls", "TPC cluster", "TPC crossed rows", "ITS cluster", "DCAz", "DCAxy Nsigma", "DCAz Nsigma(override)"}, {"Nch", "Observable"}}, "separate Nch and observable track selections"}; enum TrackCut { // enum for labelledArray track selection kChi2prTPCcls = 0, // max chi2 per TPC clusters @@ -105,7 +107,8 @@ struct FlowTask { kTPCCrossedRows, // minimum TPC crossed rows kITSclu, // minimum ITS found clusters kDCAz, // max DCA to vertex z - kDCAxyNSigma // 0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction, nsigma=7 is the same with global track + kDCAxyNSigma, // 0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction, nsigma=7 is the same with global track + kDCAzNSigma // 0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction }; enum TrackCutGroup { kTrCutNch = 0, @@ -129,6 +132,7 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking', 'CBT_hadronPID' ") O2_DEFINE_CONFIGURABLE(cfgGetInteractionRate, bool, false, "Get interaction rate from CCDB") O2_DEFINE_CONFIGURABLE(cfgUseInteractionRateCut, bool, false, "Use events with low interaction rate") O2_DEFINE_CONFIGURABLE(cfgCutMaxIR, float, 50.0f, "maximum interaction rate (kHz)") @@ -211,7 +215,10 @@ struct FlowTask { // Functional form of pt-dependent DCAxy cut TF1* fPtDepDCAxy = nullptr; TF1* fPtDepDCAxyForNch = nullptr; + TF1* fPtDepDCAz = nullptr; + TF1* fPtDepDCAzForNch = nullptr; O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAz cut"); } cfgFuncParas; struct : ConfigurableGroup { @@ -316,6 +323,7 @@ struct FlowTask { std::unordered_map gHadronicRate; ctpRateFetcher mRateFetcher; TH2* gCurrentHadronicRate; + RCTFlagsChecker rctChecker{"CentralBarrelTracking"}; // phi-EP correction std::vector funcEff; @@ -346,7 +354,7 @@ struct FlowTask { registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "after supicious Runs removal"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "after additional event cut"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "after correction loads"); - registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); @@ -360,6 +368,7 @@ struct FlowTask { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "occupancy"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "MultCorrelation"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "cfgEvSelV0AT0ACut"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "RCTflags"); registry.add("hVtxZ", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); registry.add("hMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); @@ -739,6 +748,19 @@ struct FlowTask { cfgFuncParas.fPtDepDCAxyForNch->SetParameter(0, cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch]); LOGF(info, "DCAxy pt-dependence function for Nch: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch], cfgFuncParas.cfgDCAxyFunc->c_str())); } + if (cfgTrackCuts->getData()[kDCAzNSigma][kTrCutObs]) { + cfgFuncParas.fPtDepDCAz = new TF1("ptDepDCAz", Form("[0]*%s", cfgFuncParas.cfgDCAzFunc->c_str()), 0.001, 1000); + cfgFuncParas.fPtDepDCAz->SetParameter(0, cfgTrackCuts->getData()[kDCAzNSigma][kTrCutObs]); + LOGF(info, "DCAz pt-dependence function: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAzNSigma][kTrCutObs], cfgFuncParas.cfgDCAzFunc->c_str())); + } + if (cfgTrackCuts->getData()[kDCAzNSigma][kTrCutNch]) { + cfgFuncParas.fPtDepDCAzForNch = new TF1("ptDepDCAzForNch", Form("[0]*%s", cfgFuncParas.cfgDCAzFunc->c_str()), 0.001, 1000); + cfgFuncParas.fPtDepDCAzForNch->SetParameter(0, cfgTrackCuts->getData()[kDCAzNSigma][kTrCutNch]); + LOGF(info, "DCAz pt-dependence function for Nch: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAzNSigma][kTrCutNch], cfgFuncParas.cfgDCAzFunc->c_str())); + } + if (!cfgEvSelRCTflags.value.empty()) { + rctChecker.init(cfgEvSelRCTflags.value.c_str(), true); // override initialzation + } } void createOutputObjectsForRun(int runNumber) @@ -1054,6 +1076,11 @@ struct FlowTask { if (cfgFuncParas.cfgEvSelV0AT0ACut) registry.fill(HIST("hEventCountSpecific"), 11.5); + if (!cfgEvSelRCTflags.value.empty() && !rctChecker(*collision)) + return 0; + if (!cfgEvSelRCTflags.value.empty()) + registry.fill(HIST("hEventCountSpecific"), 12.5); + return 1; } @@ -1076,6 +1103,8 @@ struct FlowTask { { if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutObs] && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt()))) return false; + if (cfgTrackCuts->getData()[kDCAzNSigma][kTrCutObs] && (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAz->Eval(track.pt()))) + return false; return ((track.tpcNClsFound() >= cfgTrackCuts->getData()[kTPCclu][kTrCutObs]) && (track.tpcNClsCrossedRows() >= cfgTrackCuts->getData()[kTPCCrossedRows][kTrCutObs]) && (track.itsNCls() >= cfgTrackCuts->getData()[kITSclu][kTrCutObs]) && (track.tpcChi2NCl() < cfgTrackCuts->getData()[kChi2prTPCcls][kTrCutObs]) && (std::fabs(track.dcaZ()) < cfgTrackCuts->getData()[kDCAz][kTrCutObs])); } @@ -1084,6 +1113,8 @@ struct FlowTask { { if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch] && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxyForNch->Eval(track.pt()))) return false; + if (cfgTrackCuts->getData()[kDCAzNSigma][kTrCutNch] && (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAzForNch->Eval(track.pt()))) + return false; return ((track.tpcNClsFound() >= cfgTrackCuts->getData()[kTPCclu][kTrCutNch]) && (track.tpcNClsCrossedRows() >= cfgTrackCuts->getData()[kTPCCrossedRows][kTrCutNch]) && (track.itsNCls() >= cfgTrackCuts->getData()[kITSclu][kTrCutNch]) && (track.tpcChi2NCl() < cfgTrackCuts->getData()[kChi2prTPCcls][kTrCutNch]) && (std::fabs(track.dcaZ()) < cfgTrackCuts->getData()[kDCAz][kTrCutNch])); } From 14c96a998c6534a026ca1f6b81285141a5376888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Thu, 7 May 2026 13:15:19 +0200 Subject: [PATCH 077/449] [PWGEM] Fix includes (#16090) --- PWGEM/Dilepton/DataModel/dileptonTables.h | 2 -- PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx | 3 ++- PWGEM/Dilepton/Tasks/matchingMFT.cxx | 3 +++ PWGEM/Dilepton/Tasks/taggingHFE.cxx | 1 - PWGEM/PhotonMeson/Tasks/photonResoTask.cxx | 1 + PWGEM/PhotonMeson/Utils/MCUtilities.h | 1 + 6 files changed, 7 insertions(+), 4 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index c574cb3689a..9b47e2d4dd4 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -27,8 +27,6 @@ #include #include #include -#include -#include #include #ifndef PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx index 05eaeaf9ee1..d9ff8eee3ba 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx @@ -23,6 +23,7 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include @@ -50,6 +50,7 @@ #include #include +#include #include #include #include diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 477fbfbd33d..eab695fe25b 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -26,6 +26,7 @@ #include "Tools/ML/MlResponse.h" #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +52,7 @@ #include #include +#include #include #include #include diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 3a2ea08cab4..7a1596e8233 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -30,7 +30,6 @@ #include "Common/DataModel/PIDResponseTPC.h" #include -#include #include #include #include diff --git a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx index 87ca1f0fb3a..3ae919f990c 100644 --- a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx @@ -49,6 +49,7 @@ #include #include +#include #include #include #include diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 90568398c63..ff0b7307727 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -22,6 +22,7 @@ #include #include +#include #include #include From bbc7bc7847d1fbd8fddf4d4419392dba54b19d16 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Thu, 7 May 2026 13:59:52 +0200 Subject: [PATCH 078/449] [PWGCF] Fix MC processing, remove tmp histograms from registry (#16106) --- .../Tasks/flowGenericFramework.cxx | 994 ++++++++++-------- 1 file changed, 536 insertions(+), 458 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index e1eedcd7744..d86048f7b10 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -178,16 +179,16 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgTPCSectorCut, bool, false, "Cut on pt-phi distribution"); } cfgTrackCuts; struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); - O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); - O2_DEFINE_CONFIGURABLE(cfgIsGoodITSLayersAll, bool, true, "kIsGoodITSLayersAll"); - O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); - O2_DEFINE_CONFIGURABLE(cfgNoCollInRofStandard, bool, true, "kNoCollInRofStandard"); - O2_DEFINE_CONFIGURABLE(cfgNoHighMultCollInPrevRof, bool, true, "kNoHighMultCollInPrevRof"); - O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, true, "kNoITSROFrameBorder"); - O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, true, "kNoTimeFrameBorder"); - O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "kTVXinTRD - Use kTVXinTRD (reject TRD triggered events)"); - O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "kIsVertexITSTPC - Selects collisions with at least one ITS-TPC track"); + O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "NoSameBunchPileupCut"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "IsGoodZvtxFT0vsPV"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodITSLayersAll, bool, true, "IsGoodITSLayersAll"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "NoCollInTimeRangeStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInRofStandard, bool, true, "NoCollInRofStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoHighMultCollInPrevRof, bool, true, "NoHighMultCollInPrevRof"); + O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, true, "NoITSROFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, true, "NoTimeFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "TVXinTRD - Use TVXinTRD (reject TRD triggered events)"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "IsVertexITSTPC - Selects collisions with at least one ITS-TPC track"); } cfgEventCutFlags; O2_DEFINE_CONFIGURABLE(cfgOccupancySelection, int, 2000, "Max occupancy selection, -999 to disable"); O2_DEFINE_CONFIGURABLE(cfgDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); @@ -274,54 +275,54 @@ struct FlowGenericFramework { // QA outputs std::map>> th1sList; std::map>> th3sList; - std::vector> histosNpt; - std::vector> histosResoNpt; + std::vector> histosNpt; + std::vector> histosResoNpt; enum OutputTH1Names { - hPhi = 0, - hEta, - hVtxZ, - hMult, - hCent, - hEventSel, - kCount_TH1Names + Phi = 0, + Eta, + VtxZ, + Mult, + Cent, + EventSel, + TH1NameCount }; // NUA outputs enum OutputTH3Names { - hNUAref = 0, - hNUAch, - hNUApi, - hNUAka, - hNUApr, - hPtPhiMult, - kCount_TH3Names + NUAref = 0, + NUAch, + NUApi, + NUAka, + NUApr, + PtPhiMult, + TH3NameCount }; enum CentEstimators { - kCentFT0C = 0, - kCentFT0CVariant1, - kCentFT0M, - kCentFV0A, - kCentNTPV, - kCentNGlobal, - kCentMFT + CentFT0C = 0, + CentFT0CVariant1, + CentFT0M, + CentFV0A, + CentNTPV, + CentNGlobal, + CentMFT }; - std::map centNamesMap = {{kCentFT0C, "FT0C"}, {kCentFT0CVariant1, "FT0C variant1"}, {kCentFT0M, "FT0M"}, {kCentFV0A, "FV0A"}, {kCentNTPV, "NTPV"}, {kCentNGlobal, "NGlobal"}, {kCentMFT, "MFT"}}; + std::map centNamesMap = {{CentFT0C, "FT0C"}, {CentFT0CVariant1, "FT0C variant1"}, {CentFT0M, "FT0M"}, {CentFV0A, "FV0A"}, {CentNTPV, "NTPV"}, {CentNGlobal, "NGlobal"}, {CentMFT, "MFT"}}; enum EventSelFlags { - kFilteredEvent = 1, - kSel8, - kOccupancy, - kTVXinTRD, - kNoSameBunchPileup, - kIsGoodZvtxFT0vsPV, - kNoCollInTimeRangeStandard, - kNoCollInRofStandard, - kNoHighMultCollInPrevRof, - kNoTimeFrameBorder, - kNoITSROFrameBorder, - kIsVertexITSTPC, - kIsGoodITSLayersAll, - kMultCuts, - kTrackCent + FilteredEvent = 1, + Sel8, + Occupancy, + TVXinTRD, + NoSameBunchPileup, + IsGoodZvtxFT0vsPV, + NoCollInTimeRangeStandard, + NoCollInRofStandard, + NoHighMultCollInPrevRof, + NoTimeFrameBorder, + NoITSROFrameBorder, + IsVertexITSTPC, + IsGoodITSLayersAll, + MultCuts, + TrackCent }; struct EventCut { bool enabled; @@ -330,73 +331,73 @@ struct FlowGenericFramework { }; std::vector eventcutflags; enum Particles { - PIONS, - KAONS, - PROTONS + Pions, + Kaons, + Protons }; enum ParticleIDs { - CHARGEDID = 0, - PIONID, - KAONID, - PROTONID, - SPECIESCOUNT + ChargedID = 0, + PionID, + KaonID, + ProtonID, + SpeciesCount }; enum ResoIDs { - K0SIDEBAND1 = 0, - K0SIGNAL, - K0SIDEBAND2, - LAMBDASIDEBAND1, - LAMBDASIGNAL, - LAMBDASIDEBAND2, - RESOCOUNT + K0Sideband1 = 0, + K0Signal, + K0Sideband2, + LambdaSideband1, + LambdaSignal, + LambdaSideband2, + ResonanceCount }; enum OutputSpecies { K0 = 0, - LAMBDA = 1, - PHI = 2, - ANLAMBDA = 3, - REF = 4, - kCount_OutputSpecies + Lambda = 1, + PhiMeson = 2, + LambdaBar = 3, + RefParticle = 4, + OutputSpeciesCount }; enum ParticleCuts { - kCosPA = 0, - kMassMin, - kMassMax, - kPosTrackPt, - kNegTrackPt, - kDCAPosToPVMin, - kDCANegToPVMin, - kDCAxDaughters, - kLifeTime, - kRadiusMin, - kRadiusMax, - kRapidity, - kArmPodMin, - kMassRejection + CosPA = 0, + MassMin, + MassMax, + PosTrackPt, + NegTrackPt, + DCAPosToPVMin, + DCANegToPVMin, + DCAxDaughters, + LifeTime, + RadiusMin, + RadiusMax, + Rapidity, + ArmPodMin, + MassRejection }; enum ParticleSwitches { - kUseParticle = 0, - kUseCosPA, - kMassBins, - kUseDCAxDaughters, - kUseProperLifetime, - kUseV0Radius, - kUseArmPodCut, - kUseCompetingMassRejection + UseParticle = 0, + UseCosPA, + MassBins, + UseDCAxDaughters, + UseProperLifetime, + UseV0Radius, + UseArmPodCut, + UseCompetingMassRejection }; enum V0Selection { - kFillCandidate = 1, - kFillDaughterPt, - kFillMassCut, - kFillRapidityCut, - kFillDCAtoPV, - kFillDCAxDaughters, - kFillV0Radius, - kFillCosPA, - kFillProperLifetime, - kFillArmPodCut, - kFillCompetingMass, - kFillDaughterTrackSelection + FillCandidate = 1, + FillDaughterPt, + FillMassCut, + FillRapidityCut, + FillDCAtoPV, + FillDCAxDaughters, + FillV0Radius, + FillCosPA, + FillProperLifetime, + FillArmPodCut, + FillCompetingMass, + FillDaughterTrackSelection }; // Define global variables @@ -497,7 +498,8 @@ struct FlowGenericFramework { readMatrix(cfgPIDCuts.resonanceSwitches->getData(), resoSwitchVals); printResoCuts(); - for (int i = 0; i < 4; ++i) { // o2-linter: disable=magic-number (maximum of 4 subevents) + int nPtPtSubMax = 4; + for (int i = 0; i < nPtPtSubMax; ++i) { if (cfgPtPtGaps->getData()[i][0] < -1. || cfgPtPtGaps->getData()[i][1] < -1.) continue; o2::analysis::gfw::etagapsPtPt.push_back(std::make_pair(cfgPtPtGaps->getData()[i][0], cfgPtPtGaps->getData()[i][1])); @@ -508,15 +510,15 @@ struct FlowGenericFramework { } // Setup event cuts - eventcutflags.push_back({cfgEventCutFlags.cfgNoSameBunchPileupCut, kNoSameBunchPileup, o2::aod::evsel::kNoSameBunchPileup}); - eventcutflags.push_back({cfgEventCutFlags.cfgIsGoodZvtxFT0vsPV, kIsGoodZvtxFT0vsPV, o2::aod::evsel::kIsGoodZvtxFT0vsPV}); - eventcutflags.push_back({cfgEventCutFlags.cfgNoCollInTimeRangeStandard, kNoCollInTimeRangeStandard, o2::aod::evsel::kNoCollInTimeRangeStandard}); - eventcutflags.push_back({cfgEventCutFlags.cfgNoCollInRofStandard, kNoCollInRofStandard, o2::aod::evsel::kNoCollInRofStandard}); - eventcutflags.push_back({cfgEventCutFlags.cfgNoHighMultCollInPrevRof, kNoHighMultCollInPrevRof, o2::aod::evsel::kNoHighMultCollInPrevRof}); - eventcutflags.push_back({cfgEventCutFlags.cfgNoTimeFrameBorder, kNoTimeFrameBorder, o2::aod::evsel::kNoTimeFrameBorder}); - eventcutflags.push_back({cfgEventCutFlags.cfgNoITSROFrameBorder, kNoITSROFrameBorder, o2::aod::evsel::kNoITSROFrameBorder}); - eventcutflags.push_back({cfgEventCutFlags.cfgIsVertexITSTPC, kIsVertexITSTPC, o2::aod::evsel::kIsVertexITSTPC}); - eventcutflags.push_back({cfgEventCutFlags.cfgIsGoodITSLayersAll, kIsGoodITSLayersAll, o2::aod::evsel::kIsGoodITSLayersAll}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoSameBunchPileupCut, NoSameBunchPileup, o2::aod::evsel::kNoSameBunchPileup}); + eventcutflags.push_back({cfgEventCutFlags.cfgIsGoodZvtxFT0vsPV, IsGoodZvtxFT0vsPV, o2::aod::evsel::kIsGoodZvtxFT0vsPV}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoCollInTimeRangeStandard, NoCollInTimeRangeStandard, o2::aod::evsel::kNoCollInTimeRangeStandard}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoCollInRofStandard, NoCollInRofStandard, o2::aod::evsel::kNoCollInRofStandard}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoHighMultCollInPrevRof, NoHighMultCollInPrevRof, o2::aod::evsel::kNoHighMultCollInPrevRof}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoTimeFrameBorder, NoTimeFrameBorder, o2::aod::evsel::kNoTimeFrameBorder}); + eventcutflags.push_back({cfgEventCutFlags.cfgNoITSROFrameBorder, NoITSROFrameBorder, o2::aod::evsel::kNoITSROFrameBorder}); + eventcutflags.push_back({cfgEventCutFlags.cfgIsVertexITSTPC, IsVertexITSTPC, o2::aod::evsel::kIsVertexITSTPC}); + eventcutflags.push_back({cfgEventCutFlags.cfgIsGoodITSLayersAll, IsGoodITSLayersAll, o2::aod::evsel::kIsGoodITSLayersAll}); for (const auto& cut : eventcutflags) { LOGF(info, "Flag %d is %senabled", cut.histBin, (cut.enabled) ? "" : "not "); } @@ -559,6 +561,10 @@ struct FlowGenericFramework { registryQA.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); registryQA.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registryQA.addClone("MCGen/before/", "MCGen/after/"); + registry.add("MCGen/after/pt_centrality_K0_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_Lambda_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_proton_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); if (doprocessOnTheFly) registryQA.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); } @@ -580,19 +586,12 @@ struct FlowGenericFramework { registryQA.add("trackQA/after/etaNch", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); registryQA.add("trackQA/after/etaPtPt", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); registryQA.add("trackQA/after/etaV0Daughters", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); - - histosNpt.resize(SPECIESCOUNT); - histosNpt[CHARGEDID] = registry.add("nptCh", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[PIONID] = registry.add("nptPi", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[KAONID] = registry.add("nptKa", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[PROTONID] = registry.add("nptPr", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosResoNpt.resize(RESOCOUNT); - histosResoNpt[K0SIDEBAND1] = registry.add("nptK0SB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[K0SIGNAL] = registry.add("nptK0Sig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[K0SIDEBAND2] = registry.add("nptK0SB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LAMBDASIDEBAND1] = registry.add("nptLambdaSB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LAMBDASIGNAL] = registry.add("nptLambdaSig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LAMBDASIDEBAND2] = registry.add("nptLambdaSB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + if (doprocessMCReco) { + registry.add("trackQA/after/pt_centrality_K0_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_Lambda_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_proton", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + } registryQA.add("eventQA/before/centrality", "; centrality (%); Counts", {HistType::kTH1D, {centAxis}}); registryQA.add("eventQA/before/multiplicity", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); @@ -606,32 +605,21 @@ struct FlowGenericFramework { registryQA.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); registryQA.addClone("eventQA/before/", "eventQA/after/"); registryQA.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{15, 0.5, 15.5}}}); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kFilteredEvent, "Filtered event"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kSel8, "sel8"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kOccupancy, "occupancy"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTVXinTRD, "kTVXinTRD"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoSameBunchPileup, "kNoSameBunchPileup"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodZvtxFT0vsPV, "kIsGoodZvtxFT0vsPV"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInTimeRangeStandard, "kNoCollInTimeRangeStandard"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInRofStandard, "kNoCollInRofStandard"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoHighMultCollInPrevRof, "kNoHighMultCollInPrevRof"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoTimeFrameBorder, "kNoTimeFrameBorder"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoITSROFrameBorder, "kNoITSROFrameBorder"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsVertexITSTPC, "kIsVertexITSTPC"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodITSLayersAll, "kIsGoodITSLayersAll"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kMultCuts, "after Mult cuts"); - registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTrackCent, "has track + within cent"); - - registry.add("npt_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(FilteredEvent, "Filtered event"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(Sel8, "sel8"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(Occupancy, "occupancy"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(TVXinTRD, "TVXinTRD"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoSameBunchPileup, "NoSameBunchPileup"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(IsGoodZvtxFT0vsPV, "IsGoodZvtxFT0vsPV"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoCollInTimeRangeStandard, "NoCollInTimeRangeStandard"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoCollInRofStandard, "NoCollInRofStandard"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoHighMultCollInPrevRof, "NoHighMultCollInPrevRof"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoTimeFrameBorder, "NoTimeFrameBorder"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(NoITSROFrameBorder, "NoITSROFrameBorder"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(IsVertexITSTPC, "IsVertexITSTPC"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(IsGoodITSLayersAll, "IsGoodITSLayersAll"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(MultCuts, "after Mult cuts"); + registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(TrackCent, "has track + within cent"); if (!cfgRunByRun) { if (cfgUsePID) { @@ -645,11 +633,11 @@ struct FlowGenericFramework { } } - AxisSpec axisK0Mass = {resoSwitchVals[kMassBins][K0], resoCutVals[kMassMin][K0], resoCutVals[kMassMax][K0]}; - AxisSpec axisLambdaMass = {resoSwitchVals[kMassBins][LAMBDA], resoCutVals[kMassMin][LAMBDA], resoCutVals[kMassMax][LAMBDA]}; + AxisSpec axisK0Mass = {resoSwitchVals[MassBins][K0], resoCutVals[MassMin][K0], resoCutVals[MassMax][K0]}; + AxisSpec axisLambdaMass = {resoSwitchVals[MassBins][Lambda], resoCutVals[MassMin][Lambda], resoCutVals[MassMax][Lambda]}; // QA histograms for V0s - if (resoSwitchVals[kUseParticle][K0]) { + if (resoSwitchVals[UseParticle][K0]) { registryQA.add("K0/PiPlusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); registryQA.add("K0/PiMinusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); registryQA.add("K0/PiPlusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); @@ -661,21 +649,21 @@ struct FlowGenericFramework { registryQA.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillCandidate, "K0 candidates"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDaughterPt, "Daughter pt"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillMassCut, "Mass cut"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillRapidityCut, "Rapidity cut"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDCAtoPV, "DCA to PV"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDCAxDaughters, "DCA between daughters"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillV0Radius, "V0radius"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillCosPA, "CosPA"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillProperLifetime, "Proper lifetime"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillArmPodCut, "Armenteros-Podolanski cut"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillCompetingMass, "Competing mass rejection"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDaughterTrackSelection, "Daughter track selection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate, "K0 candidates"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillRapidityCut, "Rapidity cut"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDCAtoPV, "DCA to PV"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDCAxDaughters, "DCA between daughters"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV0Radius, "V0radius"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCosPA, "CosPA"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelection, "Daughter track selection"); } - if (resoSwitchVals[kUseParticle][LAMBDA]) { + if (resoSwitchVals[UseParticle][Lambda]) { registryQA.add("Lambda/PrPlusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); registryQA.add("Lambda/PiMinusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); registryQA.add("Lambda/PrPlusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); @@ -694,21 +682,45 @@ struct FlowGenericFramework { registryQA.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillCandidate, "Lambda candidates"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDaughterPt, "Daughter pt"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillMassCut, "Mass cut"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillRapidityCut, "Rapidity cut"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDCAtoPV, "DCA to PV"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDCAxDaughters, "DCA between daughters"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillV0Radius, "V0radius"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillCosPA, "CosPA"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillProperLifetime, "Proper lifetime"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillArmPodCut, "Armenteros-Podolanski cut"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillCompetingMass, "Competing mass rejection"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDaughterTrackSelection, "Daughter track selection"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate, "Lambda candidates"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillRapidityCut, "Rapidity cut"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAtoPV, "DCA to PV"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAxDaughters, "DCA between daughters"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillV0Radius, "V0radius"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCosPA, "CosPA"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelection, "Daughter track selection"); } } + registry.add("npt_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + + histosNpt.resize(SpeciesCount); + histosNpt[ChargedID] = std::make_unique("nptCh", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptCh", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); + histosNpt[PionID] = std::make_unique("nptPi", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptPi", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); + histosNpt[KaonID] = std::make_unique("nptKa", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptKa", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); + histosNpt[ProtonID] = std::make_unique("nptPr", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptPr", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); + histosResoNpt.resize(ResonanceCount); + histosResoNpt[K0Sideband1] = std::make_unique("nptK0SB1", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0SB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + histosResoNpt[K0Signal] = std::make_unique("nptK0Sig", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0Sig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + histosResoNpt[K0Sideband2] = std::make_unique("nptK0SB2", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0SB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + histosResoNpt[LambdaSideband1] = std::make_unique("nptLambdaSB1", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + histosResoNpt[LambdaSignal] = std::make_unique("nptLambdaSig", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + histosResoNpt[LambdaSideband2] = std::make_unique("nptLambdaSB2", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + if (o2::analysis::gfw::regions.GetSize() < 0) LOGF(error, "Configuration contains vectors of different size - check the GFWRegions configurable"); for (auto i(0); i < o2::analysis::gfw::regions.GetSize(); ++i) { @@ -893,8 +905,8 @@ struct FlowGenericFramework { printTable(cfgPIDCuts.resonanceSwitches.value, resoSwitchValsF, "Resonance Switches"); } enum QAFillTime { - kBefore, - kAfter + Before, + After }; void addConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) @@ -947,6 +959,9 @@ struct FlowGenericFramework { cfg.mAcceptance.push_back(ccdb->getForTimeStamp(cfgAcceptance.value + runstr, timestamp)); } } + // Run-by-run efficiencies are not supported at the moment + if (cfg.correctionsLoaded) + return; if (!cfgEfficiency.value.empty()) { if (!cfgUsePIDEfficiencies) { cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); @@ -1062,11 +1077,11 @@ struct FlowGenericFramework { } if (isPion) { - pid = PIONS; + pid = Pions; } else if (isKaon) { - pid = KAONS; + pid = Kaons; } else if (isProton) { - pid = PROTONS; + pid = Protons; } else { return 0; // no particle satisfies the criteria } @@ -1079,14 +1094,14 @@ struct FlowGenericFramework { { // Cut on trigger alias if (cfgEventCutFlags.cfgTVXinTRD) { - if (collision.alias_bit(kTVXinTRD)) { + if (collision.alias_bit(TVXinTRD)) { // TRD triggered // "CMTVX-B-NOPF-TRD,minbias_TVX" return false; } - registryQA.fill(HIST("eventQA/eventSel"), kTVXinTRD); + registryQA.fill(HIST("eventQA/eventSel"), TVXinTRD); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(kTVXinTRD); + th1sList[run][EventSel]->Fill(TVXinTRD); } // Cut on event selection flags for (const auto& cut : eventcutflags) { @@ -1096,7 +1111,7 @@ struct FlowGenericFramework { return false; registryQA.fill(HIST("eventQA/eventSel"), cut.histBin); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(cut.histBin); + th1sList[run][EventSel]->Fill(cut.histBin); } // Cut on vertex if (!selectVertex(collision)) @@ -1150,9 +1165,9 @@ struct FlowGenericFramework { return false; if (!(cfgMultCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) > fMultGlobalT0ACutHigh->Eval(multTrk)) return false; - registryQA.fill(HIST("eventQA/eventSel"), kMultCuts); + registryQA.fill(HIST("eventQA/eventSel"), MultCuts); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(kMultCuts); + th1sList[run][EventSel]->Fill(MultCuts); return true; } @@ -1187,12 +1202,15 @@ struct FlowGenericFramework { { if (std::fabs(track.dcaXY()) > (0.0105f + 0.035f / std::pow(track.pt(), 1.1))) return false; - return ((track.tpcNClsCrossedRows() >= 70) && (track.tpcNClsFound() >= 50) && (track.itsNCls() >= 5)); // o2-linter: disable=magic-number (hard coded default cuts) + int tpcNClsCrossedRowsDefault = 70; + int tpcNClsFoundDefault = 50; + int itsNclsDefault = 5; + return ((track.tpcNClsCrossedRows() >= tpcNClsCrossedRowsDefault) && (track.tpcNClsFound() >= tpcNClsFoundDefault) && (track.itsNCls() >= itsNclsDefault)); } enum DataType { - kReco, - kGen + Reco, + Gen }; template @@ -1205,9 +1223,9 @@ struct FlowGenericFramework { bool withinPtRef = (o2::analysis::gfw::ptreflow < track.pt()) && (track.pt() < o2::analysis::gfw::ptrefup); // within RF pT range if (cfgRunByRun) { if (withinPtRef && !pid_index) - th3sList[run][hNUAref]->Fill(track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow + th3sList[run][NUAref]->Fill(track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow if (withinPtPOI) - th3sList[run][hNUAch + pid_index]->Fill(track.phi(), track.eta(), vtxz); // charged and id'ed particle weights + th3sList[run][NUAch + pid_index]->Fill(track.phi(), track.eta(), vtxz); // charged and id'ed particle weights } else { if (withinPtRef && !pid_index) registryQA.fill(HIST("phi_eta_vtxz_ref"), track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow @@ -1230,7 +1248,7 @@ struct FlowGenericFramework { } } else { if (cfgRunByRun) - th3sList[run][hNUAref]->Fill(track.phi(), track.eta(), vtxz); + th3sList[run][NUAref]->Fill(track.phi(), track.eta(), vtxz); else registryQA.fill(HIST("phi_eta_vtxz_ref"), track.phi(), track.eta(), vtxz); } @@ -1246,36 +1264,36 @@ struct FlowGenericFramework { AxisSpec nchAxis = {o2::analysis::gfw::nchbins, o2::analysis::gfw::nchlow, o2::analysis::gfw::nchup, "N_{ch}"}; AxisSpec centAxis = {o2::analysis::gfw::centbinning, "Centrality (%)"}; AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; - std::vector> histos(kCount_TH1Names); - histos[hPhi] = registryQA.add(Form("%d/phi", run), "", {HistType::kTH1D, {phiAxis}}); - histos[hEta] = registryQA.add(Form("%d/eta", run), "", {HistType::kTH1D, {etaAxis}}); - histos[hVtxZ] = registryQA.add(Form("%d/vtxz", run), "", {HistType::kTH1D, {vtxAxis}}); - histos[hMult] = registryQA.add(Form("%d/mult", run), "", {HistType::kTH1D, {nchAxis}}); - histos[hCent] = registryQA.add(Form("%d/cent", run), "", {HistType::kTH1D, {centAxis}}); - histos[hEventSel] = registryQA.add(Form("%d/eventSel", run), "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); - histos[hEventSel]->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos[hEventSel]->GetXaxis()->SetBinLabel(2, "sel8"); - histos[hEventSel]->GetXaxis()->SetBinLabel(3, "occupancy"); - histos[hEventSel]->GetXaxis()->SetBinLabel(4, "kTVXinTRD"); - histos[hEventSel]->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - histos[hEventSel]->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - histos[hEventSel]->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - histos[hEventSel]->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC"); - histos[hEventSel]->GetXaxis()->SetBinLabel(9, "kIsGoodITSLayersAll"); - histos[hEventSel]->GetXaxis()->SetBinLabel(10, "after Mult cuts"); - histos[hEventSel]->GetXaxis()->SetBinLabel(11, "has track + within cent"); + std::vector> histos(TH1NameCount); + histos[Phi] = registryQA.add(Form("%d/phi", run), "", {HistType::kTH1D, {phiAxis}}); + histos[Eta] = registryQA.add(Form("%d/eta", run), "", {HistType::kTH1D, {etaAxis}}); + histos[VtxZ] = registryQA.add(Form("%d/vtxz", run), "", {HistType::kTH1D, {vtxAxis}}); + histos[Mult] = registryQA.add(Form("%d/mult", run), "", {HistType::kTH1D, {nchAxis}}); + histos[Cent] = registryQA.add(Form("%d/cent", run), "", {HistType::kTH1D, {centAxis}}); + histos[EventSel] = registryQA.add(Form("%d/eventSel", run), "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); + histos[EventSel]->GetXaxis()->SetBinLabel(1, "Filtered event"); + histos[EventSel]->GetXaxis()->SetBinLabel(2, "sel8"); + histos[EventSel]->GetXaxis()->SetBinLabel(3, "occupancy"); + histos[EventSel]->GetXaxis()->SetBinLabel(4, "TVXinTRD"); + histos[EventSel]->GetXaxis()->SetBinLabel(5, "NoSameBunchPileup"); + histos[EventSel]->GetXaxis()->SetBinLabel(6, "IsGoodZvtxFT0vsPV"); + histos[EventSel]->GetXaxis()->SetBinLabel(7, "NoCollInTimeRangeStandard"); + histos[EventSel]->GetXaxis()->SetBinLabel(8, "IsVertexITSTPC"); + histos[EventSel]->GetXaxis()->SetBinLabel(9, "IsGoodITSLayersAll"); + histos[EventSel]->GetXaxis()->SetBinLabel(10, "after Mult cuts"); + histos[EventSel]->GetXaxis()->SetBinLabel(11, "has track + within cent"); th1sList.insert(std::make_pair(run, histos)); - std::vector> histos3d(kCount_TH3Names); + std::vector> histos3d(TH3NameCount); if (cfgUsePID) { - histos3d[hNUAref] = registryQA.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - histos3d[hNUAch] = registryQA.add(Form("%d/phi_eta_vtxz_ch", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - histos3d[hNUApi] = registryQA.add(Form("%d/phi_eta_vtxz_pi", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - histos3d[hNUAka] = registryQA.add(Form("%d/phi_eta_vtxz_ka", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - histos3d[hNUApr] = registryQA.add(Form("%d/phi_eta_vtxz_pr", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUAref] = registryQA.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUAch] = registryQA.add(Form("%d/phi_eta_vtxz_ch", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUApi] = registryQA.add(Form("%d/phi_eta_vtxz_pi", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUAka] = registryQA.add(Form("%d/phi_eta_vtxz_ka", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUApr] = registryQA.add(Form("%d/phi_eta_vtxz_pr", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } else { - histos3d[hNUAref] = registryQA.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + histos3d[NUAref] = registryQA.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } - histos3d[hPtPhiMult] = registryQA.add(Form("%d/pt_phi_mult", run), "", {HistType::kTH3D, {ptAxis, phiModAxis, (cfgUseNch) ? nchAxis : centAxis}}); + histos3d[PtPhiMult] = registryQA.add(Form("%d/pt_phi_mult", run), "", {HistType::kTH3D, {ptAxis, phiModAxis, (cfgUseNch) ? nchAxis : centAxis}}); th3sList.insert(std::make_pair(run, histos3d)); return; } @@ -1304,7 +1322,7 @@ struct FlowGenericFramework { continue; auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; if (std::abs(val) < 1) { - (dt == kGen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + (dt == Gen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); if (cfgUseGapMethod) { fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); } @@ -1317,51 +1335,51 @@ struct FlowGenericFramework { continue; auto val = fGFW->Calculate(corrconfigs.at(l_ind), i - 1, kFALSE).real() / dnx; if (std::abs(val) < 1) - (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); } } - if (histosNpt[CHARGEDID]->Integral() <= 0) + if (histosNpt[ChargedID]->Integral() <= 0) return; - double dnPi = histosNpt[CHARGEDID]->Integral(); - double dnKa = histosNpt[CHARGEDID]->Integral(); - double dnPr = histosNpt[CHARGEDID]->Integral(); + double dnPi = histosNpt[ChargedID]->Integral(); + double dnKa = histosNpt[ChargedID]->Integral(); + double dnPr = histosNpt[ChargedID]->Integral(); if (cfgUsePIDTotal) { - dnPi = histosNpt[PIONID]->Integral(); - dnKa = histosNpt[KAONID]->Integral(); - dnPr = histosNpt[PROTONID]->Integral(); + dnPi = histosNpt[PionID]->Integral(); + dnKa = histosNpt[KaonID]->Integral(); + dnPr = histosNpt[ProtonID]->Integral(); } for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { - registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i), centmult, histosNpt[CHARGEDID]->GetBinContent(i) / histosNpt[CHARGEDID]->Integral()); + registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ChargedID]->GetBinContent(i) / histosNpt[ChargedID]->Integral()); if (dnPi > 0) - registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PIONID]->GetBinContent(i) / dnPi); + registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PionID]->GetBinContent(i) / dnPi); if (dnKa > 0) - registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i), centmult, histosNpt[KAONID]->GetBinContent(i) / dnKa); + registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i), centmult, histosNpt[KaonID]->GetBinContent(i) / dnKa); if (dnPr > 0) - registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PROTONID]->GetBinContent(i) / dnPr); + registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ProtonID]->GetBinContent(i) / dnPr); } - if (corrconfigsV02.size() < SPECIESCOUNT) + if (corrconfigsV02.size() < SpeciesCount) return; // For alternative normalisation with integrated pid spectra - std::vector dns = {histosNpt[CHARGEDID]->Integral(), dnPi, dnKa, dnPr}; + std::vector dns = {histosNpt[ChargedID]->Integral(), dnPi, dnKa, dnPr}; - for (uint l_ind = 0; l_ind < SPECIESCOUNT; ++l_ind) { + for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); if (dnx == 0) continue; auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; if (std::abs(val) < 1 && dns[l_ind] > 0) - (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); } } - if (corrconfigsV0.size() < SPECIESCOUNT) + if (corrconfigsV0.size() < SpeciesCount) return; double mpt = 0; @@ -1372,16 +1390,17 @@ struct FlowGenericFramework { } else { if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) return; - double mpt_sub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; - double mpt_sub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; - mpt = 0.5 * (mpt_sub1 + mpt_sub2); + double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; + double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; + mpt = 0.5 * (mptSub1 + mptSub2); } if (std::isnan(mpt)) return; - for (uint l_ind = 0; l_ind < SPECIESCOUNT; ++l_ind) { + + for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { if (dns[l_ind] > 0) - (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm); } } return; @@ -1392,18 +1411,18 @@ struct FlowGenericFramework { { if (tracks.size() < 1) return; - if (dt != kGen && (centrality < o2::analysis::gfw::centbinning.front() || centrality > o2::analysis::gfw::centbinning.back())) + if (dt != Gen && (centrality < o2::analysis::gfw::centbinning.front() || centrality > o2::analysis::gfw::centbinning.back())) return; - if (dt != kGen) { - registryQA.fill(HIST("eventQA/eventSel"), kTrackCent); + if (dt != Gen) { + registryQA.fill(HIST("eventQA/eventSel"), TrackCent); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(kTrackCent); + th1sList[run][EventSel]->Fill(TrackCent); } float vtxz = collision.posZ(); - if (dt != kGen && cfgRunByRun) { - th1sList[run][hVtxZ]->Fill(vtxz); - th1sList[run][hMult]->Fill(tracks.size()); - th1sList[run][hCent]->Fill(centrality); + if (dt != Gen && cfgRunByRun) { + th1sList[run][VtxZ]->Fill(vtxz); + th1sList[run][Mult]->Fill(tracks.size()); + th1sList[run][Cent]->Fill(centrality); } fGFW->Clear(); fFCpt->clearVector(); @@ -1451,8 +1470,10 @@ struct FlowGenericFramework { for (const auto& track : tracks) { processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); } - registryQA.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); - registryQA.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.totaluncorr); + if (dt != Gen) { + registryQA.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); + registryQA.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.totaluncorr); + } int multiplicity = 0; switch (cfgUseNchCorrection) { @@ -1479,64 +1500,95 @@ struct FlowGenericFramework { for (const auto& h : histosResoNpt) h->Reset("ICESM"); - // Process V0s - for (const auto& v0 : v0s) { - if (resoSwitchVals[kUseParticle][K0]) { - double weff = 1; - if (selectK0(collision, v0, centrality, weff)) { - if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) - histosResoNpt[K0SIDEBAND1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) - histosResoNpt[K0SIGNAL]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand2Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand2Max) - histosResoNpt[K0SIDEBAND2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + // Process V0s only for reconstructed-track workflows. + if constexpr (dt != Gen) { + for (const auto& v0 : v0s) { + if (resoSwitchVals[UseParticle][K0]) { + double weff = 1; + if (selectK0(collision, v0, tracks, centrality, weff)) { + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) + histosResoNpt[K0Sideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) + histosResoNpt[K0Signal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand2Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand2Max) + histosResoNpt[K0Sideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + } + } + if (resoSwitchVals[UseParticle][Lambda]) { + double weff = 1.; + if (selectLambda(collision, v0, tracks, centrality, weff)) { + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) + histosResoNpt[LambdaSideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) + histosResoNpt[LambdaSignal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand2Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand2Max) + histosResoNpt[LambdaSideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + } } } - if (resoSwitchVals[kUseParticle][LAMBDA]) { - double weff = 1.; - if (selectLambda(collision, v0, centrality, weff)) { - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) - histosResoNpt[LAMBDASIDEBAND1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) - histosResoNpt[LAMBDASIGNAL]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand2Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand2Max) - histosResoNpt[LAMBDASIDEBAND2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + } else { + for (const auto& particle : tracks) { + if (!particle.has_daughters()) + continue; + + bool isK0 = (particle.pdgCode() == PDG_t::kK0Short); + bool isLambda = (particle.pdgCode() == PDG_t::kLambda0); + + if (!isK0 && !isLambda) + continue; + + if (isK0) + histosResoNpt[K0Signal]->Fill(particle.pt(), 1.0); + if (isLambda) + histosResoNpt[LambdaSignal]->Fill(particle.pt(), 1.0); + + // For efficiency + for (const auto& d : particle.template daughters_as()) { + if (std::abs(d.pdgCode()) == PDG_t::kPiPlus) { + if (isK0) + registry.fill(HIST("MCGen/after/pt_centrality_K0_pion_gen"), d.pt(), centrality); + if (isLambda) + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_pion_gen"), d.pt(), centrality); + registry.fill(HIST("MCGen/after/pt_centrality_pion_gen"), d.pt(), centrality); + } + if (std::abs(d.pdgCode()) == PDG_t::kProton) + registry.fill(HIST("MCGen/after/pt_centrality_proton_gen"), d.pt(), centrality); } } } - if (histosNpt[CHARGEDID]->Integral() <= 0) + if (histosNpt[ChargedID]->Integral() <= 0) return; - double dnK0SB1 = histosNpt[CHARGEDID]->Integral(); - double dnK0Sig = histosNpt[CHARGEDID]->Integral(); - double dnK0SB2 = histosNpt[CHARGEDID]->Integral(); - double dnLambdaSB1 = histosNpt[CHARGEDID]->Integral(); - double dnLambdaSig = histosNpt[CHARGEDID]->Integral(); - double dnLambdaSB2 = histosNpt[CHARGEDID]->Integral(); + double dnK0SB1 = histosNpt[ChargedID]->Integral(); + double dnK0Sig = histosNpt[ChargedID]->Integral(); + double dnK0SB2 = histosNpt[ChargedID]->Integral(); + double dnLambdaSB1 = histosNpt[ChargedID]->Integral(); + double dnLambdaSig = histosNpt[ChargedID]->Integral(); + double dnLambdaSB2 = histosNpt[ChargedID]->Integral(); if (cfgUsePIDTotal) { - dnK0SB1 = histosResoNpt[K0SIDEBAND1]->Integral(); - dnK0Sig = histosResoNpt[K0SIGNAL]->Integral(); - dnK0SB2 = histosResoNpt[K0SIDEBAND2]->Integral(); - dnLambdaSB1 = histosResoNpt[LAMBDASIDEBAND1]->Integral(); - dnLambdaSig = histosResoNpt[LAMBDASIGNAL]->Integral(); - dnLambdaSB2 = histosResoNpt[LAMBDASIDEBAND2]->Integral(); + dnK0SB1 = histosResoNpt[K0Sideband1]->Integral(); + dnK0Sig = histosResoNpt[K0Signal]->Integral(); + dnK0SB2 = histosResoNpt[K0Sideband2]->Integral(); + dnLambdaSB1 = histosResoNpt[LambdaSideband1]->Integral(); + dnLambdaSig = histosResoNpt[LambdaSignal]->Integral(); + dnLambdaSB2 = histosResoNpt[LambdaSideband2]->Integral(); } for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { if (dnK0SB1 > 0) - registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0SIDEBAND1]->GetBinContent(i) / dnK0SB1); + registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband1]->GetBinContent(i) / dnK0SB1); if (dnK0Sig > 0) - registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0SIGNAL]->GetBinContent(i) / dnK0Sig); + registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Signal]->GetBinContent(i) / dnK0Sig); if (dnK0SB2 > 0) - registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0SIDEBAND2]->GetBinContent(i) / dnK0SB2); + registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband2]->GetBinContent(i) / dnK0SB2); if (dnLambdaSB1 > 0) - registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LAMBDASIDEBAND1]->GetBinContent(i) / dnLambdaSB1); + registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband1]->GetBinContent(i) / dnLambdaSB1); if (dnLambdaSig > 0) - registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LAMBDASIGNAL]->GetBinContent(i) / dnLambdaSig); + registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSignal]->GetBinContent(i) / dnLambdaSig); if (dnLambdaSB2 > 0) - registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LAMBDASIDEBAND2]->GetBinContent(i) / dnLambdaSB2); + registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband2]->GetBinContent(i) / dnLambdaSB2); } std::vector dns = {dnK0SB1, dnK0Sig, dnK0SB2, dnLambdaSB1, dnLambdaSig, dnLambdaSB2}; @@ -1548,23 +1600,33 @@ struct FlowGenericFramework { continue; auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; if (std::abs(val) < 1 && dns[l_ind - 4] > 0) - (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom); } } if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) return; - double mpt_sub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; - double mpt_sub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; - double mpt = 0.5 * (mpt_sub1 + mpt_sub2); + double mpt = 0; + if (cfgEtaPtPt->first * cfgEtaPtPt->second >= 0) { + if (fFCpt->corrDen[1] == 0.) + return; + mpt = fFCpt->corrNum[1] / fFCpt->corrDen[1]; + } else { + if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) + return; + double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; + double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; + mpt = 0.5 * (mptSub1 + mptSub2); + } + if (std::isnan(mpt)) return; for (uint l_ind = 4; l_ind < corrconfigsV0.size(); ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { if (dns[l_ind] > 0) - (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom); } } } @@ -1580,7 +1642,7 @@ struct FlowGenericFramework { if (!mcParticle.isPhysicalPrimary()) return; if (cfgFillQA) - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz); if (mcParticle.eta() < o2::analysis::gfw::etalow || mcParticle.eta() > o2::analysis::gfw::etaup || mcParticle.pt() < o2::analysis::gfw::ptlow || mcParticle.pt() > o2::analysis::gfw::ptup) return; @@ -1600,40 +1662,38 @@ struct FlowGenericFramework { return; int pidIndex = 0; - if (cfgUsePID) { - if (std::abs(mcParticle.pdgCode()) == kPiPlus) - pidIndex = PIONID; - if (std::abs(mcParticle.pdgCode()) == kKPlus) - pidIndex = KAONID; - if (std::abs(mcParticle.pdgCode()) == kProton) - pidIndex = PROTONID; - } + if (std::abs(mcParticle.pdgCode()) == kPiPlus) + pidIndex = PionID; + if (std::abs(mcParticle.pdgCode()) == kKPlus) + pidIndex = KaonID; + if (std::abs(mcParticle.pdgCode()) == kProton) + pidIndex = ProtonID; if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { double weff = getEfficiency(track, pidIndex); if (weffCh > 0) - histosNpt[CHARGEDID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); - if (pidIndex == PIONID && weff > 0) - histosNpt[PIONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == KAONID && weff > 0) - histosNpt[KAONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == PROTONID && weff > 0) - histosNpt[PROTONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); + if (pidIndex == PionID && weff > 0) + histosNpt[PionID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (pidIndex == KaonID && weff > 0) + histosNpt[KaonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (pidIndex == ProtonID && weff > 0) + histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); } if (cfgFillWeights) { fillWeights(mcParticle, vtxz, 0, run); } else { - fillPtSums(track, vtxz); - fillGFW(mcParticle, vtxz, pidIndex, densitycorrections); + fillPtSums(track, vtxz); + fillGFW(mcParticle, vtxz, pidIndex, densitycorrections); } if (cfgFillQA) { - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz); if (cfgRunByRun) { - th1sList[run][hPhi]->Fill(track.phi()); - th1sList[run][hEta]->Fill(track.eta()); + th1sList[run][Phi]->Fill(track.phi()); + th1sList[run][Eta]->Fill(track.eta()); } } @@ -1641,42 +1701,38 @@ struct FlowGenericFramework { if (!track.isPhysicalPrimary()) return; if (cfgFillQA) - fillTrackQA(track, vtxz); - + fillTrackQA(track, vtxz); if (track.eta() < o2::analysis::gfw::etalow || track.eta() > o2::analysis::gfw::etaup || track.pt() < o2::analysis::gfw::ptlow || track.pt() > o2::analysis::gfw::ptup) return; - int pidIndex = 0; - if (cfgUsePID) { - if (std::abs(track.pdgCode()) == kPiPlus) - pidIndex = 1; - if (std::abs(track.pdgCode()) == kKPlus) - pidIndex = 2; - if (std::abs(track.pdgCode()) == kProton) - pidIndex = 3; - } + if (std::abs(track.pdgCode()) == kPiPlus) + pidIndex = PionID; + if (std::abs(track.pdgCode()) == kKPlus) + pidIndex = KaonID; + if (std::abs(track.pdgCode()) == kProton) + pidIndex = ProtonID; if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { ++acceptedTracks.total; ++acceptedTracks.totaluncorr; - histosNpt[CHARGEDID]->Fill(track.pt()); - if (pidIndex == PIONID) - histosNpt[PIONID]->Fill(track.pt()); - if (pidIndex == KAONID) - histosNpt[KAONID]->Fill(track.pt()); - if (pidIndex == PROTONID) - histosNpt[PROTONID]->Fill(track.pt()); + histosNpt[ChargedID]->Fill(track.pt()); + if (pidIndex == PionID) + histosNpt[PionID]->Fill(track.pt()); + if (pidIndex == KaonID) + histosNpt[KaonID]->Fill(track.pt()); + if (pidIndex == ProtonID) + histosNpt[ProtonID]->Fill(track.pt()); } - fillPtSums(track, vtxz); - fillGFW(track, vtxz, pidIndex, densitycorrections); - + fillPtSums(track, vtxz); + fillGFW(track, vtxz, pidIndex, densitycorrections); if (cfgFillQA) - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz); + } else { if (cfgFillQA) - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz); // Select tracks with nominal cuts always if (!nchSelected(track)) return; @@ -1698,26 +1754,26 @@ struct FlowGenericFramework { double weff = getEfficiency(track, pidIndex); if (weffCh > 0) - histosNpt[CHARGEDID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); - if (pidIndex == PIONID && weff > 0) - histosNpt[PIONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == KAONID && weff > 0) - histosNpt[KAONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == PROTONID && weff > 0) - histosNpt[PROTONID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); + if (pidIndex == PionID && weff > 0) + histosNpt[PionID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (pidIndex == KaonID && weff > 0) + histosNpt[KaonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (pidIndex == ProtonID && weff > 0) + histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); } if (cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { - fillPtSums(track, vtxz); - fillGFW(track, vtxz, pidIndex, densitycorrections); + fillPtSums(track, vtxz); + fillGFW(track, vtxz, pidIndex, densitycorrections); } if (cfgFillQA) { - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz); if (cfgRunByRun) { - th1sList[run][hPhi]->Fill(track.phi()); - th1sList[run][hEta]->Fill(track.eta()); + th1sList[run][Phi]->Fill(track.phi()); + th1sList[run][Eta]->Fill(track.eta()); } } } @@ -1736,11 +1792,11 @@ struct FlowGenericFramework { return 0; if (cfgPIDCuts.cfgUseOnlyTPC) { - if (pid == PIONS && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) + if (pid == Pions && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) return false; - if (pid == KAONS && std::abs(track.tpcNSigmaKa()) > cfgPIDCuts.cfgTPCNsigmaCut) + if (pid == Kaons && std::abs(track.tpcNSigmaKa()) > cfgPIDCuts.cfgTPCNsigmaCut) return false; - if (pid == PROTONS && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) + if (pid == Protons && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) return false; } else { int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); @@ -1756,59 +1812,60 @@ struct FlowGenericFramework { return true; } - template - bool selectK0(TCollision const& collision, TV0 const& v0, const double& centrality, double& weff) + template + bool selectK0(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality, double& weff) { + using V0TrackTable = std::decay_t; double massK0s = v0.mK0Short(); - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); - registryQA.fill(HIST("K0/hK0Count"), kFillCandidate); - if (postrack.pt() < resoCutVals[kPosTrackPt][K0] || negtrack.pt() < resoCutVals[kNegTrackPt][K0]) + registryQA.fill(HIST("K0/hK0Count"), FillCandidate); + if (postrack.pt() < resoCutVals[PosTrackPt][K0] || negtrack.pt() < resoCutVals[NegTrackPt][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillDaughterPt); - if (massK0s < resoCutVals[kMassMin][K0] && massK0s > resoCutVals[kMassMax][K0]) + registryQA.fill(HIST("K0/hK0Count"), FillDaughterPt); + if (massK0s < resoCutVals[MassMin][K0] && massK0s > resoCutVals[MassMax][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillMassCut); + registryQA.fill(HIST("K0/hK0Count"), FillMassCut); // Rapidity correction - if (v0.yK0Short() > resoCutVals[kRapidity][K0]) + if (v0.yK0Short() > resoCutVals[Rapidity][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillRapidityCut); + registryQA.fill(HIST("K0/hK0Count"), FillRapidityCut); // DCA cuts for K0short - if (std::abs(v0.dcapostopv()) < resoCutVals[kDCAPosToPVMin][K0] || std::abs(v0.dcanegtopv()) < resoCutVals[kDCANegToPVMin][K0]) + if (std::abs(v0.dcapostopv()) < resoCutVals[DCAPosToPVMin][K0] || std::abs(v0.dcanegtopv()) < resoCutVals[DCANegToPVMin][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillDCAtoPV); - if (resoSwitchVals[kUseDCAxDaughters][K0] && std::abs(v0.dcaV0daughters()) > resoCutVals[kDCAxDaughters][K0]) + registryQA.fill(HIST("K0/hK0Count"), FillDCAtoPV); + if (resoSwitchVals[UseDCAxDaughters][K0] && std::abs(v0.dcaV0daughters()) > resoCutVals[DCAxDaughters][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillDCAxDaughters); + registryQA.fill(HIST("K0/hK0Count"), FillDCAxDaughters); // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][K0] && (v0.v0radius() < resoCutVals[kRadiusMin][K0] || v0.v0radius() > resoCutVals[kRadiusMax][K0])) + if (resoSwitchVals[UseV0Radius][K0] && (v0.v0radius() < resoCutVals[RadiusMin][K0] || v0.v0radius() > resoCutVals[RadiusMax][K0])) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillV0Radius); + registryQA.fill(HIST("K0/hK0Count"), FillV0Radius); // cosine pointing angle cuts - if (v0.v0cosPA() < resoCutVals[kCosPA][K0]) + if (v0.v0cosPA() < resoCutVals[CosPA][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillCosPA); + registryQA.fill(HIST("K0/hK0Count"), FillCosPA); // Proper lifetime - if (resoSwitchVals[kUseProperLifetime][K0] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[kLifeTime][K0]) + if (resoSwitchVals[UseProperLifetime][K0] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[LifeTime][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillProperLifetime); + registryQA.fill(HIST("K0/hK0Count"), FillProperLifetime); // ArmenterosPodolanskiCut - if (resoSwitchVals[kUseArmPodCut][K0] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[kArmPodMin][K0]) + if (resoSwitchVals[UseArmPodCut][K0] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[ArmPodMin][K0]) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillArmPodCut); - if (resoSwitchVals[kUseCompetingMassRejection][K0]) { - if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < resoCutVals[kMassRejection][K0]) + registryQA.fill(HIST("K0/hK0Count"), FillArmPodCut); + if (resoSwitchVals[UseCompetingMassRejection][K0]) { + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < resoCutVals[MassRejection][K0]) return false; - if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < resoCutVals[kMassRejection][K0]) + if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < resoCutVals[MassRejection][K0]) return false; } - registryQA.fill(HIST("K0/hK0Count"), kFillCompetingMass); - if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PIONS)) + registryQA.fill(HIST("K0/hK0Count"), FillCompetingMass); + if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Pions)) return false; - registryQA.fill(HIST("K0/hK0Count"), kFillDaughterTrackSelection); + registryQA.fill(HIST("K0/hK0Count"), FillDaughterTrackSelection); registryQA.fill(HIST("K0/hK0Mass_sparse"), massK0s, v0.pt(), centrality); registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); @@ -1827,12 +1884,20 @@ struct FlowGenericFramework { registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); } + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); + } + return true; } - template - bool selectLambda(TCollision const& collision, TV0 const& v0, const double& centrality, double& weff) + template + bool selectLambda(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality, double& weff) { + using V0TrackTable = std::decay_t; bool isL = false; // Is lambda candidate bool isAL = false; // Is anti-lambda candidate @@ -1840,71 +1905,71 @@ struct FlowGenericFramework { double mantilambda = v0.mAntiLambda(); // separate the positive and negative V0 daughters - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillCandidate); - if (postrack.pt() < resoCutVals[kPosTrackPt][LAMBDA] || negtrack.pt() < resoCutVals[kNegTrackPt][LAMBDA]) + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCandidate); + if (postrack.pt() < resoCutVals[PosTrackPt][Lambda] || negtrack.pt() < resoCutVals[NegTrackPt][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillDaughterPt); - if (mlambda > resoCutVals[kMassMin][LAMBDA] && mlambda < resoCutVals[kMassMax][LAMBDA]) + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterPt); + if (mlambda > resoCutVals[MassMin][Lambda] && mlambda < resoCutVals[MassMax][Lambda]) isL = true; - if (mantilambda > resoCutVals[kMassMin][LAMBDA] && mantilambda < resoCutVals[kMassMax][LAMBDA]) + if (mantilambda > resoCutVals[MassMin][Lambda] && mantilambda < resoCutVals[MassMax][Lambda]) isAL = true; if (!isL && !isAL) { return false; } - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillMassCut); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillMassCut); // Rapidity correction - if (v0.yLambda() > resoCutVals[kRapidity][LAMBDA]) + if (v0.yLambda() > resoCutVals[Rapidity][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillRapidityCut); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillRapidityCut); // DCA cuts for lambda and antilambda if (isL) { - if (std::abs(v0.dcapostopv()) < resoCutVals[kDCAPosToPVMin][LAMBDA] || std::abs(v0.dcanegtopv()) < resoCutVals[kDCANegToPVMin][LAMBDA]) + if (std::abs(v0.dcapostopv()) < resoCutVals[DCAPosToPVMin][Lambda] || std::abs(v0.dcanegtopv()) < resoCutVals[DCANegToPVMin][Lambda]) return false; } if (isAL) { - if (std::abs(v0.dcapostopv()) < resoCutVals[kDCANegToPVMin][LAMBDA] || std::abs(v0.dcanegtopv()) < resoCutVals[kDCAPosToPVMin][LAMBDA]) + if (std::abs(v0.dcapostopv()) < resoCutVals[DCANegToPVMin][Lambda] || std::abs(v0.dcanegtopv()) < resoCutVals[DCAPosToPVMin][Lambda]) return false; } - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillDCAtoPV); - if (resoSwitchVals[kUseDCAxDaughters][LAMBDA] && std::abs(v0.dcaV0daughters()) > resoCutVals[kDCAxDaughters][LAMBDA]) + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAtoPV); + if (resoSwitchVals[UseDCAxDaughters][Lambda] && std::abs(v0.dcaV0daughters()) > resoCutVals[DCAxDaughters][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillDCAxDaughters); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAxDaughters); // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][LAMBDA] && (v0.v0radius() < resoCutVals[kRadiusMin][LAMBDA] || v0.v0radius() > resoCutVals[kRadiusMax][LAMBDA])) + if (resoSwitchVals[UseV0Radius][Lambda] && (v0.v0radius() < resoCutVals[RadiusMin][Lambda] || v0.v0radius() > resoCutVals[RadiusMax][Lambda])) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillV0Radius); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillV0Radius); // cosine pointing angle cuts - if (v0.v0cosPA() < resoCutVals[kCosPA][LAMBDA]) + if (v0.v0cosPA() < resoCutVals[CosPA][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillCosPA); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCosPA); // Proper lifetime - if (resoSwitchVals[kUseProperLifetime][LAMBDA] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[kLifeTime][LAMBDA]) + if (resoSwitchVals[UseProperLifetime][Lambda] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LifeTime][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillProperLifetime); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillProperLifetime); // ArmenterosPodolanskiCut - if (resoSwitchVals[kUseArmPodCut][LAMBDA] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[kArmPodMin][LAMBDA]) + if (resoSwitchVals[UseArmPodCut][Lambda] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[ArmPodMin][Lambda]) return false; - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillArmPodCut); - if (resoSwitchVals[kUseCompetingMassRejection][LAMBDA]) { - if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[kMassRejection][LAMBDA]) + registryQA.fill(HIST("Lambda/hLambdaCount"), FillArmPodCut); + if (resoSwitchVals[UseCompetingMassRejection][Lambda]) { + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[MassRejection][Lambda]) return false; } - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillCompetingMass); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillCompetingMass); if (isL) { - if (!selectionV0Daughter(postrack, PROTONS) || !selectionV0Daughter(negtrack, PIONS)) + if (!selectionV0Daughter(postrack, Protons) || !selectionV0Daughter(negtrack, Pions)) return false; } if (isAL) { - if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PROTONS)) + if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Protons)) return false; } - registryQA.fill(HIST("Lambda/hLambdaCount"), kFillDaughterTrackSelection); + registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelection); if (isL) { registryQA.fill(HIST("Lambda/hLambdaMass_sparse"), mlambda, v0.pt(), centrality); @@ -1923,6 +1988,11 @@ struct FlowGenericFramework { if (weff > 0) registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); } + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_proton"), postrack.pt(), centrality); + } } if (isAL) { registryQA.fill(HIST("Lambda/hAntiLambdaMass_sparse"), mantilambda, v0.pt(), centrality); @@ -1941,15 +2011,21 @@ struct FlowGenericFramework { if (weff > 0) registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); } + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_proton"), negtrack.pt(), centrality); + } } + return true; } template inline void fillPtSums(TTrack track, const double& vtxz) { - double wacc = (dt == kGen) ? 1. : getAcceptance(track, vtxz, 0); - double weff = (dt == kGen) ? 1. : getEfficiency(track); + double wacc = (dt == Gen) ? 1. : getAcceptance(track, vtxz, 0); + double weff = (dt == Gen) ? 1. : getEfficiency(track); if (weff < 0) return; @@ -1985,9 +2061,9 @@ struct FlowGenericFramework { if (!withinPtPOI && !withinPtRef) return; - double waccRef = (dt == kGen) ? 1. : getAcceptance(track, vtxz, 0); - double waccPOI = (dt == kGen) ? 1. : withinPtPOI ? getAcceptance(track, vtxz, pid_index + 1) - : getAcceptance(track, vtxz, 0); // + double waccRef = (dt == Gen) ? 1. : getAcceptance(track, vtxz, 0); + double waccPOI = (dt == Gen) ? 1. : withinPtPOI ? getAcceptance(track, vtxz, pid_index + 1) + : getAcceptance(track, vtxz, 0); // if (withinPtRef && withinPtPOI && pid_index) waccRef = waccPOI; // if particle is both (then it's overlap), override ref with POI if (withinPtRef) @@ -2005,10 +2081,10 @@ struct FlowGenericFramework { bool withinPtPOI = (track.pt() > o2::analysis::gfw::ptpoilow && track.pt() < o2::analysis::gfw::ptpoiup); if (!withinPtPOI && !withinPtRef) return; - double weff = (dt == kGen) ? 1. : getEfficiency(track, 0); + double weff = (dt == Gen) ? 1. : getEfficiency(track, 0); if (weff < 0) return; - if (cfgUseDensityDependentCorrection && withinPtRef && dt != kGen) { + if (cfgUseDensityDependentCorrection && withinPtRef && dt != Gen) { double fphi = densitycorrections.v2 * std::cos(2 * (track.phi() - densitycorrections.psi2Est)) + densitycorrections.v3 * std::cos(3 * (track.phi() - densitycorrections.psi3Est)) + densitycorrections.v4 * std::cos(4 * (track.phi() - densitycorrections.psi4Est)); fphi = (1 + 2 * fphi); int pTBinForEff = hFindPtBin->FindBin(track.pt()); @@ -2020,7 +2096,7 @@ struct FlowGenericFramework { } } } - double wacc = (dt == kGen) ? 1. : getAcceptance(track, vtxz, 0); + double wacc = (dt == Gen) ? 1. : getAcceptance(track, vtxz, 0); if (withinPtRef) fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 1); if (withinPtPOI) @@ -2034,12 +2110,12 @@ struct FlowGenericFramework { template inline void fillTrackQA(TTrack track, const float vtxz) { - if constexpr (dt == kGen) { + if constexpr (dt == Gen) { registryQA.fill(HIST("MCGen/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ_gen"), track.phi(), track.eta(), vtxz); registryQA.fill(HIST("MCGen/") + HIST(FillTimeName[ft]) + HIST("pt_gen"), track.pt()); } else { double wacc = getAcceptance(track, vtxz, 0); - registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz, (ft == kAfter) ? wacc : 1.0); + registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz, (ft == After) ? wacc : 1.0); registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_dcaXY_dcaZ"), track.pt(), track.dcaXY(), track.dcaZ()); registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("chi2prTPCcls"), track.tpcChi2NCl()); @@ -2048,7 +2124,7 @@ struct FlowGenericFramework { registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nITSClusters"), track.itsNCls()); registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nTPCCrossedRows"), track.tpcNClsCrossedRows()); - if (ft == kAfter) { + if (ft == After) { registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_ref"), track.pt()); registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_poi"), track.pt()); @@ -2064,19 +2140,19 @@ struct FlowGenericFramework { float getCentrality(TCollision collision) { switch (cfgCentEstimator) { - case kCentFT0C: + case CentFT0C: return collision.centFT0C(); - case kCentFT0CVariant1: + case CentFT0CVariant1: return collision.centFT0CVariant1(); - case kCentFT0M: + case CentFT0M: return collision.centFT0M(); - case kCentFV0A: + case CentFV0A: return collision.centFV0A(); - case kCentNTPV: + case CentNTPV: return collision.centNTPV(); - case kCentNGlobal: + case CentNGlobal: return collision.centNGlobal(); - case kCentMFT: + case CentMFT: return collision.centMFT(); default: return collision.centFT0C(); @@ -2102,6 +2178,7 @@ struct FlowGenericFramework { using GFWCollisions = soa::Filtered>; // using GFWTracks = soa::Filtered>; using GFWTracks = soa::Filtered>; + using GFWMCTracks = soa::Filtered>; SliceCache cache; Partition posTracks = aod::track::signed1Pt > 0.0f; @@ -2134,12 +2211,12 @@ struct FlowGenericFramework { loadCorrections(bc); registryQA.fill(HIST("eventQA/eventSel"), 0.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(0.5); + th1sList[run][EventSel]->Fill(0.5); if (!collision.sel8()) return; registryQA.fill(HIST("eventQA/eventSel"), 1.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(1.5); + th1sList[run][EventSel]->Fill(1.5); float centrality = getCentrality(collision); if (cfgDoOccupancySel) { @@ -2151,25 +2228,26 @@ struct FlowGenericFramework { } registryQA.fill(HIST("eventQA/eventSel"), 2.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(2.5); + th1sList[run][EventSel]->Fill(2.5); if (cfgFillQA) - fillEventQA(collision, tracks); + fillEventQA(collision, tracks); registryQA.fill(HIST("eventQA/before/centrality"), centrality); registryQA.fill(HIST("eventQA/before/multiplicity"), tracks.size()); if (!eventSelected(collision, tracks.size(), centrality, run)) return; if (cfgFillQA) - fillEventQA(collision, tracks); + fillEventQA(collision, tracks); registryQA.fill(HIST("eventQA/after/centrality"), centrality); registryQA.fill(HIST("eventQA/after/multiplicity"), tracks.size()); // Get magnetic field polarity - auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) + int defaultMagCut = 99999; + auto field = (cfgMagField == defaultMagCut) ? getMagneticField(bc.timestamp()) : cfgMagField; - processCollision(collision, tracks, v0s, centrality, field, run); + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processData, "Process analysis for non-derived data", true); - void processMCReco(GFWCollisions::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&, aod::V0Datas const& v0s) + void processMCReco(GFWCollisions::iterator const& collision, aod::BCsWithTimestamps const&, GFWMCTracks const& tracks, aod::McParticles const&, aod::V0Datas const& v0s) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -2181,14 +2259,14 @@ struct FlowGenericFramework { registryQA.fill(HIST("eventQA/eventSel"), 0.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(0.5); + th1sList[run][EventSel]->Fill(0.5); if (!collision.sel8()) return; registryQA.fill(HIST("eventQA/eventSel"), 1.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(1.5); + th1sList[run][EventSel]->Fill(1.5); const auto centrality = getCentrality(collision); @@ -2201,20 +2279,20 @@ struct FlowGenericFramework { } registryQA.fill(HIST("eventQA/eventSel"), 2.5); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(2.5); + th1sList[run][EventSel]->Fill(2.5); if (cfgFillQA) - fillEventQA(collision, tracks); + fillEventQA(collision, tracks); if (!eventSelected(collision, tracks.size(), centrality, run)) return; if (cfgFillQA) - fillEventQA(collision, tracks); + fillEventQA(collision, tracks); if (!cfgFillWeights) loadCorrections(bc); - - auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) - processCollision(collision, tracks, v0s, centrality, field, run); + int defaultMagCut = 99999; + auto field = (cfgMagField == defaultMagCut) ? getMagneticField(bc.timestamp()) : cfgMagField; + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processMCReco, "Process analysis for MC reconstructed events", false); @@ -2228,7 +2306,7 @@ struct FlowGenericFramework { centrality = getCentrality(collision); } int run = 0; - processCollision(mcCollision, particles, v0s, centrality, -999, run); + processCollision(mcCollision, particles, v0s, centrality, -999, run); } PROCESS_SWITCH(FlowGenericFramework, processMCGen, "Process analysis for MC generated events", false); @@ -2236,7 +2314,7 @@ struct FlowGenericFramework { { int run = 0; registryQA.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); - processCollision(mcCollision, mcParticles, v0s, mcCollision.impactParameter(), -999, run); + processCollision(mcCollision, mcParticles, v0s, mcCollision.impactParameter(), -999, run); } PROCESS_SWITCH(FlowGenericFramework, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); @@ -2254,9 +2332,9 @@ struct FlowGenericFramework { const auto centrality = collision.centRun2V0M(); if (!cfgFillWeights) loadCorrections(bc); - - auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) - processCollision(collision, tracks, v0s, centrality, field, run); + int defaultMagCut = 99999; + auto field = (cfgMagField == defaultMagCut) ? getMagneticField(bc.timestamp()) : cfgMagField; + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processRun2, "Process analysis for Run 2 converted data", false); }; From 984b3fc0f0923b3251b2cd278185ade189d3fdef Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Thu, 7 May 2026 14:18:30 +0200 Subject: [PATCH 079/449] [PWGCF] FemtoUniverse V0 Task -- fixed an incorrect comment (#16127) Co-authored-by: Shirajum Monira --- .../Tasks/femtoUniversePairTaskTrackV0Extended.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index ed3237ed0bc..57f8f414e16 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -699,7 +699,7 @@ struct FemtoUniversePairTaskTrackV0Extended { // track cleaning & checking for duplicate pairs if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { - // mark for rejection the cascade that shares a daughter with another cascade and has an invariant mass further from default value + // mark for rejection the v0 that shares a daughter with another v0 and has an invariant mass further from default value. Set confV0DuplCosPA as TRUE to do the same check with cosPA instead. if (!ConfV0Selection.confV0DuplCosPA) { if (std::abs(p1.mLambda() - v0InvMass[ConfV0Selection.confV0Type1]) < std::abs(p2.mLambda() - v0InvMass[ConfV0Selection.confV0Type2])) { v0Duplicates.insert(p2.globalIndex()); From 5af2a9dd6a3c206233ed9f2679015e404e68618e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Thu, 7 May 2026 15:08:43 +0200 Subject: [PATCH 080/449] [PWGHF] Fix a bug for kaon pid in charm femto track task (#16147) Co-authored-by: ALICE Action Bot --- PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx index eb197529980..fcfd59ea839 100644 --- a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx +++ b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx @@ -391,7 +391,7 @@ struct HfProducerCharmHadronsTrackFemtoDream { if (std::abs(nSigmaCombKa) >= kaonPidSel.nSigmaCombKaTightMax) { isTrackKaonPidMethod2 = false; } - if (std::abs(nSigmaCombPi) >= kaonPidSel.nSigmaCombPiMax) { + if (std::abs(nSigmaCombPi) <= kaonPidSel.nSigmaCombPiMax) { isTrackKaonPidMethod2 = false; } } From b0e977268690817b47b7d99d3be538b983741281 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Thu, 7 May 2026 15:28:36 +0200 Subject: [PATCH 081/449] [PWGHF] Decouple SP and EsE process functions (#16143) --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 188 ++++++++++++++++------- PWGHF/D2H/Utils/utilsFlow.h | 57 ++++++- 2 files changed, 179 insertions(+), 66 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 14d9c2c190f..6e228d572dc 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -105,6 +105,12 @@ enum DecayChannel { DplusToPiKPi = 0, Xic0ToXiPi }; +enum RunMode { + kSP = 0, + kEsE, + kSPEsE, +}; + struct HfTaskFlowCharmHadrons { Produces rowCandMassPtMl; Produces rowCandMassPtMlSpCent; @@ -119,6 +125,7 @@ struct HfTaskFlowCharmHadrons { Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable storeEP{"storeEP", false, "Flag to store EP-related axis"}; Configurable storeMl{"storeMl", false, "Flag to store ML scores"}; + Configurable storeSPQVec{"storeSPQVec", true, "Flag to store the Q-vectors for SP"}; Configurable storeRedQVec{"storeRedQVec", false, "Flag to store reduced Q-vectors for ESE"}; Configurable fillMassPtMlTree{"fillMassPtMlTree", false, "Flag to fill mass, pt and ML scores tree"}; Configurable fillMassPtMlSpCentTree{"fillMassPtMlSpCentTree", false, "Flag to fill mass, pt, ML scores, SP and centrality tree"}; @@ -153,7 +160,9 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithSPQvecs = soa::Join; + using CollsWithEsEQvecs = soa::Join; + using CollsWithSPEsEQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -212,6 +221,12 @@ struct HfTaskFlowCharmHadrons { if (storeResoOccu && occEstimator == 0) { LOGP(fatal, "Occupancy estimation must be enabled to store resolution THnSparse! Please check your configuration!"); } + if (storeRedQVec && !doprocessD0EsEMl && !doprocessD0SPEsEMl) { + LOGP(fatal, "EsE q-vectors require dedicated process functions. Please check your configuration!"); + } + if (storeSPQVec && doprocessD0EsEMl) { + LOGP(fatal, "Scalar product tables not available for this process function. Please check your configuration!"); + } const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "Inv. mass (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality"}; @@ -237,7 +252,10 @@ struct HfTaskFlowCharmHadrons { const AxisSpec thnAxisResoFT0cTPCtot{thnConfigAxisResoFT0cTPCtot, "Q_{FT0c} #bullet Q_{TPCtot}"}; const AxisSpec thnAxisResoFV0aTPCtot{thnConfigAxisResoFV0aTPCtot, "Q_{FV0a} #bullet Q_{TPCtot}"}; - std::vector axes = {thnAxisInvMass, thnAxisPt, thnAxisCent, thnAxisScalarProd}; + std::vector axes = {thnAxisInvMass, thnAxisPt, thnAxisCent}; + if (storeSPQVec) { + axes.insert(axes.end(), {thnAxisScalarProd}); + } if (storeEP) { axes.insert(axes.end(), {thnAxisCosNPhi, thnAxisSinNPhi, thnAxisCosDeltaPhi}); } @@ -279,7 +297,7 @@ struct HfTaskFlowCharmHadrons { registry.add("ep/hSparseEp", "THn for Event Plane distirbution", {HistType::kTHnSparseF, {thnAxisCent, thnAxisPsi, thnAxisCosNPhi, thnAxisSinNPhi}}); } - if (doprocessResolution) { // enable resolution histograms only for resolution process + if (doprocessResolutionSP || doprocessResolutionSPEsE) { // enable resolution histograms only for resolution process registry.add("spReso/hSpResoFT0cFT0a", "hSpResoFT0cFT0a; centrality; Q_{FT0c} #bullet Q_{FT0a}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0cFV0a", "hSpResoFT0cFV0a; centrality; Q_{FT0c} #bullet Q_{FV0a}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoFT0cTPCpos", "hSpResoFT0cTPCpos; centrality; Q_{FT0c} #bullet Q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); @@ -298,9 +316,12 @@ struct HfTaskFlowCharmHadrons { registry.add("spReso/hSpResoFV0aTPCtot", "hSpResoFV0aTPCtot; centrality; Q_{FV0a} #bullet Q_{TPCtot}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); registry.add("spReso/hSpResoTPCposTPCneg", "hSpResoTPCposTPCneg; centrality; Q_{TPCpos} #bullet Q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisScalarProd}}); - if (storeRedQVec) { + if (doprocessResolutionSPEsE) { registry.add("redQVecs/hSparseRedQVecs", "hSpResoRedQVec; centrality; Q_{red} #bullet Q_{TPCtot}", {HistType::kTHnSparseF, {thnAxisCent, thnAxisRedQVec, thnAxisRedQVec, thnAxisRedQVec, thnAxisRedQVec}}); registry.add("redQVecs/hRedQVecFT0C", "hRedQVecFT0C; centrality; q_{FT0c}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecFT0A", "hRedQVecFT0A; centrality; q_{FT0a}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecFT0M", "hRedQVecFT0M; centrality; q_{FT0m}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); + registry.add("redQVecs/hRedQVecFV0A", "hRedQVecFV0A; centrality; q_{FV0a}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); registry.add("redQVecs/hRedQVecTpcPos", "hRedQVecTpcPos; centrality; q_{TPCpos}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); registry.add("redQVecs/hRedQVecTpcNeg", "hRedQVecTpcNeg; centrality; q_{TPCneg}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); registry.add("redQVecs/hRedQVecTpcAll", "hRedQVecTpcAll; centrality; q_{TPCall}", {HistType::kTH2F, {thnAxisCent, thnAxisRedQVec}}); @@ -472,7 +493,9 @@ struct HfTaskFlowCharmHadrons { values.push_back(mass); values.push_back(pt); values.push_back(cent); - values.push_back(sp); + if (storeSPQVec) { + values.push_back(sp); + } if (storeEP) { values.push_back(cosNPhi); @@ -518,8 +541,8 @@ struct HfTaskFlowCharmHadrons { /// \param bc is the bunch crossing with timestamp information /// \param centrality is the collision centrality /// \return true if the collision is selected, false otherwise - template - bool isCollSelected(CollsWithQvecs::iterator const& collision, + template + bool isCollSelected(TCollision const& collision, aod::BCsWithTimestamps const&, float& centrality) { @@ -539,8 +562,8 @@ struct HfTaskFlowCharmHadrons { /// Compute the scalar product /// \param collision is the collision with the Q vector information and event plane /// \param candidates are the selected candidates - template - void runFlowAnalysis(CollsWithQvecs::iterator const& collision, + template + void runFlowAnalysis(TCollision const& collision, T1 const& candidates, Trk const& /*tracks*/) { @@ -563,7 +586,10 @@ struct HfTaskFlowCharmHadrons { float const sigmaMDplus = 0.015; // used 15 MeV as the D+ average peak width in run3 float const nSigmaMass = 2.5; - std::array qVecs = getQvec(collision, qVecDetector.value); + std::array qVecs{-999.f, -999.f, -999.f}; + if constexpr (StoreInfo == RunMode::kSP || StoreInfo == RunMode::kSPEsE) { + qVecs = getQvec(collision, qVecDetector.value); + } float xQVec = qVecs[0]; float yQVec = qVecs[1]; float const amplQVec = qVecs[2]; @@ -571,7 +597,7 @@ struct HfTaskFlowCharmHadrons { float redQVec{-999.f}; std::array qVecRedComps{-999.f, -999.f, -999.f}; - if (storeRedQVec) { + if constexpr (StoreInfo == RunMode::kEsE || StoreInfo == RunMode::kSPEsE) { qVecRedComps = getEseQvec(collision, qVecRedDetector.value); } float xRedQVec = qVecRedComps[0]; @@ -798,142 +824,169 @@ struct HfTaskFlowCharmHadrons { } // Ds with ML - void processDsMl(CollsWithQvecs::iterator const& collision, + void processDsMl(CollsWithSPQvecs::iterator const& collision, CandDsDataWMl const&, TracksWithExtra const& tracks) { auto candsDsToKKPiWMl = selectedDsToKKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsDsToPiKKWMl = selectedDsToPiKKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsDsToKKPiWMl, tracks); - runFlowAnalysis(collision, candsDsToPiKKWMl, tracks); + runFlowAnalysis(collision, candsDsToKKPiWMl, tracks); + runFlowAnalysis(collision, candsDsToPiKKWMl, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processDsMl, "Process Ds candidates with ML", false); // Ds with rectangular cuts - void processDs(CollsWithQvecs::iterator const& collision, + void processDs(CollsWithSPQvecs::iterator const& collision, CandDsData const& /*candidatesDs*/, TracksWithExtra const& tracks) { auto candsDsToKKPi = selectedDsToKKPi->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsDsToPiKK = selectedDsToPiKK->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsDsToKKPi, tracks); - runFlowAnalysis(collision, candsDsToPiKK, tracks); + runFlowAnalysis(collision, candsDsToKKPi, tracks); + runFlowAnalysis(collision, candsDsToPiKK, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processDs, "Process Ds candidates", false); // Dplus with ML - void processDplusMl(CollsWithQvecs::iterator const& collision, + void processDplusMl(CollsWithSPQvecs::iterator const& collision, CandDplusDataWMl const& candidatesDplus, TracksWithExtra const& tracks) { - runFlowAnalysis(collision, candidatesDplus, tracks); + runFlowAnalysis(collision, candidatesDplus, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processDplusMl, "Process Dplus candidates with ML", false); // Dplus with rectangular cuts - void processDplus(CollsWithQvecs::iterator const& collision, + void processDplus(CollsWithSPQvecs::iterator const& collision, CandDplusData const& candidatesDplus, TracksWithExtra const& tracks) { - runFlowAnalysis(collision, candidatesDplus, tracks); + runFlowAnalysis(collision, candidatesDplus, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processDplus, "Process Dplus candidates", true); // D0 with ML - void processD0Ml(CollsWithQvecs::iterator const& collision, + void processD0Ml(CollsWithSPQvecs::iterator const& collision, CandD0DataWMl const& /*candidatesD0*/, TracksWithExtra const& tracks) { auto candsD0ToPiKWMl = selectedD0ToPiKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsD0ToKPiWMl = selectedD0ToKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsD0ToPiKWMl, tracks); - runFlowAnalysis(collision, candsD0ToKPiWMl, tracks); + runFlowAnalysis(collision, candsD0ToPiKWMl, tracks); + runFlowAnalysis(collision, candsD0ToKPiWMl, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processD0Ml, "Process D0 candidates with ML", false); + // D0 with ML + void processD0EsEMl(CollsWithEsEQvecs::iterator const& collision, + CandD0DataWMl const& /*candidatesD0*/, + TracksWithExtra const& tracks) + { + auto candsD0ToPiKWMl = selectedD0ToPiKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto candsD0ToKPiWMl = selectedD0ToKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsD0ToPiKWMl, tracks); + runFlowAnalysis(collision, candsD0ToKPiWMl, tracks); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processD0EsEMl, "Process D0 candidates with ML for EsE information", false); + + // D0 with ML + void processD0SPEsEMl(CollsWithSPEsEQvecs::iterator const& collision, + CandD0DataWMl const& /*candidatesD0*/, + TracksWithExtra const& tracks) + { + auto candsD0ToPiKWMl = selectedD0ToPiKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto candsD0ToKPiWMl = selectedD0ToKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsD0ToPiKWMl, tracks); + runFlowAnalysis(collision, candsD0ToKPiWMl, tracks); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processD0SPEsEMl, "Process D0 candidates with ML for SP and EsE information", false); + // D0 with rectangular cuts - void processD0(CollsWithQvecs::iterator const& collision, + void processD0(CollsWithSPQvecs::iterator const& collision, CandD0Data const& /*candidatesD0*/, TracksWithExtra const& tracks) { auto candsD0ToPiK = selectedD0ToPiK->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsD0ToKPi = selectedD0ToKPi->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsD0ToPiK, tracks); - runFlowAnalysis(collision, candsD0ToKPi, tracks); + runFlowAnalysis(collision, candsD0ToPiK, tracks); + runFlowAnalysis(collision, candsD0ToKPi, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processD0, "Process D0 candidates", false); // Lc with ML - void processLcMl(CollsWithQvecs::iterator const& collision, + void processLcMl(CollsWithSPQvecs::iterator const& collision, CandLcDataWMl const& /*candidatesLc*/, TracksWithExtra const& tracks) { auto candsLcToPKPiWMl = selectedLcToPKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsLcToPiKPWMl = selectedLcToPiKPWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsLcToPKPiWMl, tracks); - runFlowAnalysis(collision, candsLcToPiKPWMl, tracks); + runFlowAnalysis(collision, candsLcToPKPiWMl, tracks); + runFlowAnalysis(collision, candsLcToPiKPWMl, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processLcMl, "Process Lc candidates with ML", false); // Lc with rectangular cuts - void processLc(CollsWithQvecs::iterator const& collision, + void processLc(CollsWithSPQvecs::iterator const& collision, CandLcData const& /*candidatesLc*/, TracksWithExtra const& tracks) { auto candsLcToPKPi = selectedLcToPKPi->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsLcToPiKP = selectedLcToPiKP->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsLcToPKPi, tracks); - runFlowAnalysis(collision, candsLcToPiKP, tracks); + runFlowAnalysis(collision, candsLcToPKPi, tracks); + runFlowAnalysis(collision, candsLcToPiKP, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processLc, "Process Lc candidates", false); // Xic with ML - void processXicMl(CollsWithQvecs::iterator const& collision, + void processXicMl(CollsWithSPQvecs::iterator const& collision, CandXicDataWMl const& /*candidatesXic*/, TracksWithExtra const& tracks) { auto candsXicToPKPiWMl = selectedXicToPKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsXicToPiKPWMl = selectedXicToPiKPWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsXicToPKPiWMl, tracks); - runFlowAnalysis(collision, candsXicToPiKPWMl, tracks); + runFlowAnalysis(collision, candsXicToPKPiWMl, tracks); + runFlowAnalysis(collision, candsXicToPiKPWMl, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXicMl, "Process Xic candidates with ML", false); // Xic with rectangular cuts - void processXic(CollsWithQvecs::iterator const& collision, + void processXic(CollsWithSPQvecs::iterator const& collision, CandXicData const& /*candidatesXic*/, TracksWithExtra const& tracks) { auto candsXicToPKPi = selectedXicToPKPi->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); auto candsXicToPiKP = selectedXicToPiKP->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsXicToPKPi, tracks); - runFlowAnalysis(collision, candsXicToPiKP, tracks); + runFlowAnalysis(collision, candsXicToPKPi, tracks); + runFlowAnalysis(collision, candsXicToPiKP, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic, "Process Xic candidates", false); // Xic0 with ML - void processXic0Ml(CollsWithQvecs::iterator const& collision, + void processXic0Ml(CollsWithSPQvecs::iterator const& collision, CandXic0DataWMl const& /*candidatesXic0*/, TracksWithExtra const& tracks) { auto candsXic0WMl = selectedXic0WMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsXic0WMl, tracks); + runFlowAnalysis(collision, candsXic0WMl, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0Ml, "Process Xic0 candidates with ML", false); // Xic0 - void processXic0(CollsWithQvecs::iterator const& collision, + void processXic0(CollsWithSPQvecs::iterator const& collision, CandXic0Data const& /*candidatesXic0*/, TracksWithExtra const& tracks) { auto candsXic0 = selectedXic0->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - runFlowAnalysis(collision, candsXic0, tracks); + runFlowAnalysis(collision, candsXic0, tracks); } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0, "Process Xic0 candidates", false); - // Resolution - void processResolution(CollsWithQvecs::iterator const& collision, - aod::BCsWithTimestamps const& bcs) + /// Compute resolution + /// \param collision is the collision with the Q vector information + /// \param bcs is used for the event selection based on centrality estimators with time information + template + void fillResolution(TCollision const& collision, + aod::BCsWithTimestamps const& bcs) { float centrality{-1.f}; float const xQVecFT0a = collision.qvecFT0ARe(); @@ -944,12 +997,12 @@ struct HfTaskFlowCharmHadrons { float const yQVecFT0m = collision.qvecFT0MIm(); float const xQVecFV0a = collision.qvecFV0ARe(); float const yQVecFV0a = collision.qvecFV0AIm(); - float const xQVecTPCPos = collision.qvecTPCposRe(); - float const yQVecTPCPos = collision.qvecTPCposIm(); - float const xQVecTPCNeg = collision.qvecTPCnegRe(); - float const yQVecTPCNeg = collision.qvecTPCnegIm(); - float const xQVecTPCAll = collision.qvecTPCallRe(); - float const yQVecTPCAll = collision.qvecTPCallIm(); + float const xQVecTPCPos = collision.qvecBPosRe(); + float const yQVecTPCPos = collision.qvecBPosIm(); + float const xQVecTPCNeg = collision.qvecBNegRe(); + float const yQVecTPCNeg = collision.qvecBNegIm(); + float const xQVecTPCAll = collision.qvecBTotRe(); + float const yQVecTPCAll = collision.qvecBTotIm(); centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (storeResoOccu) { @@ -970,7 +1023,7 @@ struct HfTaskFlowCharmHadrons { registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(0)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(1)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(2)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(3))); } - if (storeRedQVec) { + if constexpr (HasRedQVecs) { registry.fill(HIST("redQVecs/hSparseRedQVecs"), centrality, std::hypot(collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm()), std::hypot(collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm()), @@ -1001,11 +1054,15 @@ struct HfTaskFlowCharmHadrons { registry.fill(HIST("spReso/hSpResoFV0aTPCtot"), centrality, xQVecFV0a * xQVecTPCAll + yQVecFV0a * yQVecTPCAll); registry.fill(HIST("spReso/hSpResoTPCposTPCneg"), centrality, xQVecTPCPos * xQVecTPCNeg + yQVecTPCPos * yQVecTPCNeg); - registry.fill(HIST("redQVecs/hRedQVecFT0C"), centrality, std::hypot(collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm())); - registry.fill(HIST("redQVecs/hRedQVecTpcPos"), centrality, std::hypot(collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm())); - registry.fill(HIST("redQVecs/hRedQVecTpcNeg"), centrality, std::hypot(collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm())); - registry.fill(HIST("redQVecs/hRedQVecTpcAll"), centrality, std::hypot(collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm())); - + if constexpr (HasRedQVecs) { + registry.fill(HIST("redQVecs/hRedQVecFT0C"), centrality, std::hypot(collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm())); + registry.fill(HIST("redQVecs/hRedQVecFT0M"), centrality, std::hypot(collision.eseQvecFT0MRe(), collision.eseQvecFT0MIm())); + registry.fill(HIST("redQVecs/hRedQVecFT0A"), centrality, std::hypot(collision.eseQvecFT0ARe(), collision.eseQvecFT0AIm())); + registry.fill(HIST("redQVecs/hRedQVecFV0A"), centrality, std::hypot(collision.eseQvecFV0ARe(), collision.eseQvecFV0AIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcPos"), centrality, std::hypot(collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcNeg"), centrality, std::hypot(collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm())); + registry.fill(HIST("redQVecs/hRedQVecTpcAll"), centrality, std::hypot(collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm())); + } if (saveEpResoHisto) { float const epFT0a = epHelper.GetEventPlane(xQVecFT0a, yQVecFT0a, harmonic); float const epFT0c = epHelper.GetEventPlane(xQVecFT0c, yQVecFT0c, harmonic); @@ -1041,7 +1098,20 @@ struct HfTaskFlowCharmHadrons { std::sin(harmonic * epHelper.GetEventPlane(xQVecFT0c, yQVecFT0c, harmonic))); } } - PROCESS_SWITCH(HfTaskFlowCharmHadrons, processResolution, "Process resolution", false); + + void processResolutionSP(CollsWithSPQvecs::iterator const& collision, + aod::BCsWithTimestamps const& bcs) + { + fillResolution(collision, bcs); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processResolutionSP, "Process SP resolution", false); + + void processResolutionSPEsE(CollsWithSPEsEQvecs::iterator const& collision, + aod::BCsWithTimestamps const& bcs) + { + fillResolution(collision, bcs); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processResolutionSPEsE, "Process SP and EsE resolution", false); }; // End struct HfTaskFlowCharmHadrons diff --git a/PWGHF/D2H/Utils/utilsFlow.h b/PWGHF/D2H/Utils/utilsFlow.h index 911fc60dd2c..02171203eba 100644 --- a/PWGHF/D2H/Utils/utilsFlow.h +++ b/PWGHF/D2H/Utils/utilsFlow.h @@ -202,6 +202,49 @@ std::array getQvec(TCollision const& collision, const int qvecEst) return std::array{-999.f, -999.f, -999.f}; } +/// Get the EsE Q vector +template +concept HasEsEQvecFT0A = requires(T collision) { + collision.eseQvecFT0ARe(); + collision.eseQvecFT0AIm(); +}; + +template +concept HasEsEQvecFT0C = requires(T collision) { + collision.eseQvecFT0CRe(); + collision.eseQvecFT0CIm(); +}; + +template +concept HasEsEQvecFT0M = requires(T collision) { + collision.eseQvecFT0MRe(); + collision.eseQvecFT0MIm(); +}; + +template +concept HasEsEQvecFV0A = requires(T collision) { + collision.eseQvecFV0ARe(); + collision.eseQvecFV0AIm(); +}; + +template +concept HasEsEQvecTPCpos = requires(T collision) { + collision.eseQvecTPCposRe(); + collision.eseQvecTPCposIm(); +}; + +template +concept HasEsEQvecTPCneg = requires(T collision) { + collision.eseQvecTPCnegRe(); + collision.eseQvecTPCnegIm(); +}; + +template +concept HasEsEQvecTPCtot = requires(T collision) { + collision.eseQvecTPCallRe(); + collision.eseQvecTPCallIm(); +}; + /// Get the Ese Q vector choosing your favourite estimator /// \param collision is the collision with the Q vector information /// \param qvecEst is the chosen Q-vector estimator @@ -210,37 +253,37 @@ std::array getEseQvec(TCollision const& collision, const int qvecEst) { switch (qvecEst) { case QvecEstimator::FV0A: - if constexpr (HasQvecFV0A) { + if constexpr (HasEsEQvecFV0A) { return std::array{collision.eseQvecFV0ARe(), collision.eseQvecFV0AIm(), collision.sumAmplFV0A()}; } break; case QvecEstimator::FT0A: - if constexpr (HasQvecFT0A) { + if constexpr (HasEsEQvecFT0A) { return std::array{collision.eseQvecFT0ARe(), collision.eseQvecFT0AIm(), collision.sumAmplFT0A()}; } break; case QvecEstimator::FT0C: - if constexpr (HasQvecFT0C) { + if constexpr (HasEsEQvecFT0C) { return std::array{collision.eseQvecFT0CRe(), collision.eseQvecFT0CIm(), collision.sumAmplFT0C()}; } break; case QvecEstimator::FT0M: - if constexpr (HasQvecFT0M) { + if constexpr (HasEsEQvecFT0M) { return std::array{collision.eseQvecFT0MRe(), collision.eseQvecFT0MIm(), collision.sumAmplFT0M()}; } break; case QvecEstimator::TPCPos: - if constexpr (HasQvecTPCpos) { + if constexpr (HasEsEQvecTPCpos) { return std::array{collision.eseQvecTPCposRe(), collision.eseQvecTPCposIm(), static_cast(collision.nTrkTPCpos())}; } break; case QvecEstimator::TPCNeg: - if constexpr (HasQvecTPCneg) { + if constexpr (HasEsEQvecTPCneg) { return std::array{collision.eseQvecTPCnegRe(), collision.eseQvecTPCnegIm(), static_cast(collision.nTrkTPCneg())}; } break; case QvecEstimator::TPCTot: - if constexpr (HasQvecTPCtot) { + if constexpr (HasEsEQvecTPCtot) { return std::array{collision.eseQvecTPCallRe(), collision.eseQvecTPCallIm(), static_cast(collision.nTrkTPCall())}; } break; From 85b815c722402c5f58fa6a408cc18f557fbf5984 Mon Sep 17 00:00:00 2001 From: Joachim Carlo Kristian Bjerg Hansen <50103987+joachimckh@users.noreply.github.com> Date: Thu, 7 May 2026 15:54:35 +0200 Subject: [PATCH 082/449] [PWGJE] occupancy qa changes (#16141) --- PWGJE/Tasks/jetSpectraEseTask.cxx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index c459561b70c..04ac8b3c1e7 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -412,8 +412,11 @@ struct JetSpectraEseTask { registry.add("hTrackPt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTHnSparseF, {{centAxis}, {100, 0, 100}, {eseAxis}, {occAxis}}}); registry.add("hTrackEta", "track #eta;#eta_{track};entries", {HistType::kTH3F, {{centAxis}, {etaAxis}, {occAxis}}}); registry.add("hTrackPhi", "track #phi;#phi_{track};entries", {HistType::kTH3F, {{centAxis}, {phiAxis}, {occAxis}}}); - registry.add("hOccupancy", "Occupancy;Occupancy;entries", {HistType::kTH1F, {{occAxis}}}); + registry.add("hOccupancy", "Occupancy;Occupancy;entries", {HistType::kTH2F, {{centAxis}, {occAxis}}}); + registry.add("hOccupancyEv", "Occupancy;Occupancy;entries", {HistType::kTH1F, {{centAxis}, {occAxis}}}); registry.add("hPsiOccupancy", "Occupancy;#Psi_{2};entries", {HistType::kTH3F, {{centAxis}, {150, -2.5, 2.5}, {occAxis}}}); + registry.add("hSTrackPtPhiEtaOcc", ";cent;jpt;phi;eta;occ", {HistType::kTHnSparseF, {{centAxis}, {100, 0, 100}, {phiAxis}, {etaAxis}, {occAxis}}}); + registry.add("hSJetPtPhiEtaOcc", ";cent;jpt;phi;eta;occ", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {phiAxis}, {etaAxis}, {occAxis}}}); } if (doprocessMCGenTrack) { LOGF(info, "JetSpectraEseTask::init() - MCGen track"); @@ -723,7 +726,7 @@ struct JetSpectraEseTask { PROCESS_SWITCH(JetSpectraEseTask, processESEBackground, "process random cones with event plane and ESE", false); void processESEOccupancy(soa::Join::iterator const& collision, - soa::Join const& tracks) + soa::Join const& tracks, soa::Filtered> const& jets) { float count{0.5}; registry.fill(HIST("hEventCounterOcc"), count++); @@ -732,22 +735,32 @@ struct JetSpectraEseTask { auto occupancy{collision.trackOccupancyInTimeRange()}; registry.fill(HIST("hPsiOccupancy"), collision.centFT0M(), psi.psi2, occupancy); - registry.fill(HIST("hOccupancy"), occupancy); + registry.fill(HIST("hOccupancy"), collision.centFT0M(), occupancy); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) return; registry.fill(HIST("hEventCounterOcc"), count++); + registry.fill(HIST("hOccupancyEv"), collision.centFT0M(), occupancy); for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; registry.fill(HIST("hTrackPt"), collision.centFT0M(), track.pt(), qPerc[0], occupancy); + registry.fill(HIST("hSTrackPtPhiEtaOcc"), collision.centFT0M(), track.pt(), track.phi(), track.eta(), occupancy); if (track.pt() < cfgOccupancyPtCut->at(0) || track.pt() > cfgOccupancyPtCut->at(1)) continue; registry.fill(HIST("hTrackEta"), collision.centFT0M(), track.eta(), occupancy); registry.fill(HIST("hTrackPhi"), collision.centFT0M(), track.phi(), occupancy); } + for (const auto& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) + continue; + if (!isAcceptedJet(jet)) { + continue; + } + registry.fill(HIST("hSJetPtPhiEtaOcc"), collision.centFT0M(), jet.pt(), jet.phi(), jet.eta(), occupancy); + } } PROCESS_SWITCH(JetSpectraEseTask, processESEOccupancy, "process occupancy", false); From ceb789eab8b4ea01f68a23a9703c5f76c251d425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Thu, 7 May 2026 16:35:22 +0200 Subject: [PATCH 083/449] [ALICE3] Fix includes (#16086) --- ALICE3/Core/Decayer.h | 1 - ALICE3/Core/TrackUtilities.h | 1 + ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 1 - ALICE3/Tasks/alice3TrackingPerformance.cxx | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 81f08f5412d..2280261dd21 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -30,7 +30,6 @@ #include #include -#include #include #include #include diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index bca0b82cf1a..1b042452899 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -22,6 +22,7 @@ #include +#include #include namespace o2::upgrade diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 614e0f6f84b..9c308ebe6ab 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/ALICE3/Tasks/alice3TrackingPerformance.cxx b/ALICE3/Tasks/alice3TrackingPerformance.cxx index bb47ffde7da..e29a914d848 100644 --- a/ALICE3/Tasks/alice3TrackingPerformance.cxx +++ b/ALICE3/Tasks/alice3TrackingPerformance.cxx @@ -37,7 +37,6 @@ #include #include #include -#include #include using namespace o2; From 0a90cef8ef3848dff0c02c14ab47a775d70b7179 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 7 May 2026 19:51:02 +0200 Subject: [PATCH 084/449] [PWGEM/Dilepton] update taggingHFE for LS eh pairs (#16154) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 152 ++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 7a1596e8233..943d30af4df 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -99,7 +99,7 @@ struct taggingHFE { Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgPdgLepton{"cfgPdgLepton", 11, "pdg code of desired lepton: 11 or 13"}; - Configurable cfgDownSampling{"cfgDownSampling", 1.1, "down sampling for fake matches"}; + Configurable cfgDownSamplingHc{"cfgDownSamplingHc", 1.1, "down sampling for charm hadrons"}; // there are enough hc, but not jpsi or hb. Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", true, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; struct : ConfigurableGroup { @@ -970,10 +970,6 @@ struct taggingHFE { continue; } - if (dist01(engine) > cfgDownSampling) { // random sampling, if necessary - continue; - } - fillEventHistograms(collision); fRegistry.fill(HIST("Event/hCollisionCounter"), 1); mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); @@ -1016,6 +1012,13 @@ struct taggingHFE { fRegistry.fill(HIST("Electron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); fRegistry.fill(HIST("Electron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Electron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + + auto mcMother = mcParticle.template mothers_as()[0]; + bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); + if (is_e_from_hc && dist01(engine) > cfgDownSamplingHc) { // random sampling hc, if necessary + continue; + } + if (track.sign() > 0) { // positron positronIds.emplace_back(trackId.trackId()); } else { // electron @@ -1182,7 +1185,7 @@ struct taggingHFE { auto mcMother_of_kaon = mckaon.template mothers_first_as(); if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); - if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { + if (commonMotherId > 0) { foundCommonMother = true; // LOGF(info, "eK: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } @@ -1220,6 +1223,71 @@ struct taggingHFE { } // end of kaon loop + for (const auto& kaonId : kaonPlusIds) { + auto kaon = tracks.rawIteratorAt(kaonId); + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(kaon); + trackParCov.setPID(kaon.pidForTracking()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY_kaon = mDcaInfoCov.getY(); + float dcaZ_kaon = mDcaInfoCov.getZ(); + + if (positronId == kaonId) { + continue; + } + + auto eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, pos, kaon, o2::track::PID::Electron, kaon.pidForTracking()); + if (!eKpair.isOK) { + continue; + } + if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + continue; + } + + auto mckaon = kaon.template mcParticle_as(); + bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; + if (mckaon.has_mothers() && !foundCommonMother) { + auto mcMother_of_kaon = mckaon.template mothers_first_as(); + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); + if (commonMotherId > 0) { + foundCommonMother = true; + // LOGF(info, "eK: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } + + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + // I want 3 types. + // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. + // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. + // 3. truely found DY->ee with misidentified ee. (SV may be found at the same position of PV.) For bkg sample in ML. + continue; + } + + // if (std::abs(mckaon.pdgCode()) == 11) { + // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); + // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { + // auto daughter = mcParticles.rawIteratorAt(d); + // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); + // } + // } + + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + + emmllhpair(leptonTable.lastIndex(), + trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), + kaon.tpcNSigmaPi(), tofNSigmaPi, + kaon.tpcNSigmaKa(), tofNSigmaKa, + eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.lxyz, eKpair.lxyzErr, + eKpair.lxy, eKpair.lxyErr, + eKpair.lz, eKpair.lzErr, + mckaon.pdgCode(), foundCommonMother); + + } // end of kaon loop + // D+ -> e+ K0S nu_e for (const auto& k0Id : k0Ids) { auto v0 = v0s.rawIteratorAt(k0Id); @@ -1271,7 +1339,7 @@ struct taggingHFE { auto mcMother_of_k0s = mcK0S.template mothers_first_as(); if (mcMother_of_k0s.pdgCode() == -323 || mcMother_of_k0s.pdgCode() == -313 || mcMother_of_k0s.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_k0s); - if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { // proton decay is implemented. reject it. + if (commonMotherId > 0) { foundCommonMother = true; // LOGF(info, "eK0S: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } @@ -1514,6 +1582,72 @@ struct taggingHFE { leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), isMotherFromB, mcMother.pdgCode()); + for (const auto& kaonId : kaonMinusIds) { + auto kaon = tracks.rawIteratorAt(kaonId); + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(kaon); + trackParCov.setPID(kaon.pidForTracking()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY_kaon = mDcaInfoCov.getY(); + float dcaZ_kaon = mDcaInfoCov.getZ(); + + if (electronId == kaonId) { + continue; + } + + auto eKpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(fitter_eK, collision, ele, kaon, o2::track::PID::Electron, kaon.pidForTracking()); + if (!eKpair.isOK) { + continue; + } + + if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + continue; + } + + auto mckaon = kaon.template mcParticle_as(); + bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; + if (mckaon.has_mothers() && !foundCommonMother) { + auto mcMother_of_kaon = mckaon.template mothers_first_as(); + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); + if (commonMotherId > 0) { + foundCommonMother = true; + // LOGF(info, "eK: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + } + } + } + + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + // I want 3 types. + // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. + // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. + // 3. truely found DY->ee with misidentified ee. (SV may be found at the same position of PV.) For bkg sample in ML. + continue; + } + + // if (std::abs(mckaon.pdgCode()) == 11) { + // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); + // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { + // auto daughter = mcParticles.rawIteratorAt(d); + // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); + // } + // } + + float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + + emmllhpair(leptonTable.lastIndex(), + trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), + kaon.tpcNSigmaPi(), tofNSigmaPi, + kaon.tpcNSigmaKa(), tofNSigmaKa, + eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.lxyz, eKpair.lxyzErr, + eKpair.lxy, eKpair.lxyErr, + eKpair.lz, eKpair.lzErr, + mckaon.pdgCode(), foundCommonMother); + + } // end of kaon loop + // D0bar -> e- anti-nu_e K+, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonPlusIds) { auto kaon = tracks.rawIteratorAt(kaonId); @@ -1542,7 +1676,7 @@ struct taggingHFE { auto mcMother_of_kaon = mckaon.template mothers_first_as(); if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); - if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { + if (commonMotherId > 0) { foundCommonMother = true; // LOGF(info, "eK: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } @@ -1630,7 +1764,7 @@ struct taggingHFE { auto mcMother_of_k0s = mcK0S.template mothers_first_as(); if (mcMother_of_k0s.pdgCode() == 323 || mcMother_of_k0s.pdgCode() == 313 || mcMother_of_k0s.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_k0s); - if (commonMotherId > 0 && std::abs(mcParticles.rawIteratorAt(commonMotherId).pdgCode()) != 2212) { // proton decay is implemented. reject it. + if (commonMotherId > 0) { foundCommonMother = true; // LOGF(info, "eK0S: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } From 42ca87a5031a41a3aaa7d61ff8ece1c17e31da06 Mon Sep 17 00:00:00 2001 From: spolitan <59452587+stefanopolitano@users.noreply.github.com> Date: Thu, 7 May 2026 22:36:32 +0200 Subject: [PATCH 085/449] [Common] Decouple EsE and EP Q vector correction (#16148) --- Common/TableProducer/qVectorsTable.cxx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index 574c370a16a..ce5152aace6 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -309,19 +309,21 @@ struct qVectorsTable { corrsQvecSp.push_back(modeCorrQvecSp); } - corrsQvecEse.clear(); - for (std::size_t i = 0; i < cfgnMods->size(); i++) { - int ind = cfgnMods->at(i); - fullPath = cfgQvecCalibPath; - fullPath += "/eseq"; - fullPath += std::to_string(ind); - auto modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); - if (!modeCorrQvecEse) { + if (cfgProduceRedQVecs) { + corrsQvecEse.clear(); + for (std::size_t i = 0; i < cfgnMods->size(); i++) { + int ind = cfgnMods->at(i); fullPath = cfgQvecCalibPath; - fullPath += "/eseq2"; - modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); + fullPath += "/eseq"; + fullPath += std::to_string(ind); + auto modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); + if (!modeCorrQvecEse) { + fullPath = cfgQvecCalibPath; + fullPath += "/eseq2"; + modeCorrQvecEse = getForTsOrRun(fullPath, timestamp, runnumber); + } + corrsQvecEse.push_back(modeCorrQvecEse); } - corrsQvecEse.push_back(modeCorrQvecEse); } if (cfgShiftCorr) { From e590fd163918be882a5d5c6effe04035e2653f0d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 7 May 2026 22:59:05 +0200 Subject: [PATCH 086/449] [PWGEM/Dilepton] update taggingHFE to include D* (#16155) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 4 ++-- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 30 +++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 4f6e03441e0..3de198ee03b 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -241,7 +241,7 @@ DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair DECLARE_SOA_COLUMN(LzSigma, lzSigma, float); //! decay length resolution of LH pair DECLARE_SOA_COLUMN(PdgCodeH, pdgCodeH, int); //! pdg code of associated hadron -DECLARE_SOA_COLUMN(PdgCodeHFH, pdgCodeHFH, int); //! pdg code of HF hadron +DECLARE_SOA_COLUMN(PdgCodeIM, pdgCodeIM, int); //! pdg code of intermediate hadron from HF hadrons. e.g K*, D* DECLARE_SOA_COLUMN(FoundCommonMother, foundCommonMother, bool); //! decay length resolution of LH pair } // namespace emmllhpair @@ -255,7 +255,7 @@ DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! emmllhpair::Lxyz, emmllhpair::LxyzSigma, emmllhpair::Lxy, emmllhpair::LxySigma, emmllhpair::Lz, emmllhpair::LzSigma, - emmllhpair::PdgCodeH, emmllhpair::FoundCommonMother); + emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLHPair = EMMLLHPairs::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 943d30af4df..592a332cff4 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1179,15 +1179,16 @@ struct taggingHFE { continue; } + int pdgCodeIM = 0; auto mckaon = kaon.template mcParticle_as(); bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413 || mcMother_of_kaon.pdgCode() == -423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + pdgCodeIM = mcMother_of_kaon.pdgCode(); } } } @@ -1219,7 +1220,7 @@ struct taggingHFE { eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, eKpair.lz, eKpair.lzErr, - mckaon.pdgCode(), foundCommonMother); + mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1244,15 +1245,16 @@ struct taggingHFE { continue; } + int pdgCodeIM = 0; auto mckaon = kaon.template mcParticle_as(); bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413 || mcMother_of_kaon.pdgCode() == -423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + pdgCodeIM = mcMother_of_kaon.pdgCode(); } } } @@ -1284,7 +1286,7 @@ struct taggingHFE { eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, eKpair.lz, eKpair.lzErr, - mckaon.pdgCode(), foundCommonMother); + mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1341,7 +1343,6 @@ struct taggingHFE { int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_k0s); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK0S: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } } } @@ -1604,15 +1605,16 @@ struct taggingHFE { continue; } + int pdgCodeIM = 0; auto mckaon = kaon.template mcParticle_as(); bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413 || mcMother_of_kaon.pdgCode() == 423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK: e+ and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + pdgCodeIM = mcMother_of_kaon.pdgCode(); } } } @@ -1644,7 +1646,7 @@ struct taggingHFE { eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, eKpair.lz, eKpair.lzErr, - mckaon.pdgCode(), foundCommonMother); + mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1670,15 +1672,16 @@ struct taggingHFE { continue; } + int pdgCodeIM = 0; auto mckaon = kaon.template mcParticle_as(); bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413 || mcMother_of_kaon.pdgCode() == 423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); + pdgCodeIM = mcMother_of_kaon.pdgCode(); } } } @@ -1710,7 +1713,7 @@ struct taggingHFE { eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, eKpair.lz, eKpair.lzErr, - mckaon.pdgCode(), foundCommonMother); + mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1766,7 +1769,6 @@ struct taggingHFE { int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_k0s); if (commonMotherId > 0) { foundCommonMother = true; - // LOGF(info, "eK0S: e- and K*(892) or phi is found. mother is %d", mcParticles.rawIteratorAt(commonMotherId).pdgCode()); } } } From bdcb6b15037937ca9e259aa96e4d6c59e0e63158 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 7 May 2026 23:25:35 +0200 Subject: [PATCH 087/449] [PWGEM/Dilepton] update skimmerPrimaryEelctronQC.cxx for flexible cut to tag (#16152) --- .../skimmerPrimaryElectronQC.cxx | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx index 3815e0bc335..cf4367dcb24 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx @@ -126,10 +126,18 @@ struct skimmerPrimaryElectronQC { Configurable maxchi2its{"maxchi2its", 5.0, "max. chi2/NclsITS"}; Configurable dca_xy_max{"dca_xy_max", 0.2, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 0.2, "max DCAz in cm"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; // Don't change. - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", +2.0, "max. TPC n sigma for electron inclusion"}; // Don't change. - Configurable minTOFNsigmaEl{"minTOFNsigmaEl", -2.0, "min. TOF n sigma for electron inclusion"}; // Don't change. - Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", +2.0, "max. TOF n sigma for electron inclusion"}; // Don't change. + Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", +2.0, "max. TPC n sigma for electron inclusion"}; + Configurable minTOFNsigmaEl{"minTOFNsigmaEl", -2.0, "min. TOF n sigma for electron inclusion"}; + Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", +2.0, "max. TOF n sigma for electron inclusion"}; + + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.5, "max. TPC n sigma for pion exclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 2.5, "max. TPC n sigma for kaon exclusion"}; + Configurable minTPCNsigmaKa{"minTPCNsigmaKa", -2.5, "min. TPC n sigma for kaon exclusion"}; + Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 2.5, "max. TPC n sigma for proton exclusion"}; + Configurable minTPCNsigmaPr{"minTPCNsigmaPr", -2.5, "min. TPC n sigma for proton exclusion"}; + Configurable requireTOF{"requireTOF", true, "require TOF hit"}; } tighttrackcut; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; @@ -467,9 +475,19 @@ struct skimmerPrimaryElectronQC { template bool isElectronTight(TTrack const& track) { - bool is_El_TPC = tighttrackcut.minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < tighttrackcut.maxTPCNsigmaEl; - bool is_El_TOF = tighttrackcut.minTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < tighttrackcut.maxTOFNsigmaEl; - return is_El_TPC && is_El_TOF; + if (tighttrackcut.requireTOF) { + bool is_El_TPC = tighttrackcut.minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < tighttrackcut.maxTPCNsigmaEl; + bool is_El_TOF = tighttrackcut.minTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < tighttrackcut.maxTOFNsigmaEl; + return is_El_TPC && is_El_TOF; + } else { // TPC hadron band rejection OR TOFreq + bool is_el_included_TPC = tighttrackcut.minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < tighttrackcut.maxTPCNsigmaEl; + bool is_el_included_TOF = track.hasTOF() ? tighttrackcut.minTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < tighttrackcut.maxTOFNsigmaEl : true; + bool is_pi_excluded_TPC = !(tighttrackcut.minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < tighttrackcut.maxTPCNsigmaPi); + bool is_ka_excluded_TPC = !(tighttrackcut.minTPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < tighttrackcut.maxTPCNsigmaKa); + bool is_pr_excluded_TPC = !(tighttrackcut.minTPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < tighttrackcut.maxTPCNsigmaPr); + bool is_el_included_TOFreq = tighttrackcut.minTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < tighttrackcut.maxTOFNsigmaEl; + return (is_el_included_TPC && is_el_included_TOF && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC) || (is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOFreq); + } } template From 713795a0a65d752cbcb92392da1cb6cab1388395 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 7 May 2026 23:28:33 +0200 Subject: [PATCH 088/449] [PWGEM/Dilepton] fix after #16155 (#16156) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 592a332cff4..f151a305122 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1184,7 +1184,7 @@ struct taggingHFE { bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413 || mcMother_of_kaon.pdgCode() == -423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; @@ -1250,7 +1250,7 @@ struct taggingHFE { bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413 || mcMother_of_kaon.pdgCode() == -423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == -323 || mcMother_of_kaon.pdgCode() == -313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == -413) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; @@ -1610,7 +1610,7 @@ struct taggingHFE { bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413 || mcMother_of_kaon.pdgCode() == 423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; @@ -1677,7 +1677,7 @@ struct taggingHFE { bool foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mckaon) > 0; if (mckaon.has_mothers() && !foundCommonMother) { auto mcMother_of_kaon = mckaon.template mothers_first_as(); - if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413 || mcMother_of_kaon.pdgCode() == 423) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e + if (mcMother_of_kaon.pdgCode() == 323 || mcMother_of_kaon.pdgCode() == 313 || mcMother_of_kaon.pdgCode() == 333 || mcMother_of_kaon.pdgCode() == 413) { // accept short-lived resonances such as phi->KK, K*(892)->Kpi for D+ -> anti-K*0(892) e+ nu_e -> (K- pi+) e+ nu_e and Ds+ -> phi e+ nu_e int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_kaon); if (commonMotherId > 0) { foundCommonMother = true; From fedc35f6028ef9c191a7b5b3b5d1995cd3b02f30 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Fri, 8 May 2026 12:09:15 +0530 Subject: [PATCH 089/449] [PWGLF] Added particles K0s, K*+- and Xi1530 for simulations (#16153) --- PWGLF/Tasks/QC/mcParticlePrediction.cxx | 2 +- PWGLF/Utils/mcParticle.h | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/QC/mcParticlePrediction.cxx b/PWGLF/Tasks/QC/mcParticlePrediction.cxx index 0da77c92ee9..2f506ba14e5 100644 --- a/PWGLF/Tasks/QC/mcParticlePrediction.cxx +++ b/PWGLF/Tasks/QC/mcParticlePrediction.cxx @@ -57,7 +57,7 @@ using namespace o2::pwglf; // Particles static const std::vector parameterNames{"Enable"}; static constexpr int nParameters = 1; -static const int defaultParticles[PIDExtended::NIDsTot][nParameters]{{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; +static const int defaultParticles[PIDExtended::NIDsTot][nParameters]{{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; bool enabledParticlesArray[PIDExtended::NIDsTot]; // Estimators diff --git a/PWGLF/Utils/mcParticle.h b/PWGLF/Utils/mcParticle.h index 4f7690bc7e1..657e696ec9a 100644 --- a/PWGLF/Utils/mcParticle.h +++ b/PWGLF/Utils/mcParticle.h @@ -131,7 +131,10 @@ class PIDExtended static constexpr ID XiCPlus = PIDCounts + 37; static constexpr ID XiC0 = PIDCounts + 38; static constexpr ID Kstar = PIDCounts + 39; - static constexpr ID NIDsTot = PIDCounts + 40; + static constexpr ID KstarPM = PIDCounts + 40; + static constexpr ID Kshort = PIDCounts + 41; + static constexpr ID Xi1530 = PIDCounts + 42; + static constexpr ID NIDsTot = PIDCounts + 43; static constexpr const char* sNames[NIDsTot + 1] = { o2::track::pid_constants::sNames[Electron], // Electron @@ -193,6 +196,9 @@ class PIDExtended "XiCPlus", // XiCPlus "XiC0", // XiC0 "Kstar", // Kstar + "KstarPM", // KstarPM + "Kshort", // Kshort + "Xi1530", // Xi1530 nullptr}; static std::vector arrayNames() @@ -329,6 +335,12 @@ class PIDExtended return XiC0; case o2::constants::physics::Pdg::kK0Star892: return Kstar; + case 323: + return KstarPM; + case 310: + return Kshort; + case 3324: + return Xi1530; default: LOG(debug) << "Cannot identify particle with PDG code " << particle.pdgCode(); break; From e86c87e082a08667320d041ee4f3d39d2a5a05ec Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 8 May 2026 10:44:30 +0200 Subject: [PATCH 090/449] [Infrastructure] Add staging build option to clean-test workflow (#16160) --- .github/workflows/clean-test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/clean-test.yml b/.github/workflows/clean-test.yml index c6c9bc12067..7ec1b0355a6 100644 --- a/.github/workflows/clean-test.yml +++ b/.github/workflows/clean-test.yml @@ -34,6 +34,11 @@ name: Clean PR checks type: boolean default: true + 'check_build/O2Physics/staging': + description: build/O2Physics/staging + type: boolean + default: true + permissions: {} jobs: From 91b4b095ae1b0c9ea064060aa007b9610a560196 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Fri, 8 May 2026 12:01:32 +0200 Subject: [PATCH 091/449] [PWGHF] Fix EsE resolution computation (#16159) Co-authored-by: Marcello Di Costanzo --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 6e228d572dc..5279d032a1b 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -221,7 +221,7 @@ struct HfTaskFlowCharmHadrons { if (storeResoOccu && occEstimator == 0) { LOGP(fatal, "Occupancy estimation must be enabled to store resolution THnSparse! Please check your configuration!"); } - if (storeRedQVec && !doprocessD0EsEMl && !doprocessD0SPEsEMl) { + if (storeRedQVec && !doprocessD0EsEMl && !doprocessD0SPEsEMl && !doprocessResolutionSPEsE) { LOGP(fatal, "EsE q-vectors require dedicated process functions. Please check your configuration!"); } if (storeSPQVec && doprocessD0EsEMl) { From 0d67e591b987e056c7fc70dd4463081afbcd69a7 Mon Sep 17 00:00:00 2001 From: HANSEO PARK <53218370+hanseopark@users.noreply.github.com> Date: Fri, 8 May 2026 19:54:27 +0900 Subject: [PATCH 092/449] [PWGJE] fix mistake name of histogram (#16162) --- PWGJE/TableProducer/secondaryVertexReconstruction.cxx | 2 +- PWGJE/Tasks/bjetCentMult.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index c1ee4dd3b73..d722cb4d743 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -283,7 +283,7 @@ struct SecondaryVertexReconstruction { zMomenta, energySV, massSV, chi2PCA, dispersion, errorDecayLength, errorDecayLengthXY); svIndices.push_back(sv2prongTableData.lastIndex()); - } else if ((doprocessDataNProngs || doprocessDataNProngsExternalMagneticField) && numProngs == TwoProngCount) { + } else if ((doprocessDataNProngs || doprocessDataNProngsExternalMagneticField)) { svnprongTableData(analysisJet.globalIndex(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], diff --git a/PWGJE/Tasks/bjetCentMult.cxx b/PWGJE/Tasks/bjetCentMult.cxx index fa0beb6081d..545fd434db0 100644 --- a/PWGJE/Tasks/bjetCentMult.cxx +++ b/PWGJE/Tasks/bjetCentMult.cxx @@ -144,7 +144,7 @@ struct BjetCentMultTask { registry.add("h2_centrality_percentile_multiplicity", "mcd collision centrality; centrality; counts", {HistType::kTH2F, {{axisRebinnedCentrality}, {axisPercentileMultiplicity}}}); } if (doprocessSVData) { - registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h2_jet_pt_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); registry.add("h2_jet_eta_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); registry.add("h2_jet_phi_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); @@ -163,7 +163,7 @@ struct BjetCentMultTask { } } if (doprocessRhoAreaSubSVData) { - registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); registry.add("h2_jet_pt_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); registry.add("h2_jet_eta_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); registry.add("h2_jet_phi_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); From bb6e3990c58f89fa4da0fe7c0de275baa3cf2a48 Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Fri, 8 May 2026 13:14:08 +0200 Subject: [PATCH 093/449] [PWGLF] Fix in hStrangeCorrelation.cxx (#16163) Co-authored-by: Lucia Anna Tarasovicova --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 55606515998..c5d120deb0e 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -2186,8 +2186,8 @@ struct HStrangeCorrelation { continue; float efficiency = 1.0f; float purity = 1.0f; - histos.fill(HIST("hDCAzAssocHadron"), assoc.dcaZ(), assoc.pt()); - histos.fill(HIST("hDCAxyAssocHadron"), assoc.dcaXY(), assoc.pt()); + histos.fill(HIST("hDCAzAssociatedHadron"), assoc.dcaZ(), assoc.pt()); + histos.fill(HIST("hDCAxyAssociatedHadron"), assoc.dcaXY(), assoc.pt()); if (efficiencyFlags.applyEfficiencyCorrection) { efficiency = hEfficiencyHadron->Interpolate(assoc.pt(), assoc.eta()); if (efficiencyFlags.applyPurityHadron) From 4d03ca69d9ab7d36b3a563cfe266a195512551c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 8 May 2026 14:56:43 +0200 Subject: [PATCH 094/449] [Infrastructure,Scripts] Add FDD in the header patterns (#16150) --- .clang-format | 2 +- Scripts/format_includes.awk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index 674e1494ecd..5fd38a073da 100644 --- a/.clang-format +++ b/.clang-format @@ -51,7 +51,7 @@ IncludeCategories: Priority: 3 CaseSensitive: true # O2 - - Regex: ^(<|")(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|Field|Framework|FT0|FV0|GlobalTracking|GPU|ITS|MathUtils|MFT|MCH|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*/.*\.h + - Regex: ^(<|")(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|FDD|Field|Framework|FT0|FV0|GlobalTracking|GPU|ITS|MathUtils|MCH|MFT|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*/.*\.h Priority: 4 CaseSensitive: true # ROOT diff --git a/Scripts/format_includes.awk b/Scripts/format_includes.awk index ac22332acc5..d024e91e79c 100644 --- a/Scripts/format_includes.awk +++ b/Scripts/format_includes.awk @@ -7,7 +7,7 @@ if ($1 ~ /^#include/) { h = substr($2, 2, length($2) - 2) if ( h ~ /^(PWG[A-Z]{2}|Common|ALICE3|DPG|EventFiltering|Tools|Tutorials)\/.*\.h/ ) { $2 = "\""h"\"" } # O2Physics - else if ( h ~ /^(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|Field|Framework|FT0|FV0|GlobalTracking|GPU|ITS|MathUtils|MFT|MCH|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*\/.*\.h/ ) { $2 = "<"h">" } # O2 + else if ( h ~ /^(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|FDD|Field|Framework|FT0|FV0|GlobalTracking|GPU|ITS|MathUtils|MCH|MFT|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*\/.*\.h/ ) { $2 = "<"h">" } # O2 else if ( h ~ /^(T[A-Z]|Math\/|Roo[A-Z])[[:alnum:]\/]+\.h/ ) { $2 = "<"h">" } # ROOT else if ( h ~ /^KF[A-Z][[:alnum:]]+\.h/ ) { $2 = "<"h">" } # KFParticle else if ( h ~ /^(fastjet\/|onnxruntime)/ ) { $2 = "<"h">" } # FastJet, ONNX From 024668db40422c10004b991dadbd07db32ced79a Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 8 May 2026 15:44:31 +0200 Subject: [PATCH 095/449] [PWGEM/Dilepton] use proper timestamp (#16165) --- .../TableProducer/skimmerPrimaryElectron.cxx | 55 ++++++++++--------- .../skimmerPrimaryElectronQC.cxx | 53 +++++++++--------- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index e9fe1653412..c8af8922bb6 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -168,7 +168,7 @@ struct skimmerPrimaryElectron { Configurable> cutsMl{"cutsMl", std::vector{0.95, 0.95, 0.7, 0.7, 0.8, 0.8, 0.7, 0.7}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"tpcInnerParam", "tpcNClsFound", "tpcChi2NCl", "tpcNSigmaEl", "tofNSigmaEl", "meanClusterSizeITSobCos"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + // Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -237,32 +237,6 @@ struct skimmerPrimaryElectron { fRegistry.add("Track/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Track/hNe", "electron counts;N_{e} per collision", kTH1F, {{51, -0.5, 50.5}}, false); } - - if (usePIDML) { - static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - const std::vector labelsClasses = {"Background", "Signal"}; - const uint32_t nBinsMl = binsMl.value.size() - 1; - const std::vector labelsBins(nBinsMl, "bin"); - double cutsMlArr[nBinsMl][nClassesMl]; - for (uint32_t i = 0; i < nBinsMl; i++) { - cutsMlArr[i][0] = 0.0; - cutsMlArr[i][1] = cutsMl.value[i]; - } - o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); - if (loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, timestampCCDB.value); - } else { - mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); - } - mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); - mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); - mlResponseSingleTrack.init(enableOptimizations.value); - mlResponseSingleTrack.useReassociatedTOF(useTOFNSigmaDeltaBC.value); - } // end of PID ML } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -319,6 +293,33 @@ struct skimmerPrimaryElectron { d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } + + if (usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; + const uint32_t nBinsMl = binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = cutsMl.value[i]; + } + o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, bc.timestamp()); + } else { + mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); + } + mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); + mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); + mlResponseSingleTrack.init(enableOptimizations.value); + mlResponseSingleTrack.useReassociatedTOF(useTOFNSigmaDeltaBC.value); + } // end of PID ML + mRunNumber = bc.runNumber(); } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx index cf4367dcb24..d17a395027e 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx @@ -154,7 +154,7 @@ struct skimmerPrimaryElectronQC { Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + // Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -220,31 +220,6 @@ struct skimmerPrimaryElectronQC { fRegistry.add("Track/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Pair/hMvsPhiV", "m_{ee} vs. #varphi_{V} ULS;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0.f, M_PI}, {100, 0, 0.1}}); } - - if (usePIDML) { - static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - const std::vector labelsClasses = {"Background", "Signal"}; - const uint32_t nBinsMl = binsMl.value.size() - 1; - const std::vector labelsBins(nBinsMl, "bin"); - double cutsMlArr[nBinsMl][nClassesMl]; - for (uint32_t i = 0; i < nBinsMl; i++) { - cutsMlArr[i][0] = 0.0; - cutsMlArr[i][1] = cutsMl.value[i]; - } - o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); - if (loadModelsFromCCDB) { - ccdbApi.init(ccdburl); - mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, timestampCCDB.value); - } else { - mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); - } - mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); - mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); - mlResponseSingleTrack.init(enableOptimizations.value); - } // end of PID ML } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -301,6 +276,32 @@ struct skimmerPrimaryElectronQC { d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } + + if (usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; + const uint32_t nBinsMl = binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = cutsMl.value[i]; + } + o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, bc.timestamp()); + } else { + mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); + } + mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); + mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); + mlResponseSingleTrack.init(enableOptimizations.value); + } // end of PID ML + mRunNumber = bc.runNumber(); } From 9bda3cc9b04eb2522e3fe4ba3b9abb96be60220c Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Fri, 8 May 2026 15:50:19 +0200 Subject: [PATCH 096/449] [PWGHF] Separate UPC Lc analysis into a dedicated task file (#15786) --- PWGHF/D2H/Tasks/CMakeLists.txt | 5 + PWGHF/D2H/Tasks/taskLc.cxx | 212 +------------------- PWGHF/D2H/Tasks/taskUpcLc.cxx | 351 +++++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+), 202 deletions(-) create mode 100644 PWGHF/D2H/Tasks/taskUpcLc.cxx diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 1ffbbf3cd33..96296bf2c6b 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -114,6 +114,11 @@ o2physics_add_dpl_workflow(task-lc PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-upc-lc + SOURCES taskUpcLc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-lc-to-k0s-p SOURCES taskLcToK0sP.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index e7144cf505d..805ae3f05ed 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -17,7 +17,6 @@ /// \author Vít Kučera , CERN /// \author Annalena Kalteyer , GSI Darmstadt /// \author Biao Zhang , Heidelberg University -/// \author Ran Tu , Fudan University /// \author Oleksii Lubynets , Heidelberg University, GSI Darmstadt #include "PWGHF/Core/CentralityEstimation.h" @@ -29,9 +28,6 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Utils/utilsUpcHf.h" -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UPCHelpers.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" @@ -69,7 +65,6 @@ using namespace o2::framework::expressions; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::hf_evsel; -using namespace o2::analysis::hf_upc; /// Λc± → p± K∓ π± analysis task struct HfTaskLc { @@ -79,7 +74,6 @@ struct HfTaskLc { Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; // ThnSparse for ML outputScores and Vars Configurable fillTHn{"fillTHn", false, "fill THn"}; - Configurable fillUPCTHnLite{"fillUPCTHnLite", false, "fill THn"}; Configurable storeOccupancy{"storeOccupancy", true, "Flag to store occupancy information"}; Configurable occEstimator{"occEstimator", 2, "Occupancy estimation (None: 0, ITS: 1, FT0C: 2)"}; Configurable storeProperLifetime{"storeProperLifetime", false, "Flag to store proper lifetime"}; @@ -88,8 +82,7 @@ struct HfTaskLc { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; - HfEventSelection hfEvSel; // event selection and monitoring - HfUpcGapThresholds upcThresholds; // UPC gap determination thresholds + HfEventSelection hfEvSel; // event selection and monitoring SliceCache cache; Service ccdb{}; @@ -127,13 +120,7 @@ struct HfTaskLc { ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"}; ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"}; ConfigurableAxis thnConfigAxisProperLifetime{"thnConfigAxisProperLifetime", {200, 0, 2}, "Proper lifetime, ps"}; - ConfigurableAxis thnConfigAxisGapType{"thnConfigAxisGapType", {7, -1.5, 5.5}, "axis for UPC gap type (see TrueGap enum in o2::aod::sgselector)"}; - ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {1001, -1.5, 999.5}, "axis for FV0-A amplitude (a.u.)"}; - ConfigurableAxis thnConfigAxisFT0{"thnConfigAxisFT0", {1001, -1.5, 999.5}, "axis for FT0 amplitude (a.u.)"}; - ConfigurableAxis thnConfigAxisZN{"thnConfigAxisZN", {510, -1.5, 49.5}, "axis for ZN energy (a.u.)"}; - ConfigurableAxis thnConfigAxisZNTime{"thnConfigAxisZNTime", {200, -10, 10}, "axis for ZN energy (a.u.)"}; HistogramRegistry registry{"registry", {}}; - HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Factors for conversion between units constexpr static float CtToProperLifetimePs = 1.f / o2::constants::physics::LightSpeedCm2PS; @@ -157,13 +144,12 @@ struct HfTaskLc { void init(InitContext&) { - const std::array doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessDataWithMlWithUpc, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M, doprocessDataStdWithUpc}; + const std::array doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M}; if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { LOGP(fatal, "no or more than one process function enabled! Please check your configuration!"); } - const bool isData = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M || doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc; - const bool isUpc = doprocessDataWithMlWithUpc || doprocessDataStdWithUpc; + const bool isData = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M || doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M; auto addHistogramsRec = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { if (isData) { @@ -266,14 +252,6 @@ struct HfTaskLc { /// decay length error addHistogramsRec("hDecLenErrVsPt", "decay length error (cm)", "#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 1.}, {vbins}}}); - if (isUpc) { - qaRegistry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{500, 0., 500}, {500, 0., 500}}}); - qaRegistry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{100, 0., 10}, {100, 0., 10}}}); - qaRegistry.add("Data/zdc/timeZNA_vs_timeZNC", "ZNA vs ZNC time;ZNA Time;ZNC time", {HistType::kTH2F, {{200, -10., 10}, {200, -10., 10}}}); - qaRegistry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); - qaRegistry.add("Data/hUpcMulti", "Multiplicity of UPC events;Multiplicity;Counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - qaRegistry.add("Data/hUpcVtz", "Vertex Z position of UPC events;Vz (cm);Counts", {HistType::kTH1F, {{200, -10., 10.}}}); - } if (fillTHn) { const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"}; @@ -293,39 +271,26 @@ struct HfTaskLc { const AxisSpec thnAxisTracklets{thnConfigAxisNumPvContr, "Number of PV contributors"}; const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"}; const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, "T_{proper} (ps)"}; - const AxisSpec thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"}; - const AxisSpec thnAxisFT0A{thnConfigAxisFT0, "FT0-A amplitude"}; - const AxisSpec thnAxisFT0C{thnConfigAxisFT0, "FT0-C amplitude"}; - const AxisSpec thnAxisZNA{thnConfigAxisZN, "ZNA energy"}; - const AxisSpec thnAxisZNC{thnConfigAxisZN, "ZNC energy"}; - const AxisSpec thnAxisZNATime{thnConfigAxisZNTime, "ZNA time"}; - const AxisSpec thnAxisZNCTime{thnConfigAxisZNTime, "ZNC time"}; - - bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc; + + bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M; bool const isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M; - bool const isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M || doprocessDataStdWithUpc; + bool const isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M; bool const isMcStd = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M; - std::vector axesStd, axesWithBdt, axesGen, axesUpc, axesUpcWithBdt; + std::vector axesStd, axesWithBdt, axesGen; - if (isDataStd && !isUpc) { + if (isDataStd) { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets}; } - if (isDataStd && isUpc) { - axesUpc = {thnAxisMass, thnAxisPt, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisFV0A, thnAxisFT0A, thnAxisFT0C, thnAxisZNA, thnAxisZNC, thnAxisZNATime, thnAxisZNCTime}; - } if (isMcStd) { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } if (isMcStd || isMcWithMl) { axesGen = {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } - if (isDataWithMl && !isUpc) { + if (isDataWithMl) { axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets}; } - if (isDataWithMl && isUpc) { - axesUpcWithBdt = {thnAxisMass, thnAxisPt, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisFV0A, thnAxisFT0A, thnAxisFT0C, thnAxisZNA, thnAxisZNC, thnAxisZNATime, thnAxisZNCTime}; - } if (isMcWithMl) { axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; } @@ -344,13 +309,7 @@ struct HfTaskLc { } } } - if (isUpc) { - if (isDataStd) { - registry.add("hnLcUpcVars", "THn for Lambdac candidates for Data in UPC", HistType::kTHnSparseF, axesUpc); - } else if (isDataWithMl) { - registry.add("hnLcUpcVarsWithBdt", "THn for Lambdac candidates with BDT scores for data in UPC", HistType::kTHnSparseF, axesUpcWithBdt); - } - } else if (isDataWithMl) { + if (isDataWithMl) { registry.add("hnLcVarsWithBdt", "THn for Lambdac candidates with BDT scores for data with ML", HistType::kTHnSparseF, axesWithBdt); } else if (isMcWithMl) { registry.add("hnLcVarsWithBdt", "THn for Lambdac candidates with BDT scores for mc with ML", HistType::kTHnSparseF, axesWithBdt); @@ -363,10 +322,6 @@ struct HfTaskLc { } } - if (isUpc) { - hfEvSel.addHistograms(qaRegistry); // collision monitoring - } - ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -732,127 +687,6 @@ struct HfTaskLc { } } - template - void runAnalysisPerCollisionDataWithUpc(CollType const& collisions, - CandType const& candidates, - BCsType const& bcs, - aod::FT0s const& ft0s, - aod::FV0As const& fv0as, - aod::FDDs const& fdds - - ) - { - for (const auto& collision : collisions) { - float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, qaRegistry, bcs); - if (rejectionMask != 0) { - /// at least one event selection not satisfied --> reject the candidate - continue; - } - const auto thisCollId = collision.globalIndex(); - const auto& groupedLcCandidates = candidates.sliceBy(candLcPerCollision, thisCollId); - const auto numPvContributors = collision.numContrib(); - const auto& bc = collision.template bc_as(); - - // Determine gap type using SGSelector with BC range checking - const auto gapResult = hf_upc::determineGapType(collision, bcs, upcThresholds); - const int gap = gapResult.value; - - // Use the BC with FIT activity if available from SGSelector - auto bcForUPC = bc; - if (gapResult.bc) { - bcForUPC = *(gapResult.bc); - } - - // Get FIT information from the UPC BC - upchelpers::FITInfo fitInfo{}; - udhelpers::getFITinfo(fitInfo, bcForUPC, bcs, ft0s, fv0as, fdds); - - // Get ZDC energies if available (extract once and reuse) - const bool hasZdc = bcForUPC.has_zdc(); - float zdcEnergyZNA = -1.f; - float zdcEnergyZNC = -1.f; - float zdcTimeZNA = -1.f; - float zdcTimeZNC = -1.f; - - if (hasZdc) { - const auto zdc = bcForUPC.zdc(); - zdcEnergyZNA = zdc.energyCommonZNA(); - zdcEnergyZNC = zdc.energyCommonZNC(); - zdcTimeZNA = zdc.timeZNA(); - zdcTimeZNC = zdc.timeZNC(); - qaRegistry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); - qaRegistry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); - qaRegistry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); - qaRegistry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast(gap)); - } - for (const auto& candidate : groupedLcCandidates) { - if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { - continue; - } - if (yCandRecoMax >= 0. && std::abs(HfHelper::yLc(candidate)) > yCandRecoMax) { - continue; - } - const auto pt = candidate.pt(); - const auto ptProng0 = candidate.ptProng0(); - const auto ptProng1 = candidate.ptProng1(); - const auto ptProng2 = candidate.ptProng2(); - const auto decayLength = candidate.decayLength(); - const auto chi2PCA = candidate.chi2PCA(); - const auto cpa = candidate.cpa(); - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - qaRegistry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); - qaRegistry.fill(HIST("Data/hUpcVtz"), collision.posZ()); - } - - if (fillTHn) { - double outputBkg(-1), outputPrompt(-1), outputFD(-1); - - auto fillTHnData = [&](bool isPKPi) { - const auto massLc = isPKPi ? HfHelper::invMassLcToPKPi(candidate) : HfHelper::invMassLcToPiKP(candidate); - - if constexpr (FillMl) { - const auto& mlProb = isPKPi ? candidate.mlProbLcToPKPi() : candidate.mlProbLcToPiKP(); - if (mlProb.size() == NumberOfMlClasses) { - outputBkg = mlProb[MlClassBackground]; /// bkg score - outputPrompt = mlProb[MlClassPrompt]; /// prompt score - outputFD = mlProb[MlClassNonPrompt]; /// non-prompt score - } - /// Fill the ML outputScores and variables of candidate - if (fillUPCTHnLite) { - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - std::vector valuesToFill{massLc, pt, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; - registry.get(HIST("hnLcUpcVarsWithBdt"))->Fill(valuesToFill.data()); - } - } else { - std::vector valuesToFill{massLc, pt, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; - registry.get(HIST("hnLcUpcVarsWithBdt"))->Fill(valuesToFill.data()); - } - - } else { - if (fillUPCTHnLite) { - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - std::vector valuesToFill{massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; - registry.get(HIST("hnLcUpcVars"))->Fill(valuesToFill.data()); - } - } else { - std::vector valuesToFill{massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; - registry.get(HIST("hnLcUpcVars"))->Fill(valuesToFill.data()); - } - } - }; - - if (candidate.isSelLcToPKPi() >= selectionFlagLc) { - fillTHnData(true); - } - if (candidate.isSelLcToPiKP() >= selectionFlagLc) { - fillTHnData(false); - } - } - } - } - } - /// Run the analysis on MC data /// \tparam FillMl switch to fill ML histograms template @@ -916,32 +750,6 @@ struct HfTaskLc { } PROCESS_SWITCH(HfTaskLc, processDataWithMlWithFT0M, "Process real data with the ML method and with FT0M centrality", false); - void processDataWithMlWithUpc(soa::Join const& collisions, - aod::BcFullInfos const& bcs, - LcCandidatesMl const& selectedLcCandidatesMl, - aod::Tracks const&, - aod::FT0s const& ft0s, - aod::FV0As const& fv0as, - aod::FDDs const& fdds, - aod::Zdcs const& /*zdcs*/) - { - runAnalysisPerCollisionDataWithUpc(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds); - } - PROCESS_SWITCH(HfTaskLc, processDataWithMlWithUpc, "Process real data with the ML method with UPC", false); - - void processDataStdWithUpc(soa::Join const& collisions, - aod::BcFullInfos const& bcs, - LcCandidatesMl const& selectedLcCandidatesMl, - aod::Tracks const&, - aod::FT0s const& ft0s, - aod::FV0As const& fv0as, - aod::FDDs const& fdds, - aod::Zdcs const& /*zdcs*/) - { - runAnalysisPerCollisionDataWithUpc(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds); - } - PROCESS_SWITCH(HfTaskLc, processDataStdWithUpc, "Process real data with the standard method with UPC", false); - void processMcStd(CollisionsMc const& collisions, LcCandidatesMc const& selectedLcCandidatesMc, McParticles3ProngMatched const& mcParticles, diff --git a/PWGHF/D2H/Tasks/taskUpcLc.cxx b/PWGHF/D2H/Tasks/taskUpcLc.cxx new file mode 100644 index 00000000000..fcf2200a1e3 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskUpcLc.cxx @@ -0,0 +1,351 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file taskUpcLc.cxx +/// \brief Λc± → p± K∓ π± analysis task +/// \note Extended from taskLc +/// +/// \author Biao Zhang , Heidelberg University +/// \author Ran Tu , Fudan University + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsUpcHf.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCHelpers.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include // std::vector + +using namespace o2; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; +using namespace o2::hf_evsel; +using namespace o2::analysis::hf_upc; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(BkgScore, bkgScore, float); +DECLARE_SOA_COLUMN(PromptScore, promptScore, float); +DECLARE_SOA_COLUMN(FdScore, fdScore, float); +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); +DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); +DECLARE_SOA_COLUMN(Cpa, cpa, float); +DECLARE_SOA_COLUMN(PvContributors, pvContributors, float); +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +DECLARE_SOA_COLUMN(Vtz, vtz, float); +DECLARE_SOA_COLUMN(AmpFV0A, ampFV0A, float); +DECLARE_SOA_COLUMN(AmpFT0A, ampFT0A, float); +DECLARE_SOA_COLUMN(AmpFT0C, ampFT0C, float); +DECLARE_SOA_COLUMN(ZdcTimeZNA, zdcTimeZNA, float); +DECLARE_SOA_COLUMN(ZdcTimeZNC, zdcTimeZNC, float); +} // namespace full +DECLARE_SOA_TABLE(HfUpcQa, "AOD", "HFUPCQA", + full::PvContributors, + full::Multiplicity, + full::Vtz, + full::AmpFV0A, + full::AmpFT0A, + full::AmpFT0C, + full::ZdcTimeZNA, + full::ZdcTimeZNC); + +DECLARE_SOA_TABLE(HfUpcLcBdtInfos, "AOD", "HFUPCLCBDTINFOS", + full::M, + full::Pt, + full::BkgScore, + full::PromptScore, + full::FdScore, + full::AmpFV0A, + full::AmpFT0A, + full::AmpFT0C, + full::ZdcTimeZNA, + full::ZdcTimeZNC); + +DECLARE_SOA_TABLE(HfUpcLcInfos, "AOD", "HFUPCLCINFOS", + full::M, + full::Pt, + full::PtProng0, + full::PtProng1, + full::PtProng2, + full::Chi2PCA, + full::DecayLength, + full::Cpa, + full::AmpFV0A, + full::AmpFT0A, + full::AmpFT0C, + full::ZdcTimeZNA, + full::ZdcTimeZNC); +} // namespace o2::aod + +/// Λc± → p± K∓ π± analysis task +struct HfTaskUpcLc { + Produces rowCandUpcBdt; + Produces rowCandUpc; + Produces rowUpcQa; + + Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + Configurable fillTreeOnlySingleGap{"fillTreeOnlySingleGap", false, "Only fill the tree for candidates that pass the single-gap UPC events"}; + Configurable fillTreeUpcQa{"fillTreeUpcQa", false, "Fill Tree for UPC QA"}; + Configurable verticesWithUpc{"verticesWithUpc", false, "Consider vertices with UPC settings"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + HfEventSelection hfEvSel; // event selection and monitoring + HfUpcGapThresholds upcThresholds; // UPC gap determination thresholds + SliceCache cache; + Service ccdb{}; + + using Collisions = soa::Join; + + using LcCandidates = soa::Filtered>; + using LcCandidatesMl = soa::Filtered>; + + Filter filterSelectCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc; + Preslice candLcPerCollision = aod::hf_cand::collisionId; + PresliceUnsorted colPerMcCollision = aod::mcparticle::mcCollisionId; + + HistogramRegistry registry{"registry", {}}; + + enum MlClasses : int { + MlClassBackground = 0, + MlClassPrompt, + MlClassNonPrompt, + NumberOfMlClasses + }; + + void init(InitContext&) + { + const std::array doprocess{doprocessDataWithMlWithUpc, doprocessDataStdWithUpc}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "no or more than one process function enabled! Please check your configuration!"); + } + + auto vbins = (std::vector)binsPt; + registry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{500, 0., 500}, {500, 0., 500}}}); + registry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{100, 0., 10}, {100, 0., 10}}}); + registry.add("Data/zdc/timeZNA_vs_timeZNC", "ZNA vs ZNC time;ZNA Time;ZNC time", {HistType::kTH2F, {{200, -10., 10}, {200, -10., 10}}}); + registry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); + registry.add("Data/hUpcMulti", "Multiplicity of UPC events;Multiplicity;Counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("Data/hUpcVtz", "Vertex Z position of UPC events;Vz (cm);Counts", {HistType::kTH1F, {{200, -10., 10.}}}); + + hfEvSel.addHistograms(registry); + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + /// Evaluate centrality/multiplicity percentile (centrality estimator is automatically selected based on the used table) + /// \param collision is collision + /// \return centrality/multiplicity percentile of the collision + template + float evaluateCentralityColl(const Coll& collision) + { + return o2::hf_centrality::getCentralityColl(collision); + } + + template + void runAnalysisPerCollisionDataWithUpc(CollType const& collisions, + CandType const& candidates, + BCsType const& bcs, + aod::FT0s const& ft0s, + aod::FV0As const& fv0as, + aod::FDDs const& fdds + + ) + { + for (const auto& collision : collisions) { + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + if (rejectionMask != 0) { + /// at least one event selection not satisfied --> reject the candidate + continue; + } + const auto thisCollId = collision.globalIndex(); + const auto& groupedLcCandidates = candidates.sliceBy(candLcPerCollision, thisCollId); + const auto numPvContributors = collision.numContrib(); + const auto& bc = collision.template bc_as(); + + // Determine gap type using SGSelector with BC range checking + const auto gapResult = hf_upc::determineGapType(collision, bcs, upcThresholds); + const int gap = gapResult.value; + const int upcFlag = (collision.flags() & dataformats::Vertex>::Flags::UPCMode) ? 1 : 0; + + // Use the BC with FIT activity if available from SGSelector + auto bcForUPC = bc; + if (gapResult.bc) { + bcForUPC = *(gapResult.bc); + } + + // Get FIT information from the UPC BC + upchelpers::FITInfo fitInfo{}; + udhelpers::getFITinfo(fitInfo, bcForUPC, bcs, ft0s, fv0as, fdds); + + // Get ZDC energies if available (extract once and reuse) + const bool hasZdc = bcForUPC.has_zdc(); + float zdcEnergyZNA = -1.f; + float zdcEnergyZNC = -1.f; + float zdcTimeZNA = -1.f; + float zdcTimeZNC = -1.f; + if (verticesWithUpc && !upcFlag) { + continue; + } + if (hasZdc) { + const auto zdc = bcForUPC.zdc(); + zdcEnergyZNA = zdc.energyCommonZNA(); + zdcEnergyZNC = zdc.energyCommonZNC(); + zdcTimeZNA = zdc.timeZNA(); + zdcTimeZNC = zdc.timeZNC(); + registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); + registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); + registry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); + registry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast(gap)); + } + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + registry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); + registry.fill(HIST("Data/hUpcVtz"), collision.posZ()); + } + if (fillTreeUpcQa) { + rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } + + for (const auto& candidate : groupedLcCandidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(HfHelper::yLc(candidate)) > yCandRecoMax) { + continue; + } + const auto pt = candidate.pt(); + const auto ptProng0 = candidate.ptProng0(); + const auto ptProng1 = candidate.ptProng1(); + const auto ptProng2 = candidate.ptProng2(); + const auto decayLength = candidate.decayLength(); + const auto chi2PCA = candidate.chi2PCA(); + const auto cpa = candidate.cpa(); + + double outputBkg(-1), outputPrompt(-1), outputFD(-1); + + auto fillTHnData = [&](bool isPKPi) { + const auto massLc = isPKPi ? HfHelper::invMassLcToPKPi(candidate) : HfHelper::invMassLcToPiKP(candidate); + + if constexpr (FillMl) { + const auto& mlProb = isPKPi ? candidate.mlProbLcToPKPi() : candidate.mlProbLcToPiKP(); + if (mlProb.size() == NumberOfMlClasses) { + outputBkg = mlProb[MlClassBackground]; /// bkg score + outputPrompt = mlProb[MlClassPrompt]; /// prompt score + outputFD = mlProb[MlClassNonPrompt]; /// non-prompt score + } + /// Fill the ML outputScores and variables of candidate + if (fillTreeOnlySingleGap) { + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + rowCandUpcBdt(massLc, pt, outputBkg, outputPrompt, outputFD, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } + } else { + rowCandUpcBdt(massLc, pt, outputBkg, outputPrompt, outputFD, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } + + } else { + if (fillTreeOnlySingleGap) { + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } + } else { + rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } + } + }; + + if (candidate.isSelLcToPKPi() >= selectionFlagLc) { + fillTHnData(true); + } + if (candidate.isSelLcToPiKP() >= selectionFlagLc) { + fillTHnData(false); + } + } + } + } + + void processDataWithMlWithUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + LcCandidatesMl const& selectedLcCandidatesMl, + aod::Tracks const&, + aod::FT0s const& ft0s, + aod::FV0As const& fv0as, + aod::FDDs const& fdds, + aod::Zdcs const& /*zdcs*/) + { + runAnalysisPerCollisionDataWithUpc(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds); + } + PROCESS_SWITCH(HfTaskUpcLc, processDataWithMlWithUpc, "Process real data with the ML method with UPC", false); + + void processDataStdWithUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + LcCandidates const& selectedLcCandidates, + aod::Tracks const&, + aod::FT0s const& ft0s, + aod::FV0As const& fv0as, + aod::FDDs const& fdds, + aod::Zdcs const& /*zdcs*/) + { + runAnalysisPerCollisionDataWithUpc(collisions, selectedLcCandidates, bcs, ft0s, fv0as, fdds); + } + PROCESS_SWITCH(HfTaskUpcLc, processDataStdWithUpc, "Process real data with the standard method with UPC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 758e0ca2f8e530e5f16d9a6e4ff6e5103119ce8e Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 8 May 2026 16:22:50 +0200 Subject: [PATCH 097/449] [PWGEM/Dilepton] update taggingHFE for proton (#16167) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 1 + PWGEM/Dilepton/Tasks/taggingHFE.cxx | 40 ++++++++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 3de198ee03b..149333eb33a 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -251,6 +251,7 @@ DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, + pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, emmllhpair::Lxyz, emmllhpair::LxyzSigma, emmllhpair::Lxy, emmllhpair::LxySigma, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index f151a305122..c722d997add 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -166,8 +166,12 @@ struct taggingHFE { Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; - Configurable requirePiKa{"requirePiKa", false, "require hadron to be pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. - Configurable applyTOFif{"applyTOFif", false, "apply TOFif for pion or kaon"}; // proton is not involved in semileptonic decay of HF hadrons often. + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + Configurable requirePiKaPr{"requirePiKaPr", true, "require hadron to be pion or kaon or proton"}; + Configurable applyTOFif{"applyTOFif", false, "apply TOFif for hadron identification"}; } hadronCut; struct : ConfigurableGroup { @@ -457,19 +461,23 @@ struct taggingHFE { } template - bool isKaon_or_isPion(TCollision const& collision, TTrack const& track) + bool isPiKaPr(TCollision const& collision, TTrack const& track) { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; - bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; - bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < hadronCut.cfg_max_TOFNsigmaKa) : true; + float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; bool is_pi_included_TPC = hadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < hadronCut.cfg_max_TPCNsigmaPi; bool is_pi_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < hadronCut.cfg_max_TOFNsigmaPi) : true; + bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; + bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < hadronCut.cfg_max_TOFNsigmaKa) : true; + bool is_pr_included_TPC = hadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < hadronCut.cfg_max_TPCNsigmaPr; + bool is_pr_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < hadronCut.cfg_max_TOFNsigmaPr) : true; if (!hadronCut.applyTOFif) { - is_ka_included_TOF = true; is_pi_included_TOF = true; + is_ka_included_TOF = true; + is_pr_included_TOF = true; } - return (is_ka_included_TPC && is_ka_included_TOF) || (is_pi_included_TPC && is_pi_included_TOF); + return (is_pi_included_TPC && is_pi_included_TOF) || (is_ka_included_TPC && is_ka_included_TOF) || (is_pr_included_TPC && is_pr_included_TOF); } template @@ -624,7 +632,7 @@ struct taggingHFE { return false; } - if (hadronCut.requirePiKa && !isKaon_or_isPion(collision, track)) { + if (hadronCut.requirePiKaPr && !isPiKaPr(collision, track)) { return false; } @@ -865,6 +873,7 @@ struct taggingHFE { std::map, float> mapTOFNsigmaPiReassociated; // map pair(collisionId, trackId) -> tof n sigma pi std::map, float> mapTOFNsigmaKaReassociated; // map pair(collisionId, trackId) -> tof n sigma ka + std::map, float> mapTOFNsigmaPrReassociated; // map pair(collisionId, trackId) -> tof n sigma pr std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta std::unordered_map mapCollisionTime; std::unordered_map mapCollisionTimeError; @@ -890,13 +899,16 @@ struct taggingHFE { auto bcTrack = track.template collision_as().template bc_as(); float tofNSigmaPi = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); float tofNSigmaKa = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + float tofNSigmaPr = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); float beta = track.length() / (track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()) - mapCollisionTime[collision.globalIndex()]) / (TMath::C() * 1e+2 * 1e-12); mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaPi; mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaKa; + mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaPr; mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = beta; } else { mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); } } // end of track loop @@ -910,6 +922,7 @@ struct taggingHFE { } mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); } } // end of track loop @@ -925,6 +938,7 @@ struct taggingHFE { } mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); } // end of track loop } // end of collision loop @@ -937,6 +951,7 @@ struct taggingHFE { } mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); } } // end of track loop @@ -1211,11 +1226,13 @@ struct taggingHFE { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, + kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -1277,11 +1294,13 @@ struct taggingHFE { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, + kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -1637,11 +1656,13 @@ struct taggingHFE { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, + kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -1704,11 +1725,13 @@ struct taggingHFE { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmllhpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, + kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.lxyz, eKpair.lxyzErr, eKpair.lxy, eKpair.lxyErr, @@ -2178,6 +2201,7 @@ struct taggingHFE { mapCollisionTimeError.clear(); mapTOFNsigmaPiReassociated.clear(); mapTOFNsigmaKaReassociated.clear(); + mapTOFNsigmaPrReassociated.clear(); mapTOFBetaReassociated.clear(); } PROCESS_SWITCH(taggingHFE, processMC, "process with TTCA", true); From 45c8b45ccf2eddae5478574f9603ec761ad12b4f Mon Sep 17 00:00:00 2001 From: glegras <71757105+glegras@users.noreply.github.com> Date: Fri, 8 May 2026 16:44:48 +0200 Subject: [PATCH 098/449] [PWGDQ] small fixes for dalitz selection (#16169) --- PWGDQ/Tasks/DalitzSelection.cxx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index da755a538ef..70eb8415d27 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -138,6 +138,7 @@ struct DalitzSelection { void init(o2::framework::InitContext&) { fIsTagAndProbe = false; + VarManager::SetDefaultVarNames(); // Event cuts fEventCut = new AnalysisCompositeCut(true); @@ -158,7 +159,7 @@ struct DalitzSelection { if (addTrackCutsStr != "") { std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); for (const auto& t : addTrackCuts) { - fTrackCuts.push_back(reinterpret_cast(t)); + fTrackCuts.push_back(*dynamic_cast(t)); } } @@ -176,7 +177,7 @@ struct DalitzSelection { if (addTrackCutsProbeStr != "" && (cutNamesProbeStr.CompareTo(cutNamesStr) != 0 || addTrackCutsProbeStr.CompareTo(addTrackCutsStr) != 0)) { std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsProbeStr.Data()); for (const auto& t : addTrackCuts) { - fTrackCutsProbe.push_back(reinterpret_cast(t)); + fTrackCutsProbe.push_back(*dynamic_cast(t)); } fIsTagAndProbe = true; } @@ -194,7 +195,7 @@ struct DalitzSelection { if (addPairCutsStr != "") { std::vector addPairCuts = dqcuts::GetCutsFromJSON(addPairCutsStr.Data()); for (const auto& t : addPairCuts) { - fPairCuts.push_back(reinterpret_cast(t)); + fPairCuts.push_back(*dynamic_cast(t)); } } @@ -212,7 +213,7 @@ struct DalitzSelection { } VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill - VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); fHistMan->SetUseDefaultVariableNames(kTRUE); fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); @@ -229,13 +230,13 @@ struct DalitzSelection { histClasses += Form("TrackBarrelProbe_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); histClasses += Form("Pair_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); if (fConfigOptions.fConfigEnableLikeSign) { - histClasses += Form("Pair_LS_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); + histClasses += Form("PairLS_%s_%s_%s;", (*trackCut).GetName(), fTrackCutsProbe.at(iCut).GetName(), (*pairCut).GetName()); } } else { histClasses += Form("TrackBarrel_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); histClasses += Form("Pair_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); if (fConfigOptions.fConfigEnableLikeSign) { - histClasses += Form("Pair_LS_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); + histClasses += Form("PairLS_%s_%s;", (*trackCut).GetName(), (*pairCut).GetName()); } } } @@ -334,7 +335,7 @@ struct DalitzSelection { if (!fIsTagAndProbe && track1.globalIndex() >= track2.globalIndex()) { continue; } - if (!fConfigOptions.fConfigEnableLikeSign && track1.sign() * track2.sign() > 0) { + if (!fConfigOptions.fConfigEnableLikeSign && (track1.sign() * track2.sign() > 0)) { continue; } @@ -461,7 +462,7 @@ struct DalitzSelection { } for (const auto& track : tracks) { // Fill dalitz bits - dalitzbits(fDalitzmap[track.globalIndex()]); + dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); } } From ed1e8a83d6899ad836e8be9a747036ea3ba573d2 Mon Sep 17 00:00:00 2001 From: Noor Koster <82090643+cnkoster@users.noreply.github.com> Date: Fri, 8 May 2026 17:05:28 +0200 Subject: [PATCH 099/449] [PWGCF] Check secondaries vs. pt in MCReco and add possibility for 3D corrections (#16131) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowSP.cxx | 822 +++++++++++++++++++----------------- 1 file changed, 441 insertions(+), 381 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowSP.cxx b/PWGCF/Flow/Tasks/flowSP.cxx index f1b672c76e6..37b48ee0f50 100644 --- a/PWGCF/Flow/Tasks/flowSP.cxx +++ b/PWGCF/Flow/Tasks/flowSP.cxx @@ -73,100 +73,109 @@ using namespace o2::aod::rctsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct FlowSP { - RCTFlagsChecker rctChecker; + // event selection configurable group struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgEvtUseRCTFlagChecker, bool, false, "Evt sel: use RCT flag checker"); - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLabel, std::string, "CBT_hadronPID", "Evt sel: RCT flag checker label (CBT, CBT_hadronPID)"); // all Labels can be found in Common/CCDB/RCTSelectionFlags.h - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerZDCCheck, bool, false, "Evt sel: RCT flag checker ZDC check"); - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"); - } rctFlags; + O2_DEFINE_CONFIGURABLE(cEvtUseRCTFlagChecker, bool, false, "Evt sel: use RCT flag checker"); + O2_DEFINE_CONFIGURABLE(cEvtRCTFlagCheckerLabel, std::string, "CBT_hadronPID", "Evt sel: RCT flag checker label (CBT, CBT_hadronPID)"); // all Labels can be found in Common/CCDB/RCTSelectionFlags.h + O2_DEFINE_CONFIGURABLE(cEvtRCTFlagCheckerZDCCheck, bool, false, "Evt sel: RCT flag checker ZDC check"); + O2_DEFINE_CONFIGURABLE(cEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"); + O2_DEFINE_CONFIGURABLE(cEvSelsUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut"); + O2_DEFINE_CONFIGURABLE(cEvSelsMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); + O2_DEFINE_CONFIGURABLE(cEvSelsMinOccupancy, int, 0, "Minimum occupancy of selected events"); + O2_DEFINE_CONFIGURABLE(cEvSelsNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); + O2_DEFINE_CONFIGURABLE(cEvSelsIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); + O2_DEFINE_CONFIGURABLE(cEvSelsNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); + O2_DEFINE_CONFIGURABLE(cEvSelsNoCollInTimeRangeNarrow, bool, true, "kNoCollInTimeRangeNarrow"); + O2_DEFINE_CONFIGURABLE(cEvSelsDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); + O2_DEFINE_CONFIGURABLE(cEvSelsIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track"); + O2_DEFINE_CONFIGURABLE(cEvSelsIsGoodITSLayersAll, bool, true, "Cut time intervals with dead ITS staves"); + O2_DEFINE_CONFIGURABLE(cEvSelsIsGoodITSLayer0123, bool, true, "Cut time intervals with dead ITS staves"); + + // QA Plots + O2_DEFINE_CONFIGURABLE(cFillEventQA, bool, false, "Fill histograms for event QA"); + O2_DEFINE_CONFIGURABLE(cFillTrackQA, bool, false, "Fill histograms for track QA"); + O2_DEFINE_CONFIGURABLE(cFillPIDQA, bool, false, "Fill histograms for PID QA"); + O2_DEFINE_CONFIGURABLE(cFillEventPlaneQA, bool, false, "Fill histograms for Event Plane QA"); + O2_DEFINE_CONFIGURABLE(cFillQABefore, bool, false, "Fill QA histograms before cuts, only for processData"); + O2_DEFINE_CONFIGURABLE(cFillMeanPT, bool, false, "Fill histograms for mean PX/PT"); + O2_DEFINE_CONFIGURABLE(cFillMeanPTextra, bool, false, "Fill histograms for mean PX/PT extra"); + O2_DEFINE_CONFIGURABLE(cUseCentAveragePt, bool, false, "Use in 1% centrality intervals and not cent average"); + O2_DEFINE_CONFIGURABLE(cFillWithMCParticle, bool, false, "Fill histograms with MCParticle instead of Track"); + // Flags to make and fill histograms + O2_DEFINE_CONFIGURABLE(cFillGeneralV1Histos, bool, true, "Fill histograms for vn analysis"); + O2_DEFINE_CONFIGURABLE(cFillMixedHarmonics, bool, true, "Flag to make and fill histos for mixed harmonics"); + O2_DEFINE_CONFIGURABLE(cFillEventPlane, bool, false, "Flag to make and fill histos with Event Plane"); + O2_DEFINE_CONFIGURABLE(cFillXandYterms, bool, false, "Flag to make and fill histos for with separate x and y terms for SPM"); + O2_DEFINE_CONFIGURABLE(cFillChargeDependence, bool, true, "Flag to make and fill histos for charge dependent flow"); + O2_DEFINE_CONFIGURABLE(cFillChargeDependenceQA, bool, true, "Flag to make and fill QA histos for charge dependent flow"); + O2_DEFINE_CONFIGURABLE(cFillPID, bool, false, "Flag to make and fill histos for PID flow"); + // Centrality Estimators -> standard is FT0C + O2_DEFINE_CONFIGURABLE(cCentFT0Cvariant1, bool, false, "Set centrality estimator to CentFT0Cvariant1"); + O2_DEFINE_CONFIGURABLE(cCentFT0M, bool, false, "Set centrality estimator to CentFT0M"); + O2_DEFINE_CONFIGURABLE(cCentFV0A, bool, false, "Set centrality estimator to CentFV0A"); + O2_DEFINE_CONFIGURABLE(cCentNGlobal, bool, false, "Set centrality estimator to CentNGlobal"); + // Standard selections + O2_DEFINE_CONFIGURABLE(cTrackSelsDCAxy, float, 0.2, "Cut on DCA in the transverse direction (cm)"); + O2_DEFINE_CONFIGURABLE(cTrackSelsDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); + O2_DEFINE_CONFIGURABLE(cTrackSelsNcls, float, 70, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cTrackSelsFshcls, float, 0.4, "Cut on fraction of shared TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cTrackSelsPtmin, float, 0.2, "minimum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cTrackSelsPtmax, float, 10, "maximum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cTrackSelsEta, float, 0.8, "eta cut"); + O2_DEFINE_CONFIGURABLE(cIsMCReco, bool, true, "Is MC Reco"); + O2_DEFINE_CONFIGURABLE(cEvSelsVtxZ, float, 10, "vertex cut (cm)"); + O2_DEFINE_CONFIGURABLE(cMagField, float, 99999, "Configurable magnetic field;default CCDB will be queried"); + O2_DEFINE_CONFIGURABLE(cCentMin, float, 0, "Minimum cenrality for selected events"); + O2_DEFINE_CONFIGURABLE(cCentMax, float, 90, "Maximum cenrality for selected events"); + O2_DEFINE_CONFIGURABLE(cFilterLeptons, bool, true, "Filter out leptons from MCGenerated by requiring |pdgCode| > 100"); + // NUA and NUE weights + O2_DEFINE_CONFIGURABLE(cFillWeights, bool, true, "Fill NUA weights"); + O2_DEFINE_CONFIGURABLE(cFillWeightsPOS, bool, true, "Fill NUA weights only for positive charges"); + O2_DEFINE_CONFIGURABLE(cFillWeightsNEG, bool, true, "Fill NUA weights only for negative charges"); + O2_DEFINE_CONFIGURABLE(cUseNUA1D, bool, true, "Use 1D NUA weights (only phi)"); + O2_DEFINE_CONFIGURABLE(cUseNUA2D, bool, false, "Use 2D NUA weights (phi and eta)"); + O2_DEFINE_CONFIGURABLE(cUseNUE2D, bool, false, "Use 2D NUE weights"); + O2_DEFINE_CONFIGURABLE(cUseNUE3D, bool, false, "Use 3D NUE weights (pt, eta, centrality)"); + O2_DEFINE_CONFIGURABLE(cUseNUE2Deta, bool, false, "Use 2D NUE weights TRUE: (pt and eta) FALSE: (pt and centrality)"); + // Additional track Selections + O2_DEFINE_CONFIGURABLE(cTrackSelsUseAdditionalTrackCut, bool, false, "Bool to enable Additional Track Cut"); + O2_DEFINE_CONFIGURABLE(cTrackSelsDoDCApt, bool, false, "Apply Pt dependent DCAz cut"); + O2_DEFINE_CONFIGURABLE(cTrackSelsDCApt1, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets a"); + O2_DEFINE_CONFIGURABLE(cTrackSelsDCApt2, float, 0.035, "DcaZ < const + (a * b) / pt^1.1 -> this sets b"); + O2_DEFINE_CONFIGURABLE(cTrackSelsDCAptConsMin, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets const"); + O2_DEFINE_CONFIGURABLE(cTrackSelsPIDNsigma, float, 2.0, "nSigma cut for PID"); + O2_DEFINE_CONFIGURABLE(cTrackSelDoTrackQAvsCent, bool, true, "Do track selection QA plots as function of centrality"); + // harmonics for v coefficients + O2_DEFINE_CONFIGURABLE(cHarm, int, 1, "Flow harmonic n for ux and uy: (Cos(n*phi), Sin(n*phi))"); + O2_DEFINE_CONFIGURABLE(cHarmMixed, int, 2, "Flow harmonic n for ux and uy in mixed harmonics (MH): (Cos(n*phi), Sin(n*phi))"); + // settings for CCDB data + O2_DEFINE_CONFIGURABLE(cCCDBdir_QQ, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass5/meanQQ/Default", "ccdb dir for average QQ values in 1% centrality bins"); + O2_DEFINE_CONFIGURABLE(cCCDBdir_SP, std::string, "", "ccdb dir for average event plane resolution in 1% centrality bins"); + O2_DEFINE_CONFIGURABLE(cCCDB_NUA, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/Default", "ccdb dir for NUA corrections"); + O2_DEFINE_CONFIGURABLE(cCCDB_NUE, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/Default", "ccdb dir for NUE corrections (pt)"); + O2_DEFINE_CONFIGURABLE(cCCDB_NUE2D, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/2D", "ccdb dir for NUE 2D corrections (pt, eta)"); + O2_DEFINE_CONFIGURABLE(cCCDB_NUE3D, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/3D", "ccdb dir for NUE 3D corrections (pt, eta, centrality)"); + O2_DEFINE_CONFIGURABLE(cCCDBdir_centrality, std::string, "", "ccdb dir for Centrality corrections"); + O2_DEFINE_CONFIGURABLE(cCCDBdir_meanPt, std::string, "", "ccdb dir for Mean Pt corrections"); + + // Confogirable axis + // ConfigurableAxis axisCentrality{"axisCentrality", {20, 0, 100}, "Centrality bins for vn "}; + // ConfigurableAxis axisMomentum{"axisMomentum", {20, 0, 10}, "Momentum bins for vn"}; + // ConfigurableAxis axisEtaVn{"axisEtaVn", {8, -0.8, 0.8}, "Eta bins for vn"}; + + // Configurables containing vector + Configurable> cEvSelsMultPv{"cEvSelsMultPv", std::vector{2223.49, -75.1444, 0.963572, -0.00570399, 1.34877e-05, 3790.99, -137.064, 2.13044, -0.017122, 5.82834e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; + Configurable> cEvSelsMult{"cEvSelsMult", std::vector{1301.56, -41.4615, 0.478224, -0.00239449, 4.46966e-06, 2967.6, -102.927, 1.47488, -0.0106534, 3.28622e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; + Configurable> cPtBinning{"cPtBinning", std::vector{0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}, "pT binning for vn"}; - // event selection configurable group - O2_DEFINE_CONFIGURABLE(cfgEvSelsUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMinOccupancy, int, 0, "Minimum occupancy of selected events"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsNoCollInTimeRangeNarrow, bool, true, "kNoCollInTimeRangeNarrow"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodITSLayersAll, bool, true, "Cut time intervals with dead ITS staves"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodITSLayer0123, bool, true, "Cut time intervals with dead ITS staves"); - - // QA Plots - O2_DEFINE_CONFIGURABLE(cfgFillEventQA, bool, false, "Fill histograms for event QA"); - O2_DEFINE_CONFIGURABLE(cfgFillTrackQA, bool, false, "Fill histograms for track QA"); - O2_DEFINE_CONFIGURABLE(cfgFillPIDQA, bool, false, "Fill histograms for PID QA"); - O2_DEFINE_CONFIGURABLE(cfgFillEventPlaneQA, bool, false, "Fill histograms for Event Plane QA"); - O2_DEFINE_CONFIGURABLE(cfgFillQABefore, bool, false, "Fill QA histograms before cuts, only for processData"); - O2_DEFINE_CONFIGURABLE(cfgFillMeanPT, bool, false, "Fill histograms for mean PX/PT"); - O2_DEFINE_CONFIGURABLE(cfgUseCentAveragePt, bool, false, "Use in 1% centrality intervals and not ecent average"); - // Flags to make and fill histograms - O2_DEFINE_CONFIGURABLE(cfgFillGeneralV1Histos, bool, true, "Fill histograms for vn analysis"); - O2_DEFINE_CONFIGURABLE(cfgFillMixedHarmonics, bool, true, "Flag to make and fill histos for mixed harmonics"); - O2_DEFINE_CONFIGURABLE(cfgFillEventPlane, bool, false, "Flag to make and fill histos with Event Plane"); - O2_DEFINE_CONFIGURABLE(cfgFillXandYterms, bool, false, "Flag to make and fill histos for with separate x and y terms for SPM"); - O2_DEFINE_CONFIGURABLE(cfgFillChargeDependence, bool, true, "Flag to make and fill histos for charge dependent flow"); - O2_DEFINE_CONFIGURABLE(cfgFillChargeDependenceQA, bool, true, "Flag to make and fill QA histos for charge dependent flow"); - O2_DEFINE_CONFIGURABLE(cfgFillPID, bool, false, "Flag to make and fill histos for PID flow"); - // Centrality Estimators -> standard is FT0C - O2_DEFINE_CONFIGURABLE(cfgCentFT0Cvariant1, bool, false, "Set centrality estimator to cfgCentFT0Cvariant1"); - O2_DEFINE_CONFIGURABLE(cfgCentFT0M, bool, false, "Set centrality estimator to cfgCentFT0M"); - O2_DEFINE_CONFIGURABLE(cfgCentFV0A, bool, false, "Set centrality estimator to cfgCentFV0A"); - O2_DEFINE_CONFIGURABLE(cfgCentNGlobal, bool, false, "Set centrality estimator to cfgCentNGlobal"); - // Standard selections - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCAxy, float, 0.2, "Cut on DCA in the transverse direction (cm)"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsNcls, float, 70, "Cut on number of TPC clusters found"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsFshcls, float, 0.4, "Cut on fraction of shared TPC clusters found"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsPtmin, float, 0.2, "minimum pt (GeV/c)"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsPtmax, float, 10, "maximum pt (GeV/c)"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsEta, float, 0.8, "eta cut"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsVtxZ, float, 10, "vertex cut (cm)"); - O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field;default CCDB will be queried"); - O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0, "Minimum cenrality for selected events"); - O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90, "Maximum cenrality for selected events"); - O2_DEFINE_CONFIGURABLE(cfgFilterLeptons, bool, true, "Filter out leptons from MCGenerated by requiring |pdgCode| > 100"); - // NUA and NUE weights - O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, true, "Fill NUA weights"); - O2_DEFINE_CONFIGURABLE(cfgFillWeightsPOS, bool, true, "Fill NUA weights only for positive charges"); - O2_DEFINE_CONFIGURABLE(cfgFillWeightsNEG, bool, true, "Fill NUA weights only for negative charges"); - O2_DEFINE_CONFIGURABLE(cfgUseNUA1D, bool, false, "Use 1D NUA weights (only phi)"); - O2_DEFINE_CONFIGURABLE(cfgUseNUA2D, bool, true, "Use 2D NUA weights (phi and eta)"); - O2_DEFINE_CONFIGURABLE(cfgUseNUE2D, bool, true, "Use 2D NUE weights"); - O2_DEFINE_CONFIGURABLE(cfgUseNUE2Deta, bool, true, "Use 2D NUE weights TRUE: (pt and eta) FALSE: (pt and centrality)"); - // Additional track Selections - O2_DEFINE_CONFIGURABLE(cfgTrackSelsUseAdditionalTrackCut, bool, false, "Bool to enable Additional Track Cut"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDoDCApt, bool, false, "Apply Pt dependent DCAz cut"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt1, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets a"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt2, float, 0.035, "DcaZ < const + (a * b) / pt^1.1 -> this sets b"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCAptConsMin, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets const"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsPIDNsigma, float, 2.0, "nSigma cut for PID"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelDoTrackQAvsCent, bool, true, "Do track selection QA plots as function of centrality"); - // harmonics for v coefficients - O2_DEFINE_CONFIGURABLE(cfgHarm, int, 1, "Flow harmonic n for ux and uy: (Cos(n*phi), Sin(n*phi))"); - O2_DEFINE_CONFIGURABLE(cfgHarmMixed, int, 2, "Flow harmonic n for ux and uy in mixed harmonics (MH): (Cos(n*phi), Sin(n*phi))"); - // settings for CCDB data - O2_DEFINE_CONFIGURABLE(cfgCCDBdir_QQ, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass5/meanQQ/Default", "ccdb dir for average QQ values in 1% centrality bins"); - O2_DEFINE_CONFIGURABLE(cfgCCDBdir_SP, std::string, "", "ccdb dir for average event plane resolution in 1% centrality bins"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUA, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/Default", "ccdb dir for NUA corrections"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/Default", "ccdb dir for NUE corrections (pt)"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE2D, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/2D", "ccdb dir for NUE 2D corrections (eta, pt)"); - O2_DEFINE_CONFIGURABLE(cfgCCDBdir_centrality, std::string, "", "ccdb dir for Centrality corrections"); - O2_DEFINE_CONFIGURABLE(cfgCCDBdir_meanPt, std::string, "", "ccdb dir for Mean Pt corrections"); - // Confogirable axis - ConfigurableAxis axisCentrality{"axisCentrality", {20, 0, 100}, "Centrality bins for vn "}; - ConfigurableAxis axisNch = {"axisNch", {400, 0, 4000}, "Global N_{ch}"}; - ConfigurableAxis axisMultpv = {"axisMultpv", {400, 0, 4000}, "N_{ch} (PV)"}; - // Configurables containing vector - Configurable> cfgEvSelsMultPv{"cfgEvSelsMultPv", std::vector{2223.49, -75.1444, 0.963572, -0.00570399, 1.34877e-05, 3790.99, -137.064, 2.13044, -0.017122, 5.82834e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; - Configurable> cfgEvSelsMult{"cfgEvSelsMult", std::vector{1301.56, -41.4615, 0.478224, -0.00239449, 4.46966e-06, 2967.6, -102.927, 1.47488, -0.0106534, 3.28622e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; - - Filter collisionFilter = nabs(aod::collision::posZ) < cfgEvSelsVtxZ; - Filter trackFilter = nabs(aod::track::eta) < cfgTrackSelsEta && aod::track::pt > cfgTrackSelsPtmin&& aod::track::pt < cfgTrackSelsPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && nabs(aod::track::dcaXY) < cfgTrackSelsDCAxy&& nabs(aod::track::dcaZ) < cfgTrackSelsDCAz; - Filter trackFilterMC = nabs(aod::mcparticle::eta) < cfgTrackSelsEta && aod::mcparticle::pt > cfgTrackSelsPtmin&& aod::mcparticle::pt < cfgTrackSelsPtmax; + } cfg; + + RCTFlagsChecker rctChecker; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfg.cEvSelsVtxZ; + Filter trackFilter = nabs(aod::track::eta) < cfg.cTrackSelsEta && aod::track::pt > cfg.cTrackSelsPtmin&& aod::track::pt < cfg.cTrackSelsPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true) || cfg.cIsMCReco) && nabs(aod::track::dcaXY) < cfg.cTrackSelsDCAxy&& nabs(aod::track::dcaZ) < cfg.cTrackSelsDCAz; + Filter trackFilterMC = nabs(aod::mcparticle::eta) < cfg.cTrackSelsEta && aod::mcparticle::pt > cfg.cTrackSelsPtmin&& aod::mcparticle::pt < cfg.cTrackSelsPtmax; using GeneralCollisions = soa::Join; using UnfilteredTracksPID = soa::Join; using UnfilteredTracks = soa::Join; @@ -196,6 +205,7 @@ struct FlowSP { struct Config { std::vector mEfficiency = {}; std::vector mEfficiency2D = {}; + std::vector mEfficiency3D = {}; std::vector mAcceptance = {}; std::vector mAcceptance2D = {}; bool correctionsLoaded = false; @@ -213,7 +223,7 @@ struct FlowSP { bool clCentrality = false; bool clMeanPt = false; - } cfg; + } conf; struct SPMvars { std::vector> wacc = {{{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}}; // int for part species, float for weight vector for kIncl, kPos, kNeg @@ -345,6 +355,7 @@ struct FlowSP { AxisSpec axisPhi = {60, 0, constants::math::TwoPI, "#varphi"}; AxisSpec axisEta = {64, -1.6, 1.6, "#eta"}; AxisSpec axisEtaVn = {8, -.8, .8, "#eta"}; + AxisSpec axisCentrality = {20, 0, 100, "Centrality (%)"}; AxisSpec axisVx = {40, -0.01, 0.01, "v_{x}"}; AxisSpec axisVy = {40, -0.01, 0.01, "v_{y}"}; AxisSpec axisVz = {40, -10, 10, "v_{z}"}; @@ -360,13 +371,12 @@ struct FlowSP { AxisSpec axisBeta = {150, 0, 1.5, "Beta for PID"}; AxisSpec axisCharge = {3, 0, 3, "Charge: 0 = inclusive, 1 = positive, 2 = negative"}; AxisSpec axisPx = {100, -0.05, 0.05, "p_{x} (GeV/c)"}; + AxisSpec axisNch = {400, 0, 4000, "Global N_{ch}"}; + AxisSpec axisMultpv = {400, 0, 4000, "N_{ch} (PV)"}; + AxisSpec axisPt = {cfg.cPtBinning, "#it{p}_{T} GeV/#it{c}"}; + int ptbins = cfg.cPtBinning->size() - 1; - std::vector ptbinning = {0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}; - AxisSpec axisPt = {ptbinning, "#it{p}_{T} GeV/#it{c}"}; - - int ptbins = ptbinning.size() - 1; - - rctChecker.init(rctFlags.cfgEvtRCTFlagCheckerLabel, rctFlags.cfgEvtRCTFlagCheckerZDCCheck, rctFlags.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + rctChecker.init(cfg.cEvtRCTFlagCheckerLabel, cfg.cEvtRCTFlagCheckerZDCCheck, cfg.cEvtRCTFlagCheckerLimitAcceptAsBad); histos.add("hCentrality", "Centrality; Centrality (%); ", {HistType::kTH1D, {axisCent}}); @@ -398,23 +408,23 @@ struct FlowSP { histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(trackSel_ZeroCharge + 1, "Only charged"); histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(trackSel_ParticleWeights + 1, "Apply weights"); - if (cfgFillWeights) { + if (cfg.cFillWeights) { registry.add("weights2D/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("weights2D/hPhi_Eta_vz_positive", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("weights2D/hPhi_Eta_vz_negative", "", kTH3D, {axisPhi, axisEta, axisVz}); // define output objects - fWeights->setPtBins(ptbins, &ptbinning[0]); + fWeights->setPtBins(ptbins, &cfg.cPtBinning.value[0]); fWeights->init(true, false); - fWeightsPOS->setPtBins(ptbins, &ptbinning[0]); + fWeightsPOS->setPtBins(ptbins, &cfg.cPtBinning.value[0]); fWeightsPOS->init(true, false); - fWeightsNEG->setPtBins(ptbins, &ptbinning[0]); + fWeightsNEG->setPtBins(ptbins, &cfg.cPtBinning.value[0]); fWeightsNEG->init(true, false); } - if (cfgFillEventQA) { + if (cfg.cFillEventQA) { histos.add("QA/after/hCentFT0C", " ; Cent FT0C (%); ", {HistType::kTH1D, {axisCent}}); histos.add("QA/after/hCentFT0M", "; Cent FT0M (%); ", {HistType::kTH1D, {axisCent}}); histos.add("QA/after/hCentFV0A", "; Cent FV0A (%); ", {HistType::kTH1D, {axisCent}}); @@ -431,7 +441,7 @@ struct FlowSP { histos.add("QA/after/CentFT0C_vs_CentFV0A", " ; Cent FT0C (%); Cent FV0A (%) ", {HistType::kTH2D, {axisCent, axisCent}}); histos.add("QA/after/CentFT0C_vs_CentNGlobal", " ; Cent FT0C (%); Cent NGlobal (%) ", {HistType::kTH2D, {axisCent, axisCent}}); - if (cfgFillEventPlaneQA && doprocessData) { + if (cfg.cFillEventPlaneQA && doprocessData) { histos.add("QA/after/PsiA_vs_Cent", "", {HistType::kTH2D, {axisPhiPlane, axisCent}}); histos.add("QA/after/PsiC_vs_Cent", "", {HistType::kTH2D, {axisPhiPlane, axisCent}}); histos.add("QA/after/PsiFull_vs_Cent", "", {HistType::kTH2D, {axisPhiPlane, axisCent}}); @@ -447,14 +457,14 @@ struct FlowSP { // histos.add("QA/after/DeltaPsivsPx", "", {HistType::kTH3D, {axisCent, axisPhiPlane, axisPx}}); } - if (cfgFillQABefore) { + if (cfg.cFillQABefore) { histos.addClone("QA/after/", "QA/before/"); } } if (doprocessData || doprocessMCReco || doprocessDataPID) { - if (cfgFillTrackQA) { + if (cfg.cFillTrackQA) { histos.add("incl/QA/after/pt_phi", "", {HistType::kTH2D, {axisPt, axisPhiMod}}); histos.add("incl/QA/after/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); histos.add("incl/QA/after/hPhi_Eta_vz_corrected", "", kTH3D, {axisPhi, axisEta, axisVz}); @@ -465,7 +475,7 @@ struct FlowSP { histos.add("incl/QA/after/hCrossedRows_vs_SharedClusters", "", {HistType::kTH2D, {axisCl, axisShCl}}); histos.add("incl/QA/after/hMeanPtEta", "", {HistType::kTProfile2D, {axisEta, axisCent}}); - if (cfgTrackSelDoTrackQAvsCent) { + if (cfg.cTrackSelDoTrackQAvsCent) { histos.add("incl/QA/after/hPt_Eta", "", kTH3D, {axisPt, axisEta, axisCent}); histos.add("incl/QA/after/hPt_Eta_uncorrected", "", kTH3D, {axisPt, axisEta, axisCent}); histos.add("incl/QA/after/hPhi_Eta", "", kTH3D, {axisPhi, axisEta, axisCent}); @@ -475,11 +485,11 @@ struct FlowSP { histos.add("incl/QA/after/hPhi_Eta_Pt_corrected", "", kTH3D, {axisPhi, axisEta, axisPt}); } - if (cfgFillQABefore) + if (cfg.cFillQABefore) histos.addClone("incl/QA/after/", "incl/QA/before/"); } - if (cfgFillPIDQA && doprocessDataPID) { + if (cfg.cFillPIDQA && doprocessDataPID) { histos.add("hPIDcounts", "", kTH2D, {{{4, 0, 4}, axisPt}}); histos.get(HIST("hPIDcounts"))->GetXaxis()->SetBinLabel(1, "UFO"); histos.get(HIST("hPIDcounts"))->GetXaxis()->SetBinLabel(2, "Pion"); @@ -494,7 +504,7 @@ struct FlowSP { histos.add("incl/pion/QA/after/hNsigmaTPC_pt", "", {HistType::kTH2D, {axisPt, axisNsigma}}); histos.add("incl/pion/QA/after/hNsigmaTOF_pt", "", {HistType::kTH2D, {axisPt, axisNsigma}}); - if (cfgTrackSelDoTrackQAvsCent) { + if (cfg.cTrackSelDoTrackQAvsCent) { histos.add("incl/pion/QA/after/hPt_Eta", "", kTH3D, {axisPt, axisEta, axisCent}); histos.add("incl/pion/QA/after/hPt_Eta_uncorrected", "", kTH3D, {axisPt, axisEta, axisCent}); histos.add("incl/pion/QA/after/hPhi_Eta", "", kTH3D, {axisPhi, axisEta, axisCent}); @@ -511,7 +521,7 @@ struct FlowSP { histos.add("incl/pion/QA/after/hCrossedRows_pt", "", {HistType::kTH2D, {axisPt, axisCl}}); histos.add("incl/pion/QA/after/hCrossedRows_vs_SharedClusters", "", {HistType::kTH2D, {axisCl, axisShCl}}); - if (cfgFillQABefore) { + if (cfg.cFillQABefore) { histos.addClone("incl/pion/QA/after/", "incl/pion/QA/before/"); } @@ -519,16 +529,16 @@ struct FlowSP { histos.addClone("incl/pion/", "incl/proton/"); } - if (cfgFillEventQA) { + if (cfg.cFillEventQA) { histos.add("QA/hCentFull", " ; Centrality (%); ", {HistType::kTH1D, {axisCent}}); } if (doprocessMCReco) { - registry.add("trackMCReco/after/hIsPhysicalPrimary", "", {HistType::kTH2D, {{2, 0, 2}, axisCentrality}}); + registry.add("trackMCReco/after/incl/hIsPhysicalPrimary", "", {HistType::kTH3D, {{2, 0, 2}, axisCentrality, axisPt}}); + registry.get(HIST("trackMCReco/after/incl/hIsPhysicalPrimary"))->GetXaxis()->SetBinLabel(1, "Secondary"); + registry.get(HIST("trackMCReco/after/incl/hIsPhysicalPrimary"))->GetXaxis()->SetBinLabel(2, "Primary"); registry.add("trackMCReco/hTrackSize_unFiltered", "", {HistType::kTH2D, {{100, 0, 200000}, axisCentrality}}); registry.add("trackMCReco/hTrackSize_Filtered", "", {HistType::kTH2D, {{100, 0, 20000}, axisCentrality}}); - registry.get(HIST("trackMCReco/after/hIsPhysicalPrimary"))->GetXaxis()->SetBinLabel(1, "Secondary"); - registry.get(HIST("trackMCReco/after/hIsPhysicalPrimary"))->GetXaxis()->SetBinLabel(2, "Primary"); registry.add("trackMCReco/after/incl/hPt_hadron", "", {HistType::kTH3D, {axisPt, axisEta, axisCentrality}}); registry.add("trackMCReco/after/incl/hPt_proton", "", {HistType::kTH3D, {axisPt, axisEta, axisCentrality}}); registry.add("trackMCReco/after/incl/hPt_pion", "", {HistType::kTH3D, {axisPt, axisEta, axisCentrality}}); @@ -547,7 +557,7 @@ struct FlowSP { registry.add("QQCorrelations/qAYqCX", "", kTProfile, {axisCent}); registry.add("QQCorrelations/qAXYqCXY", "", kTProfile, {axisCent}); - if (cfgFillGeneralV1Histos) { + if (cfg.cFillGeneralV1Histos) { // track properties per centrality and per eta, pt bin registry.add("incl/vnCodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnAodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); @@ -555,48 +565,52 @@ struct FlowSP { registry.add("incl/vnA", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnCSetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnASetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnOdd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnEven", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillMeanPT) { - registry.add("incl/meanPT/meanRelPtA", "", kTProfile2D, {axisEtaVn, axisCentrality}); - registry.add("incl/meanPT/meanRelPtC", "", kTProfile2D, {axisEtaVn, axisCentrality}); - - registry.add("incl/meanPT/hMeanPtEtaCent", "", kTProfile2D, {axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1A", "", kTProfile2D, {axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1C", "", kTProfile2D, {axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1Aodd", "", kTProfile2D, {axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1Codd", "", kTProfile2D, {axisEtaVn, axisCent}); - registry.add("incl/meanPT/hMeanPtCent", "", kTProfile, {axisCent}); - + if (cfg.cFillMeanPT) { registry.add("incl/meanPT/ptV1A3D", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); registry.add("incl/meanPT/ptV1C3D", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1A3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1C3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + if (cfg.cFillMeanPTextra) { + registry.add("incl/meanPT/meanRelPtA", "", kTProfile2D, {axisEtaVn, axisCentrality}); + registry.add("incl/meanPT/meanRelPtC", "", kTProfile2D, {axisEtaVn, axisCentrality}); - registry.add("incl/meanPT/ptV1A3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); - registry.add("incl/meanPT/ptV1C3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/hMeanPtEtaCent", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1A", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1Aodd", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1Codd", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/hMeanPtCent", "", kTProfile, {axisCent}); - registry.add("incl/meanPT/meanPxA", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); - registry.add("incl/meanPT/meanPxC", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); + registry.add("incl/meanPT/ptV1A3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + + registry.add("incl/meanPT/ptV1A3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + + registry.add("incl/meanPT/meanPxA", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); + registry.add("incl/meanPT/meanPxC", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); + } } - if (cfgFillXandYterms) { + if (cfg.cFillXandYterms) { registry.add("incl/vnAx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnAy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnCx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnCy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillMixedHarmonics) { + if (cfg.cFillMixedHarmonics) { registry.add("incl/MH/vnAxCxUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAyCyUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAxCyUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAyCxUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillEventPlane) { + if (cfg.cFillEventPlane) { registry.add("incl/vnA_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnC_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnFull_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillEventPlaneQA) { + if (cfg.cFillEventPlaneQA) { histos.add("QA/hSPplaneA", "hSPplaneA", kTH1D, {axisPhiPlane}); histos.add("QA/hSPplaneC", "hSPplaneC", kTH1D, {axisPhiPlane}); histos.add("QA/hSPplaneFull", "hSPplaneFull", kTH1D, {axisPhiPlane}); @@ -609,7 +623,7 @@ struct FlowSP { } // end of doProcessData - if (cfgFillChargeDependence || cfgFillChargeDependenceQA) { + if (cfg.cFillChargeDependence || cfg.cFillChargeDependenceQA) { LOGF(info, "Cloning charge dependence histograms"); registry.addClone("incl/", "pos/"); registry.addClone("incl/", "neg/"); @@ -619,7 +633,7 @@ struct FlowSP { } if (doprocessDataPID) { - if (cfgFillGeneralV1Histos) { + if (cfg.cFillGeneralV1Histos) { registry.add("incl/pion/vnCodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnAodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnC", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); @@ -628,18 +642,18 @@ struct FlowSP { registry.add("incl/vnASetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillEventPlane) { + if (cfg.cFillEventPlane) { registry.add("incl/pion/vnA_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnC_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnFull_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillXandYterms) { + if (cfg.cFillXandYterms) { registry.add("incl/pion/vnAx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnAy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnCx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/vnCy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillMixedHarmonics) { + if (cfg.cFillMixedHarmonics) { registry.add("incl/pion/MH/vnAxCxUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/MH/vnAyCyUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/pion/MH/vnAxCyUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); @@ -647,7 +661,7 @@ struct FlowSP { } registry.addClone("incl/pion/", "incl/proton/"); registry.addClone("incl/pion/", "incl/kaon/"); - if (cfgFillChargeDependence) { + if (cfg.cFillChargeDependence) { registry.addClone("incl/", "pos/"); registry.addClone("incl/", "neg/"); } @@ -665,22 +679,22 @@ struct FlowSP { registry.addClone("trackMCGen/after/", "trackMCGen/before/"); } - if (cfgEvSelsUseAdditionalEventCut) { + if (cfg.cEvSelsUseAdditionalEventCut) { fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - std::vector paramsMultPVCut = cfgEvSelsMultPv; - std::vector paramsMultCut = cfgEvSelsMult; + std::vector paramsMultPVCut = cfg.cEvSelsMultPv; + std::vector paramsMultCut = cfg.cEvSelsMult; - // number of parameters required in cfgEvSelsMultPv and cfgEvSelsMult. (5 Low + 5 High) + // number of parameters required in cfg.cEvSelsMultPv and cfg.cEvSelsMult. (5 Low + 5 High) uint64_t nParams = 10; if (paramsMultPVCut.size() < nParams) { - LOGF(fatal, "cfgEvSelsMultPv not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultPVCut.size()); + LOGF(fatal, "cfg.cEvSelsMultPv not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultPVCut.size()); } else if (paramsMultCut.size() < nParams) { - LOGF(fatal, "cfgEvSelsMult not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultCut.size()); + LOGF(fatal, "cfg.cEvSelsMult not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultCut.size()); } else { fMultPVCutLow->SetParameters(paramsMultPVCut[0], paramsMultPVCut[1], paramsMultPVCut[2], paramsMultPVCut[3], paramsMultPVCut[4]); fMultPVCutHigh->SetParameters(paramsMultPVCut[5], paramsMultPVCut[6], paramsMultPVCut[7], paramsMultPVCut[8], paramsMultPVCut[9]); @@ -689,7 +703,7 @@ struct FlowSP { } } - if (cfgTrackSelsUseAdditionalTrackCut) { + if (cfg.cTrackSelsUseAdditionalTrackCut) { fPhiCutLow = new TF1("fPhiCutLow", "0.06/x+pi/18.0-0.06", 0, 100); fPhiCutHigh = new TF1("fPhiCutHigh", "0.1/x+pi/18.0+0.06", 0, 100); } @@ -736,7 +750,7 @@ struct FlowSP { ParticleType valPID = kUnidentified; for (const auto& nsigma : usedNSigma) { - if (std::abs(nsigma.first) < cfgTrackSelsPIDNsigma) { + if (std::abs(nsigma.first) < cfg.cTrackSelsPIDNsigma) { valPID = nsigma.second; nIdentified++; } @@ -783,88 +797,107 @@ struct FlowSP { void loadCorrections(uint64_t timestamp) { // corrections saved on CCDB as TList {incl, pos, neg} of GFWWeights (acc) TH1D (eff) objects! - if (cfg.correctionsLoaded) + if (conf.correctionsLoaded) return; int nWeights = 3; - if (cfgUseNUA1D) { - if (cfgCCDB_NUA.value.empty() == false) { - TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights"))); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_positive"))); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_negative"))); - int sizeAcc = cfg.mAcceptance.size(); + if (cfg.cUseNUA1D) { + if (cfg.cCCDB_NUA.value.empty() == false) { + TList* listCorrections = ccdb->getForTimeStamp(cfg.cCCDB_NUA, timestamp); + conf.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights"))); + conf.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_positive"))); + conf.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_negative"))); + int sizeAcc = conf.mAcceptance.size(); if (sizeAcc < nWeights) - LOGF(fatal, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + LOGF(fatal, "Could not load acceptance weights from %s", cfg.cCCDB_NUA.value.c_str()); else - LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + LOGF(info, "Loaded acceptance weights from %s", cfg.cCCDB_NUA.value.c_str()); } else { - LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); + LOGF(info, "cfg.cCCDB_NUA empty! No corrections loaded"); } - } else if (cfgUseNUA2D) { - if (cfgCCDB_NUA.value.empty() == false) { - TH3D* hNUA2D = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); + } else if (cfg.cUseNUA2D) { + if (cfg.cCCDB_NUA.value.empty() == false) { + TH3D* hNUA2D = ccdb->getForTimeStamp(cfg.cCCDB_NUA, timestamp); if (!hNUA2D) { - LOGF(fatal, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + LOGF(fatal, "Could not load acceptance weights from %s", cfg.cCCDB_NUA.value.c_str()); } else { - LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); - cfg.mAcceptance2D.push_back(hNUA2D); + LOGF(info, "Loaded acceptance weights from %s", cfg.cCCDB_NUA.value.c_str()); + conf.mAcceptance2D.push_back(hNUA2D); } } else { - LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); + LOGF(info, "cfg.cCCDB_NUA empty! No corrections loaded"); } } // Get Efficiency correction - if (cfgCCDB_NUE.value.empty() == false) { - TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUE, timestamp); - cfg.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); - cfg.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); - cfg.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); - int sizeEff = cfg.mEfficiency.size(); + if (cfg.cCCDB_NUE.value.empty() == false) { + TList* listCorrections = ccdb->getForTimeStamp(cfg.cCCDB_NUE, timestamp); + conf.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); + conf.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); + conf.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); + int sizeEff = conf.mEfficiency.size(); if (sizeEff < nWeights) - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCCDB_NUE.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfg.cCCDB_NUE.value.c_str()); else - LOGF(info, "Loaded efficiency histogram from %s", cfgCCDB_NUE.value.c_str()); + LOGF(info, "Loaded efficiency histogram from %s", cfg.cCCDB_NUE.value.c_str()); } else { - LOGF(info, "cfgCCDB_NUE empty! No corrections loaded"); + LOGF(info, "cfg.cCCDB_NUE empty! No corrections loaded"); } // Get Efficiency correction - if (cfgCCDB_NUE2D.value.empty() == false) { - TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUE2D, timestamp); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); - int sizeEff = cfg.mEfficiency2D.size(); + if (cfg.cCCDB_NUE2D.value.empty() == false) { + TList* listCorrections = ccdb->getForTimeStamp(cfg.cCCDB_NUE2D, timestamp); + conf.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); + conf.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); + conf.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); + int sizeEff = conf.mEfficiency2D.size(); + if (sizeEff < nWeights) + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfg.cCCDB_NUE.value.c_str()); + else + LOGF(info, "Loaded efficiency histogram from %s", cfg.cCCDB_NUE.value.c_str()); + } else { + LOGF(info, "cfg.cCCDB_NUE2 empty! No corrections loaded"); + } + + if (cfg.cCCDB_NUE3D.value.empty() == false) { + TList* listCorrections = ccdb->getForTimeStamp(cfg.cCCDB_NUE3D, timestamp); + conf.mEfficiency3D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); + conf.mEfficiency3D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); + conf.mEfficiency3D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); + int sizeEff = conf.mEfficiency3D.size(); if (sizeEff < nWeights) - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCCDB_NUE.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfg.cCCDB_NUE.value.c_str()); else - LOGF(info, "Loaded efficiency histogram from %s", cfgCCDB_NUE.value.c_str()); + LOGF(info, "Loaded efficiency histogram from %s", cfg.cCCDB_NUE.value.c_str()); } else { - LOGF(info, "cfgCCDB_NUE2 empty! No corrections loaded"); + LOGF(info, "cfg.cCCDB_NUE2 empty! No corrections loaded"); } - cfg.correctionsLoaded = true; + conf.correctionsLoaded = true; } // From Generic Framework bool setCurrentParticleWeights(int pID, int spec, const float& phi, const float& eta, const float& pt, const float& vtxz, const float& centrality) { float eff = 1.; - int sizeEff = cfg.mEfficiency.size(); + int sizeEff = conf.mEfficiency.size(); if (sizeEff > pID) { - if (cfgUseNUE2D) { + if (cfg.cUseNUE3D) { + int binx = conf.mEfficiency3D[pID]->GetXaxis()->FindBin(pt); + int biny = conf.mEfficiency3D[pID]->GetYaxis()->FindBin(eta); + int binz = conf.mEfficiency3D[pID]->GetZaxis()->FindBin(centrality); + eff = conf.mEfficiency3D[pID]->GetBinContent(binx, biny, binz); + } else if (cfg.cUseNUE2D) { int binx; int biny; - if (cfgUseNUE2Deta) { - biny = cfg.mEfficiency2D[pID]->GetYaxis()->FindBin(pt); - binx = cfg.mEfficiency2D[pID]->GetXaxis()->FindBin(eta); + if (cfg.cUseNUE2Deta) { + biny = conf.mEfficiency2D[pID]->GetYaxis()->FindBin(pt); + binx = conf.mEfficiency2D[pID]->GetXaxis()->FindBin(eta); } else { - binx = cfg.mEfficiency2D[pID]->GetXaxis()->FindBin(pt); - biny = cfg.mEfficiency2D[pID]->GetYaxis()->FindBin(centrality); + binx = conf.mEfficiency2D[pID]->GetXaxis()->FindBin(pt); + biny = conf.mEfficiency2D[pID]->GetYaxis()->FindBin(centrality); } - eff = cfg.mEfficiency2D[pID]->GetBinContent(binx, biny); + eff = conf.mEfficiency2D[pID]->GetBinContent(binx, biny); } else { - eff = cfg.mEfficiency[pID]->GetBinContent(cfg.mEfficiency[pID]->FindBin(pt)); + eff = conf.mEfficiency[pID]->GetBinContent(conf.mEfficiency[pID]->FindBin(pt)); } } else { eff = 1.0; @@ -874,16 +907,16 @@ struct FlowSP { spm.weff[pID][spec] = 1. / eff; - if (cfgUseNUA1D) { - int sizeAcc = cfg.mAcceptance.size(); + if (cfg.cUseNUA1D) { + int sizeAcc = conf.mAcceptance.size(); if (sizeAcc > pID) { - spm.wacc[pID][spec] = cfg.mAcceptance[pID]->getNUA(phi, eta, vtxz); + spm.wacc[pID][spec] = conf.mAcceptance[pID]->getNUA(phi, eta, vtxz); } else { spm.wacc[pID][spec] = 1; } - } else if (cfgUseNUA2D) { - if (cfg.mAcceptance2D.size() > 0) { - spm.wacc[pID][spec] = getNUA2D(cfg.mAcceptance2D[0], eta, phi, vtxz); + } else if (cfg.cUseNUA2D) { + if (conf.mAcceptance2D.size() > 0) { + spm.wacc[pID][spec] = getNUA2D(conf.mAcceptance2D[0], eta, phi, vtxz); } else { spm.wacc[pID][spec] = 1; } @@ -898,20 +931,20 @@ struct FlowSP { return 0; histos.fill(HIST("hEventCount"), evSel_sel8); - if (rctFlags.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) + if (cfg.cEvtUseRCTFlagChecker && !rctChecker(collision)) return 0; histos.fill(HIST("hEventCount"), evSel_RCTFlagsZDC); // Occupancy - if (cfgEvSelsDoOccupancySel) { + if (cfg.cEvSelsDoOccupancySel) { auto occupancy = collision.trackOccupancyInTimeRange(); - if (occupancy > cfgEvSelsMaxOccupancy || occupancy < cfgEvSelsMinOccupancy) { + if (occupancy > cfg.cEvSelsMaxOccupancy || occupancy < cfg.cEvSelsMinOccupancy) { return 0; } histos.fill(HIST("hEventCount"), evSel_occupancy); } - if (cfgEvSelsNoSameBunchPileupCut) { + if (cfg.cEvSelsNoSameBunchPileupCut) { if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof @@ -919,7 +952,7 @@ struct FlowSP { } histos.fill(HIST("hEventCount"), evSel_kNoSameBunchPileup); } - if (cfgEvSelsIsGoodZvtxFT0vsPV) { + if (cfg.cEvSelsIsGoodZvtxFT0vsPV) { if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference // use this cut at low multiplicities with caution @@ -927,21 +960,21 @@ struct FlowSP { } histos.fill(HIST("hEventCount"), evSel_kIsGoodZvtxFT0vsPV); } - if (cfgEvSelsNoCollInTimeRangeStandard) { + if (cfg.cEvSelsNoCollInTimeRangeStandard) { if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // Rejection of the collisions which have other events nearby return 0; } histos.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeStandard); } - if (cfgEvSelsNoCollInTimeRangeNarrow) { + if (cfg.cEvSelsNoCollInTimeRangeNarrow) { if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { // Rejection of the collisions which have other events nearby return 0; } histos.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeNarrow); } - if (cfgEvSelsIsVertexITSTPC) { + if (cfg.cEvSelsIsVertexITSTPC) { if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { // selects collisions with at least one ITS-TPC track, and thus rejects vertices built from ITS-only tracks return 0; @@ -949,7 +982,7 @@ struct FlowSP { histos.fill(HIST("hEventCount"), evSel_kIsVertexITSTPC); } - if (cfgEvSelsIsGoodITSLayersAll) { + if (cfg.cEvSelsIsGoodITSLayersAll) { if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { // New event selection bits to cut time intervals with dead ITS staves // https://indico.cern.ch/event/1493023/ (09-01-2025) @@ -957,14 +990,14 @@ struct FlowSP { } histos.fill(HIST("hEventCount"), evSel_kIsGoodITSLayersAll); } - if (cfgEvSelsIsGoodITSLayer0123) { + if (cfg.cEvSelsIsGoodITSLayer0123) { if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { return 0; } histos.fill(HIST("hEventCount"), evSel_kIsGoodITSLayer0123); } - if (cfgEvSelsUseAdditionalEventCut) { + if (cfg.cEvSelsUseAdditionalEventCut) { float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); @@ -977,7 +1010,7 @@ struct FlowSP { auto multNTracksPV = collision.multNTracksPV(); - if (vtxz > cfgEvSelsVtxZ || vtxz < -cfgEvSelsVtxZ) + if (vtxz > cfg.cEvSelsVtxZ || vtxz < -cfg.cEvSelsVtxZ) return 0; if (multNTracksPV < fMultPVCutLow->Eval(collision.centFT0C())) return 0; @@ -997,33 +1030,33 @@ struct FlowSP { template bool trackSelected(TrackObject track, const int& field) { - if (std::fabs(track.eta()) > cfgTrackSelsEta) + if (std::fabs(track.eta()) > cfg.cTrackSelsEta) return false; histos.fill(HIST("hTrackCount"), trackSel_Eta); - if (track.pt() < cfgTrackSelsPtmin || track.pt() > cfgTrackSelsPtmax) + if (track.pt() < cfg.cTrackSelsPtmin || track.pt() > cfg.cTrackSelsPtmax) return false; histos.fill(HIST("hTrackCount"), trackSel_Pt); - if (track.dcaXY() > cfgTrackSelsDCAxy) + if (track.dcaXY() > cfg.cTrackSelsDCAxy) return false; histos.fill(HIST("hTrackCount"), trackSel_DCAxy); - if (track.dcaZ() > cfgTrackSelsDCAz) + if (track.dcaZ() > cfg.cTrackSelsDCAz) return false; - if (cfgTrackSelsDoDCApt && std::fabs(track.dcaZ()) > (cfgTrackSelsDCAptConsMin + (cfgTrackSelsDCApt1 * cfgTrackSelsDCApt2) / (std::pow(track.pt(), 1.1)))) + if (cfg.cTrackSelsDoDCApt && std::fabs(track.dcaZ()) > (cfg.cTrackSelsDCAptConsMin + (cfg.cTrackSelsDCApt1 * cfg.cTrackSelsDCApt2) / (std::pow(track.pt(), 1.1)))) return false; histos.fill(HIST("hTrackCount"), trackSel_DCAz); - if (track.tpcNClsCrossedRows() < cfgTrackSelsNcls) + if (track.tpcNClsCrossedRows() < cfg.cTrackSelsNcls) return false; histos.fill(HIST("hTrackCount"), trackSel_NCls); - if (track.tpcFractionSharedCls() > cfgTrackSelsFshcls) + if (track.tpcFractionSharedCls() > cfg.cTrackSelsFshcls) return false; histos.fill(HIST("hTrackCount"), trackSel_FshCls); @@ -1037,14 +1070,14 @@ struct FlowSP { phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle phimodn = fmod(phimodn, o2::constants::math::PI / 9.0); - if (cfgFillTrackQA && cfgFillQABefore) + if (cfg.cFillTrackQA && cfg.cFillQABefore) histos.fill(HIST("incl/QA/before/pt_phi"), track.pt(), phimodn); - if (cfgTrackSelsUseAdditionalTrackCut) { + if (cfg.cTrackSelsUseAdditionalTrackCut) { if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt())) return false; // reject track } - if (cfgFillTrackQA) + if (cfg.cFillTrackQA) histos.fill(HIST("incl/QA/after/pt_phi"), track.pt(), phimodn); histos.fill(HIST("hTrackCount"), trackSel_TPCBoundary); return true; @@ -1053,7 +1086,7 @@ struct FlowSP { template inline void fillEventQA(CollisionObject collision, TracksObject tracks) { - if (!cfgFillEventQA) + if (!cfg.cFillEventQA) return; static constexpr std::string_view Time[] = {"before", "after"}; @@ -1074,7 +1107,7 @@ struct FlowSP { histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/CentFT0C_vs_CentFV0A"), collision.centFT0C(), collision.centFV0A(), spm.centWeight); histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/CentFT0C_vs_CentNGlobal"), collision.centFT0C(), collision.centNGlobal(), spm.centWeight); - if (cfgFillEventPlaneQA) { + if (cfg.cFillEventPlaneQA) { if constexpr (o2::framework::has_type_v) { double psiA = 1.0 * std::atan2(collision.qyA(), collision.qxA()); double psiC = 1.0 * std::atan2(collision.qyC(), collision.qxC()); @@ -1107,64 +1140,68 @@ struct FlowSP { if (track.eta() < 0) scale = -1.0; - if (cfgFillGeneralV1Histos) { + if (cfg.cFillGeneralV1Histos) { registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnAodd"), track.pt(), track.eta(), spm.centrality, scale * (spm.uy * spm.qyA + spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCodd"), track.pt(), track.eta(), spm.centrality, scale * (spm.uy * spm.qyC + spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQ)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnOdd"), track.pt(), track.eta(), spm.centrality, scale * 0.5 * ((spm.uy * spm.qyA + spm.ux * spm.qxA) - (spm.uy * spm.qyC + spm.ux * spm.qxC)) / std::sqrt(std::fabs(spm.corrQQ)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnEven"), track.pt(), track.eta(), spm.centrality, 0.5 * ((spm.uy * spm.qyA + spm.ux * spm.qxA) + (spm.uy * spm.qyC + spm.ux * spm.qxC)) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnA"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyA + spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnC"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyC + spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCSetPlane"), track.pt(), track.eta(), spm.centrality, (spm.uy + spm.ux) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnASetPlane"), track.pt(), track.eta(), spm.centrality, (minusQ * spm.ux - spm.uy) / std::sqrt(std::fabs(spm.corrQQ)), weight); } - if (cfgFillMixedHarmonics) { + if (cfg.cFillMixedHarmonics) { registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("MH/vnAxCxUx_MH"), track.pt(), track.eta(), spm.centrality, (spm.uxMH * spm.qxA * spm.qxC) / spm.corrQQx, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("MH/vnAyCyUx_MH"), track.pt(), track.eta(), spm.centrality, (spm.uxMH * spm.qyA * spm.qyC) / spm.corrQQy, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("MH/vnAxCyUy_MH"), track.pt(), track.eta(), spm.centrality, (spm.uyMH * spm.qxA * spm.qyC) / spm.corrQQx, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("MH/vnAyCxUy_MH"), track.pt(), track.eta(), spm.centrality, (spm.uyMH * spm.qyA * spm.qxC) / spm.corrQQy, weight); } - if (cfgFillXandYterms) { + if (cfg.cFillXandYterms) { registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnAx"), track.pt(), track.eta(), spm.centrality, (spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQx)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnAy"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyA) / std::sqrt(std::fabs(spm.corrQQy)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCx"), track.pt(), track.eta(), spm.centrality, (spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQx)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCy"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyC) / std::sqrt(std::fabs(spm.corrQQy)), weight); } - if (cfgFillEventPlane) { // only fill for inclusive! + if (cfg.cFillEventPlane) { // only fill for inclusive! registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnA_EP"), track.pt(), track.eta(), spm.centrality, spm.vnA, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnC_EP"), track.pt(), track.eta(), spm.centrality, spm.vnC, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnFull_EP"), track.pt(), track.eta(), spm.centrality, spm.vnFull, weight); } - if (cfgFillMeanPT) { - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtEtaCent"), track.eta(), spm.centrality, track.pt(), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtCent"), spm.centrality, track.pt(), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); - - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Aodd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Codd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); - + if (cfg.cFillMeanPT) { registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3D"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3D"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); + if (cfg.cFillMeanPTextra) { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtEtaCent"), track.eta(), spm.centrality, track.pt(), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtCent"), spm.centrality, track.pt(), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Aodd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Codd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); + } } } template inline void fillTrackQA(TrackObject track) { - if (!cfgFillTrackQA) + if (!cfg.cFillTrackQA) return; static constexpr std::string_view Time[] = {"before/", "after/"}; - // NOTE: species[kUnidentified] = "" (when nocfgTrackSelDo) { - if (cfgTrackSelDoTrackQAvsCent) { + // NOTE: species[kUnidentified] = "" (when nocfg.cTrackSelDo) { + if (cfg.cTrackSelDoTrackQAvsCent) { histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_Eta"), track.pt(), track.eta(), spm.centrality, spm.wacc[ct][par] * spm.weff[ct][par]); histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_Eta_uncorrected"), track.pt(), track.eta(), spm.centrality); histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta"), track.phi(), track.eta(), spm.centrality, spm.wacc[ct][par] * spm.weff[ct][par]); @@ -1187,7 +1224,7 @@ struct FlowSP { template inline void fillPIDQA(TrackObject track) { - if (!cfgFillTrackQA) + if (!cfg.cFillTrackQA) return; if constexpr (framework::has_type_v) { histos.fill(HIST(Charge[ct]) + HIST("pion/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaPi()); @@ -1238,15 +1275,15 @@ struct FlowSP { } } - template + template inline void fillPrimaryHistos(McParticleObject mcparticle) { static constexpr std::string_view Time[] = {"/before", "/after"}; if (!mcparticle.isPhysicalPrimary()) { - registry.fill(HIST("trackMCReco") + HIST(Time[ft]) + HIST("/hIsPhysicalPrimary"), 0, spm.centrality); + registry.fill(HIST("trackMCReco") + HIST(Time[ft]) + HIST("/") + HIST(Charge[ct]) + HIST("hIsPhysicalPrimary"), 0, spm.centrality, mcparticle.pt()); } else { - registry.fill(HIST("trackMCReco") + HIST(Time[ft]) + HIST("/hIsPhysicalPrimary"), 1, spm.centrality); + registry.fill(HIST("trackMCReco") + HIST(Time[ft]) + HIST("/") + HIST(Charge[ct]) + HIST("hIsPhysicalPrimary"), 1, spm.centrality, mcparticle.pt()); } } @@ -1256,7 +1293,7 @@ struct FlowSP { fillTrackQA(track); fillPIDQA(track); - if (cfgFillChargeDependenceQA) { + if (cfg.cFillChargeDependenceQA) { switch (spm.charge) { case kPositive: { fillTrackQA(track); @@ -1278,30 +1315,30 @@ struct FlowSP { histos.fill(HIST("hEventCount"), evSel_FilteredEvent); auto bc = collision.bc_as(); int standardMagField = 99999; - auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; - - if (bc.runNumber() != cfg.lastRunNumber) { - cfg.correctionsLoaded = false; - cfg.clCentrality = false; - cfg.lastRunNumber = bc.runNumber(); - cfg.mAcceptance.clear(); - LOGF(info, "Size of mAcceptance: %i (should be 0)", (int)cfg.mAcceptance.size()); + auto field = (cfg.cMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfg.cMagField; + + if (bc.runNumber() != conf.lastRunNumber) { + conf.correctionsLoaded = false; + conf.clCentrality = false; + conf.lastRunNumber = bc.runNumber(); + conf.mAcceptance.clear(); + LOGF(info, "Size of mAcceptance: %i (should be 0)", (int)conf.mAcceptance.size()); } - if (cfgFillQABefore) + if (cfg.cFillQABefore) fillEventQA(collision, tracks); loadCorrections(bc.timestamp()); spm.centrality = collision.centFT0C(); - if (cfgCentFT0Cvariant1) + if (cfg.cCentFT0Cvariant1) spm.centrality = collision.centFT0CVariant1(); - if (cfgCentFT0M) + if (cfg.cCentFT0M) spm.centrality = collision.centFT0M(); - if (cfgCentFV0A) + if (cfg.cCentFV0A) spm.centrality = collision.centFV0A(); - if (cfgCentNGlobal) + if (cfg.cCentNGlobal) spm.centrality = collision.centNGlobal(); if (!eventSelected(collision, tracks.size())) @@ -1336,10 +1373,10 @@ struct FlowSP { registry.fill(HIST("QQCorrelations/qAqCX"), spm.centrality, spm.qxA * spm.qxC); registry.fill(HIST("QQCorrelations/qAqCY"), spm.centrality, spm.qyA * spm.qyC); - if (cfgFillEventQA) { + if (cfg.cFillEventQA) { histos.fill(HIST("QA/hCentFull"), spm.centrality, 1); } - if (cfgFillEventPlaneQA) { + if (cfg.cFillEventPlaneQA) { histos.fill(HIST("QA/hSPplaneA"), spm.psiA, 1); histos.fill(HIST("QA/hSPplaneC"), spm.psiC, 1); histos.fill(HIST("QA/hSPplaneFull"), spm.psiFull, 1); @@ -1350,7 +1387,7 @@ struct FlowSP { histos.fill(HIST("QA/hFullEvPlaneRes"), spm.centrality, -1 * std::cos(spm.psiA - spm.psiC)); } - if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) + if (spm.centrality > cfg.cCentMax || spm.centrality < cfg.cCentMin) return; histos.fill(HIST("hEventCount"), evSel_CentCuts); @@ -1359,38 +1396,38 @@ struct FlowSP { // Only load once! // If not loaded set to 1 - if (cfgCCDBdir_QQ.value.empty() == false) { - if (!cfg.clQQ) { - TList* hcorrList = ccdb->getForTimeStamp(cfgCCDBdir_QQ.value, bc.timestamp()); - cfg.hcorrQQ = reinterpret_cast(hcorrList->FindObject("qAqCXY")); - cfg.hcorrQQx = reinterpret_cast(hcorrList->FindObject("qAqCX")); - cfg.hcorrQQy = reinterpret_cast(hcorrList->FindObject("qAqCY")); - cfg.clQQ = true; + if (cfg.cCCDBdir_QQ.value.empty() == false) { + if (!conf.clQQ) { + TList* hcorrList = ccdb->getForTimeStamp(cfg.cCCDBdir_QQ.value, bc.timestamp()); + conf.hcorrQQ = reinterpret_cast(hcorrList->FindObject("qAqCXY")); + conf.hcorrQQx = reinterpret_cast(hcorrList->FindObject("qAqCX")); + conf.hcorrQQy = reinterpret_cast(hcorrList->FindObject("qAqCY")); + conf.clQQ = true; } - spm.corrQQ = cfg.hcorrQQ->GetBinContent(cfg.hcorrQQ->FindBin(spm.centrality)); - spm.corrQQx = cfg.hcorrQQx->GetBinContent(cfg.hcorrQQx->FindBin(spm.centrality)); - spm.corrQQy = cfg.hcorrQQy->GetBinContent(cfg.hcorrQQy->FindBin(spm.centrality)); + spm.corrQQ = conf.hcorrQQ->GetBinContent(conf.hcorrQQ->FindBin(spm.centrality)); + spm.corrQQx = conf.hcorrQQx->GetBinContent(conf.hcorrQQx->FindBin(spm.centrality)); + spm.corrQQy = conf.hcorrQQy->GetBinContent(conf.hcorrQQy->FindBin(spm.centrality)); } double evPlaneRes = 1.; - if (cfgCCDBdir_SP.value.empty() == false) { - if (!cfg.clEvPlaneRes) { - cfg.hEvPlaneRes = ccdb->getForTimeStamp(cfgCCDBdir_SP.value, bc.timestamp()); - cfg.clEvPlaneRes = true; + if (cfg.cCCDBdir_SP.value.empty() == false) { + if (!conf.clEvPlaneRes) { + conf.hEvPlaneRes = ccdb->getForTimeStamp(cfg.cCCDBdir_SP.value, bc.timestamp()); + conf.clEvPlaneRes = true; } - evPlaneRes = cfg.hEvPlaneRes->GetBinContent(cfg.hEvPlaneRes->FindBin(spm.centrality)); + evPlaneRes = conf.hEvPlaneRes->GetBinContent(conf.hEvPlaneRes->FindBin(spm.centrality)); if (evPlaneRes < 0) LOGF(fatal, " > 0 for centrality %.2f! Cannot determine resolution.. Change centrality ranges!!!", spm.centrality); evPlaneRes = std::sqrt(evPlaneRes); } spm.centWeight = 1.; - if (cfgCCDBdir_centrality.value.empty() == false) { - if (!cfg.clCentrality) { - cfg.hCentrality = ccdb->getForTimeStamp(cfgCCDBdir_centrality.value, bc.timestamp()); - cfg.clCentrality = true; + if (cfg.cCCDBdir_centrality.value.empty() == false) { + if (!conf.clCentrality) { + conf.hCentrality = ccdb->getForTimeStamp(cfg.cCCDBdir_centrality.value, bc.timestamp()); + conf.clCentrality = true; } - double centW = cfg.hCentrality->GetBinContent(cfg.hCentrality->FindBin(spm.centrality)); + double centW = conf.hCentrality->GetBinContent(conf.hCentrality->FindBin(spm.centrality)); if (centW < 0) { spm.centWeight = 0.; LOGF(fatal, "Centrality weight cannot be negative .. setting to 0. for (%.2f)", spm.centrality); @@ -1425,7 +1462,7 @@ struct FlowSP { spm.charge = ((track.sign() > 0)) ? kPositive : kNegative; - if (cfgFillQABefore) { + if (cfg.cFillQABefore) { fillAllQA(track); } @@ -1433,14 +1470,14 @@ struct FlowSP { continue; spm.meanPtWeight = 1.0; - if (cfgCCDBdir_meanPt.value.empty() == false) { - if (!cfg.clMeanPt) { - cfg.hMeanPt = ccdb->getForTimeStamp(cfgCCDBdir_meanPt.value, bc.timestamp()); - cfg.clMeanPt = true; + if (cfg.cCCDBdir_meanPt.value.empty() == false) { + if (!conf.clMeanPt) { + conf.hMeanPt = ccdb->getForTimeStamp(cfg.cCCDBdir_meanPt.value, bc.timestamp()); + conf.clMeanPt = true; } - int etaBin = cfg.hMeanPt->GetXaxis()->FindBin(track.eta()); - int centBin = cfg.hMeanPt->GetYaxis()->FindBin(spm.centrality); - double weight = cfg.hMeanPt->GetBinContent(etaBin, centBin); + int etaBin = conf.hMeanPt->GetXaxis()->FindBin(track.eta()); + int centBin = conf.hMeanPt->GetYaxis()->FindBin(spm.centrality); + double weight = conf.hMeanPt->GetBinContent(etaBin, centBin); if (weight > 0) { spm.meanPtWeight = 1.0 / weight; } else { @@ -1454,15 +1491,15 @@ struct FlowSP { // Fill NUA weights (last 0 is for Data see GFWWeights class (not a weight)) // ToDo: Add pi, ka, proton here! - if (cfgFillWeights) { + if (cfg.cFillWeights) { fWeights->fill(phi, track.eta(), spm.vz, track.pt(), spm.centrality, 0); registry.fill(HIST("weights2D/hPhi_Eta_vz"), phi, track.eta(), spm.vz, 1); } - if (cfgFillWeightsPOS && spm.charge == kPositive) { + if (cfg.cFillWeightsPOS && spm.charge == kPositive) { fWeightsPOS->fill(phi, track.eta(), spm.vz, track.pt(), spm.centrality, 0); registry.fill(HIST("weights2D/hPhi_Eta_vz_positive"), phi, track.eta(), spm.vz, 1); } - if (cfgFillWeightsNEG && spm.charge == kNegative) { + if (cfg.cFillWeightsNEG && spm.charge == kNegative) { fWeightsNEG->fill(phi, track.eta(), spm.vz, track.pt(), spm.centrality, 0); registry.fill(HIST("weights2D/hPhi_Eta_vz_negative"), phi, track.eta(), spm.vz, 1); } @@ -1478,16 +1515,16 @@ struct FlowSP { fillAllQA(track); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.ux = std::cos(cfgHarm * phi); - spm.uy = std::sin(cfgHarm * phi); + spm.ux = std::cos(cfg.cHarm * phi); + spm.uy = std::sin(cfg.cHarm * phi); - spm.uxMH = std::cos(cfgHarmMixed * phi); - spm.uyMH = std::sin(cfgHarmMixed * phi); + spm.uxMH = std::cos(cfg.cHarmMixed * phi); + spm.uyMH = std::sin(cfg.cHarmMixed * phi); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.vnA = std::cos(cfgHarm * (phi - spm.psiA)) / evPlaneRes; - spm.vnC = std::cos(cfgHarm * (phi - spm.psiC)) / evPlaneRes; - spm.vnFull = std::cos(cfgHarm * (phi - spm.psiFull)) / evPlaneRes; + spm.vnA = std::cos(cfg.cHarm * (phi - spm.psiA)) / evPlaneRes; + spm.vnC = std::cos(cfg.cHarm * (phi - spm.psiC)) / evPlaneRes; + spm.vnFull = std::cos(cfg.cHarm * (phi - spm.psiFull)) / evPlaneRes; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1496,7 +1533,7 @@ struct FlowSP { fillHistograms(track); - if (cfgFillChargeDependence) { + if (cfg.cFillChargeDependence) { switch (spm.charge) { case kPositive: fillHistograms(track); @@ -1539,14 +1576,14 @@ struct FlowSP { double meanPxAEvent = sumPxAEvent / meanPxEventCount; double meanPxCEvent = sumPxCEvent / meanPxEventCount; - if (cfgFillMeanPT) { + if (cfg.cFillMeanPTextra) { registry.fill(HIST("incl/meanPT/meanPxA"), spm.centrality, spm.psiA - spm.psiC, meanPxAEvent); registry.fill(HIST("incl/meanPT/meanPxC"), spm.centrality, spm.psiA - spm.psiC, meanPxCEvent); } // Now we want to fill the final relPt histogram // Loop over all eta and fill bins - if (cfgFillMeanPT) { + if (cfg.cFillMeanPTextra) { int nBinsEta = 8; for (int etabin = 1; etabin <= nBinsEta; etabin++) { // eta bin is 1 --> Find centbin!! @@ -1567,7 +1604,7 @@ struct FlowSP { registry.fill(HIST("incl/meanPT/meanRelPtA"), eta, spm.centrality, drelPxA / meanPt, spm.centWeight); registry.fill(HIST("incl/meanPT/meanRelPtC"), eta, spm.centrality, drelPxC / meanPt, spm.centWeight); - if (cfgFillChargeDependence) { + if (cfg.cFillChargeDependence) { registry.fill(HIST("neg/meanPT/meanRelPtA"), eta, spm.centrality, drelPxANeg / meanPtNeg, spm.centWeight); registry.fill(HIST("pos/meanPT/meanRelPtA"), eta, spm.centrality, drelPxAPos / meanPtPos, spm.centWeight); registry.fill(HIST("neg/meanPT/meanRelPtC"), eta, spm.centrality, drelPxCNeg / meanPtNeg, spm.centWeight); @@ -1596,30 +1633,30 @@ struct FlowSP { histos.fill(HIST("hEventCount"), evSel_FilteredEvent); auto bc = collision.bc_as(); int standardMagField = 99999; - auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; - - if (bc.runNumber() != cfg.lastRunNumber) { - cfg.correctionsLoaded = false; - cfg.clCentrality = false; - cfg.lastRunNumber = bc.runNumber(); - cfg.mAcceptance.clear(); - LOGF(info, "Size of mAcceptance: %i (should be 0)", (int)cfg.mAcceptance.size()); + auto field = (cfg.cMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfg.cMagField; + + if (bc.runNumber() != conf.lastRunNumber) { + conf.correctionsLoaded = false; + conf.clCentrality = false; + conf.lastRunNumber = bc.runNumber(); + conf.mAcceptance.clear(); + LOGF(info, "Size of mAcceptance: %i (should be 0)", (int)conf.mAcceptance.size()); } - if (cfgFillQABefore) + if (cfg.cFillQABefore) fillEventQA(collision, tracks); loadCorrections(bc.timestamp()); spm.centrality = collision.centFT0C(); - if (cfgCentFT0Cvariant1) + if (cfg.cCentFT0Cvariant1) spm.centrality = collision.centFT0CVariant1(); - if (cfgCentFT0M) + if (cfg.cCentFT0M) spm.centrality = collision.centFT0M(); - if (cfgCentFV0A) + if (cfg.cCentFV0A) spm.centrality = collision.centFV0A(); - if (cfgCentNGlobal) + if (cfg.cCentNGlobal) spm.centrality = collision.centNGlobal(); if (!eventSelected(collision, tracks.size())) @@ -1645,45 +1682,45 @@ struct FlowSP { // https://twiki.cern.ch/twiki/pub/ALICE/DirectedFlowAnalysisNote/vn_ZDC_ALICE_INT_NOTE_version02.pdf spm.psiFull = 1.0 * std::atan2(spm.qyA + spm.qyC, spm.qxA + spm.qxC); - if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) + if (spm.centrality > cfg.cCentMax || spm.centrality < cfg.cCentMin) return; // Load correlations and SP resolution needed for Scalar Product and event plane methods. // Only load once! // If not loaded set to 1 - if (cfgCCDBdir_QQ.value.empty() == false) { - if (!cfg.clQQ) { - TList* hcorrList = ccdb->getForTimeStamp(cfgCCDBdir_QQ.value, bc.timestamp()); - cfg.hcorrQQ = reinterpret_cast(hcorrList->FindObject("qAqCXY")); - cfg.hcorrQQx = reinterpret_cast(hcorrList->FindObject("qAqCX")); - cfg.hcorrQQy = reinterpret_cast(hcorrList->FindObject("qAqCY")); - cfg.clQQ = true; + if (cfg.cCCDBdir_QQ.value.empty() == false) { + if (!conf.clQQ) { + TList* hcorrList = ccdb->getForTimeStamp(cfg.cCCDBdir_QQ.value, bc.timestamp()); + conf.hcorrQQ = reinterpret_cast(hcorrList->FindObject("qAqCXY")); + conf.hcorrQQx = reinterpret_cast(hcorrList->FindObject("qAqCX")); + conf.hcorrQQy = reinterpret_cast(hcorrList->FindObject("qAqCY")); + conf.clQQ = true; } - spm.corrQQ = cfg.hcorrQQ->GetBinContent(cfg.hcorrQQ->FindBin(spm.centrality)); - spm.corrQQx = cfg.hcorrQQx->GetBinContent(cfg.hcorrQQx->FindBin(spm.centrality)); - spm.corrQQy = cfg.hcorrQQy->GetBinContent(cfg.hcorrQQy->FindBin(spm.centrality)); + spm.corrQQ = conf.hcorrQQ->GetBinContent(conf.hcorrQQ->FindBin(spm.centrality)); + spm.corrQQx = conf.hcorrQQx->GetBinContent(conf.hcorrQQx->FindBin(spm.centrality)); + spm.corrQQy = conf.hcorrQQy->GetBinContent(conf.hcorrQQy->FindBin(spm.centrality)); } double evPlaneRes = 1.; - if (cfgCCDBdir_SP.value.empty() == false) { - if (!cfg.clEvPlaneRes) { - cfg.hEvPlaneRes = ccdb->getForTimeStamp(cfgCCDBdir_SP.value, bc.timestamp()); - cfg.clEvPlaneRes = true; + if (cfg.cCCDBdir_SP.value.empty() == false) { + if (!conf.clEvPlaneRes) { + conf.hEvPlaneRes = ccdb->getForTimeStamp(cfg.cCCDBdir_SP.value, bc.timestamp()); + conf.clEvPlaneRes = true; } - evPlaneRes = cfg.hEvPlaneRes->GetBinContent(cfg.hEvPlaneRes->FindBin(spm.centrality)); + evPlaneRes = conf.hEvPlaneRes->GetBinContent(conf.hEvPlaneRes->FindBin(spm.centrality)); if (evPlaneRes < 0) LOGF(fatal, " > 0 for centrality %.2f! Cannot determine resolution.. Change centrality ranges!!!", spm.centrality); evPlaneRes = std::sqrt(evPlaneRes); } spm.centWeight = 1.; - if (cfgCCDBdir_centrality.value.empty() == false) { - if (!cfg.clCentrality) { - cfg.hCentrality = ccdb->getForTimeStamp(cfgCCDBdir_centrality.value, bc.timestamp()); - cfg.clCentrality = true; + if (cfg.cCCDBdir_centrality.value.empty() == false) { + if (!conf.clCentrality) { + conf.hCentrality = ccdb->getForTimeStamp(cfg.cCCDBdir_centrality.value, bc.timestamp()); + conf.clCentrality = true; } - double centW = cfg.hCentrality->GetBinContent(cfg.hCentrality->FindBin(spm.centrality)); + double centW = conf.hCentrality->GetBinContent(conf.hCentrality->FindBin(spm.centrality)); if (centW < 0) { spm.centWeight = 1. / centW; } else { @@ -1696,7 +1733,7 @@ struct FlowSP { for (const auto& track : tracks) { - ParticleType trackPID = (cfgFillPID || cfgFillPIDQA) ? getTrackPID(track) : kUnidentified; + ParticleType trackPID = (cfg.cFillPID || cfg.cFillPIDQA) ? getTrackPID(track) : kUnidentified; histos.fill(HIST("hPIDcounts"), trackPID, track.pt()); @@ -1707,7 +1744,7 @@ struct FlowSP { spm.charge = ((track.sign() > 0)) ? kPositive : kNegative; - if (cfgFillQABefore) { + if (cfg.cFillQABefore) { switch (trackPID) { case kPions: fillAllQA(track); @@ -1744,16 +1781,16 @@ struct FlowSP { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.ux = std::cos(cfgHarm * phi); - spm.uy = std::sin(cfgHarm * phi); + spm.ux = std::cos(cfg.cHarm * phi); + spm.uy = std::sin(cfg.cHarm * phi); - spm.uxMH = std::cos(cfgHarmMixed * phi); - spm.uyMH = std::sin(cfgHarmMixed * phi); + spm.uxMH = std::cos(cfg.cHarmMixed * phi); + spm.uyMH = std::sin(cfg.cHarmMixed * phi); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.vnA = std::cos(cfgHarm * (phi - spm.psiA)) / evPlaneRes; - spm.vnC = std::cos(cfgHarm * (phi - spm.psiC)) / evPlaneRes; - spm.vnFull = std::cos(cfgHarm * (phi - spm.psiFull)) / evPlaneRes; + spm.vnA = std::cos(cfg.cHarm * (phi - spm.psiA)) / evPlaneRes; + spm.vnC = std::cos(cfg.cHarm * (phi - spm.psiC)) / evPlaneRes; + spm.vnFull = std::cos(cfg.cHarm * (phi - spm.psiFull)) / evPlaneRes; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1773,7 +1810,7 @@ struct FlowSP { break; } - if (cfgFillChargeDependence) { + if (cfg.cFillChargeDependence) { switch (spm.charge) { case kPositive: { switch (trackPID) { @@ -1818,26 +1855,26 @@ struct FlowSP { { auto bc = collision.template bc_as(); int standardMagField = 99999; - auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; + auto field = (cfg.cMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfg.cMagField; spm.vz = collision.posZ(); spm.centrality = collision.centFT0C(); - if (cfgCentFT0Cvariant1) + if (cfg.cCentFT0Cvariant1) spm.centrality = collision.centFT0CVariant1(); - if (cfgCentFT0M) + if (cfg.cCentFT0M) spm.centrality = collision.centFT0M(); - if (cfgCentFV0A) + if (cfg.cCentFV0A) spm.centrality = collision.centFV0A(); - if (cfgCentNGlobal) + if (cfg.cCentNGlobal) spm.centrality = collision.centNGlobal(); - if (cfgFillQABefore) + if (cfg.cFillQABefore) fillEventQA(collision, filteredTracks); if (!eventSelected(collision, filteredTracks.size())) return; - if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) + if (spm.centrality > cfg.cCentMax || spm.centrality < cfg.cCentMin) return; histos.fill(HIST("hEventCount"), evSel_CentCuts); @@ -1853,28 +1890,33 @@ struct FlowSP { registry.fill(HIST("trackMCReco/hTrackSize_Filtered"), filteredTracks.size(), spm.centrality); for (const auto& track : filteredTracks) { + + if (!track.has_mcParticle()) + continue; + auto mcParticle = track.mcParticle(); + if (track.sign() == 0.0) continue; histos.fill(HIST("hTrackCount"), trackSel_ZeroCharge); - fillMCPtHistos(track, mcParticle.pdgCode()); - fillPrimaryHistos(mcParticle); - - if (!mcParticle.isPhysicalPrimary()) - continue; + if (cfg.cFillWithMCParticle) { + fillMCPtHistos(mcParticle, mcParticle.pdgCode()); + } else { + fillMCPtHistos(track, mcParticle.pdgCode()); + } spm.charge = (track.sign() > 0) ? kPositive : kNegative; int minVal = 100; - if (cfgFilterLeptons && std::abs(mcParticle.pdgCode()) < minVal) { + if (cfg.cFilterLeptons && std::abs(mcParticle.pdgCode()) < minVal) { continue; } // This neglects PID (for now) later use getPID like in data. - if (cfgFillQABefore) { + if (cfg.cFillQABefore) { fillAllQA(track); - if (cfgFillPIDQA) { + if (cfg.cFillPIDQA) { switch (std::abs(mcParticle.pdgCode())) { case kPiPlus: fillAllQA(track); @@ -1889,14 +1931,34 @@ struct FlowSP { } } + fillPrimaryHistos(mcParticle); + if (spm.charge == kPositive) { + fillPrimaryHistos(mcParticle); + } else { + fillPrimaryHistos(mcParticle); + } + if (!trackSelected(track, field)) continue; - fillMCPtHistos(track, mcParticle.pdgCode()); + fillPrimaryHistos(mcParticle); + if (spm.charge == kPositive) { + fillPrimaryHistos(mcParticle); + } else { + fillPrimaryHistos(mcParticle); + } + if (!mcParticle.isPhysicalPrimary()) + continue; + + if (cfg.cFillWithMCParticle) { + fillMCPtHistos(mcParticle, mcParticle.pdgCode()); + } else { + fillMCPtHistos(track, mcParticle.pdgCode()); + } fillAllQA(track); - if (cfgFillPIDQA) { + if (cfg.cFillPIDQA) { switch (std::abs(mcParticle.pdgCode())) { case kPions: fillAllQA(track); @@ -1910,8 +1972,6 @@ struct FlowSP { } } - fillPrimaryHistos(mcParticle); - } // end of track loop } PROCESS_SWITCH(FlowSP, processMCReco, "Process analysis for MC reconstructed events", false); @@ -1940,16 +2000,16 @@ struct FlowSP { auto filteredTrackSlice = filteredTracks.sliceBy(trackPerCollision, col.globalIndex()); spm.centrality = col.centFT0C(); - if (cfgCentFT0Cvariant1) + if (cfg.cCentFT0Cvariant1) spm.centrality = col.centFT0CVariant1(); - if (cfgCentFT0M) + if (cfg.cCentFT0M) spm.centrality = col.centFT0M(); - if (cfgCentFV0A) + if (cfg.cCentFV0A) spm.centrality = col.centFV0A(); - if (cfgCentNGlobal) + if (cfg.cCentNGlobal) spm.centrality = col.centNGlobal(); - if (cfgFillQABefore) + if (cfg.cFillQABefore) fillEventQA(col, filteredTrackSlice); if (trackSlice.size() < 1) { @@ -1961,7 +2021,7 @@ struct FlowSP { continue; } - if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) { + if (spm.centrality > cfg.cCentMax || spm.centrality < cfg.cCentMin) { colSelected = false; continue; } @@ -1989,7 +2049,7 @@ struct FlowSP { spm.charge = (pdgInfo->Charge() > 0) ? kPositive : kNegative; int minVal = 100; - if (cfgFilterLeptons && std::abs(pdgCode) < minVal) { + if (cfg.cFilterLeptons && std::abs(pdgCode) < minVal) { continue; } @@ -2003,7 +2063,7 @@ struct FlowSP { registry.fill(HIST("trackMCGen/before/neg/phi_eta_vtxZ_gen"), particle.phi(), particle.eta(), vtxz); } - if (particle.eta() < -cfgTrackSelsEta || particle.eta() > cfgTrackSelsEta || particle.pt() < cfgTrackSelsPtmin || particle.pt() > cfgTrackSelsPtmax) + if (particle.eta() < -cfg.cTrackSelsEta || particle.eta() > cfg.cTrackSelsEta || particle.pt() < cfg.cTrackSelsPtmin || particle.pt() > cfg.cTrackSelsPtmax) continue; fillMCPtHistos(particle, pdgCode); From afd37702bd87880323593eed16c1cb43ad840b83 Mon Sep 17 00:00:00 2001 From: hernasab Date: Fri, 8 May 2026 10:06:09 -0500 Subject: [PATCH 100/449] =?UTF-8?q?[PWGCF]=20removed=20obsolete=20variable?= =?UTF-8?q?s=20and=20adjusted=20binning=20for=203d=20zdc=20and=20centra?= =?UTF-8?q?=E2=80=A6=20(#16136)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 1e4cfa7bbec..6d8e581ab84 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -61,7 +61,6 @@ struct FlowZdcTask { Configurable eventSelection{"eventSelection", 1, "event selection"}; Configurable maxZem{"maxZem", 3099.5, "Max ZEM signal"}; // for ZDC info and analysis - Configurable nBinsAmp{"nBinsAmp", 1025, "nbinsAmp"}; Configurable nBinsADC{"nBinsADC", 1000, "nbinsADC"}; Configurable maxZn{"maxZn", 125.5, "Max ZN signal"}; Configurable maxZp{"maxZp", 125.5, "Max ZP signal"}; @@ -70,9 +69,10 @@ struct FlowZdcTask { Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; Configurable maxAmpFT0{"maxAmpFT0", 2500, "Max FT0 amp"}; Configurable maxAmpFT0M{"maxAmpFT0M", 2500, "Max FT0M amp"}; - Configurable nBinsAmpFV0{"nBinsAmpFV0", 100, "N bins FV0 amp"}; - Configurable maxAmpFV0{"maxAmpFV0", 2000, "Max FV0 amp"}; + Configurable nBinsAmpFT0M{"nBinsAmpFT0M", 100, "N bins FT0M amp"}; Configurable nBinsZDC{"nBinsZDC", 400, "nBinsZDC"}; + Configurable nBinsZP{"nBinsZP", 50, "nBinsZP"}; + Configurable nBinsZN{"nBinsZN", 50, "nBinsZN"}; Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; Configurable maxNch{"maxNch", 2500, "Max Nch (|eta|<0.8)"}; Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; @@ -224,8 +224,8 @@ struct FlowZdcTask { histos.add("ZNCVsFT0C", ";T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0M", ";T0A+T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsCent", ";T0C cent;ZNC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZPAZNAVsFT0M", ";T0A+T0C (#times 1/100);ZPA Amplitude;ZNA Amplitude;", kTH3F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZPCZNCVsFT0M", ";T0A+T0C (#times 1/100);ZPC Amplitude;ZNC Amplitude;", kTH3F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZPAZNAVsFT0M", ";T0A+T0C (#times 1/100);ZPA Amplitude;ZNA Amplitude;", kTH3F, {{{nBinsAmpFT0M, 0., maxAmpFT0M}, {nBinsZP, -0.5, maxZp}, {nBinsZN, -0.5, maxZn}}}); + histos.add("ZPCZNCVsFT0M", ";T0A+T0C (#times 1/100);ZPC Amplitude;ZNC Amplitude;", kTH3F, {{{nBinsAmpFT0M, 0., maxAmpFT0M}, {nBinsZP, -0.5, maxZp}, {nBinsZN, -0.5, maxZn}}}); histos.add("ZPAVsFT0A", ";T0A (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0C", ";T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0M", ";T0A+T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); @@ -269,11 +269,9 @@ struct FlowZdcTask { histos.add("ampFT0C", ";T0C (#times 1/100);", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); histos.add("ampFT0A", ";T0A (#times 1/100);", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); histos.add("ampFT0M", ";T0A+T0C (#times 1/100);", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0M}}); - histos.add("ampFV0A", ";V0A (#times 1/100);", kTH1F, {{nBinsAmpFV0, 0., maxAmpFV0}}); histos.add("NchVsFT0C", ";T0C (#times 1/100, -3.3 < #eta < -2.1);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., 950.}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsFT0A", ";T0A (#times 1/100, 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); - histos.add("NchVsFV0A", ";V0A (#times 1/100, 2.2 < #eta < 5);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFV0, 0., maxAmpFV0}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsEt", ";#it{E}_{T} (|#eta|<0.8);#LTITS+TPC tracks#GT (|#eta|<0.8);", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsMeanPt", ";#it{N}_{ch} (|#eta|<0.8);#LT[#it{p}_{T}]#GT (|#eta|<0.8);", kTProfile, {{nBinsNch, minNch, maxNch}}); histos.add("NchVsNPV", ";#it{N}_{PV} (|#eta|<1);ITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{300, -0.5, 5999.5}, {nBinsNch, minNch, maxNch}}}); @@ -406,7 +404,7 @@ struct FlowZdcTask { return true; } - void processQA(ColEvSels::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FV0As const& /*fv0as*/, aod::FT0s const& /*ft0s*/, TheFilteredTracks const& tracks) + void processQA(ColEvSels::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FT0s const& /*ft0s*/, TheFilteredTracks const& tracks) { const auto& foundBC = collision.foundBC_as(); if (!isEventSelected(collision)) { @@ -419,7 +417,7 @@ struct FlowZdcTask { auto zdc = foundBC.zdc(); auto cent = collision.centFT0C(); - float aT0A = 0., aT0C = 0., aV0A = 0.; + float aT0A = 0., aT0C = 0.; if (foundBC.has_ft0()) { for (const auto& amplitude : foundBC.ft0().amplitudeA()) { aT0A += amplitude; @@ -429,11 +427,6 @@ struct FlowZdcTask { } } histos.fill(HIST("hEventCounter"), EvCutLabel::TZero); - if (foundBC.has_fv0a()) { - for (const auto& amplitude : foundBC.fv0a().amplitude()) { - aV0A += amplitude; - } - } const double normT0M{(aT0A + aT0C) / 100.}; float et = 0., meanpt = 0.; int itsTracks = 0, glbTracks = 0; @@ -507,9 +500,7 @@ struct FlowZdcTask { histos.fill(HIST("ampFT0C"), aT0C / 100.); histos.fill(HIST("ampFT0A"), aT0A / 100.); histos.fill(HIST("ampFT0M"), (aT0A + aT0C) / 100.); - histos.fill(HIST("ampFV0A"), aV0A / 100.); // charged particle correlations - histos.fill(HIST("NchVsFV0A"), aV0A / 100., glbTracks); histos.fill(HIST("NchVsFT0A"), aT0A / 100., glbTracks); histos.fill(HIST("NchVsFT0C"), aT0C / 100., glbTracks); histos.fill(HIST("NchVsFT0M"), (aT0A + aT0C) / 100., glbTracks); From 8699515e50403a6f7257a52c4dac1bffd26b45dc Mon Sep 17 00:00:00 2001 From: Thorkj <154221526+Thorkj@users.noreply.github.com> Date: Fri, 8 May 2026 17:06:40 +0200 Subject: [PATCH 101/449] [PWGCF] Added RCTevent selection, and track counter configurable (#16149) --- .../TwoParticleCorrelations/Tasks/corrFit.cxx | 198 +++++++++++------- 1 file changed, 123 insertions(+), 75 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx index 15265a76dab..b873791944b 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx @@ -16,6 +16,7 @@ #include "PWGCF/Core/CorrelationContainer.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" @@ -56,9 +57,9 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; using namespace constants::math; -// define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct CorrFit { @@ -69,6 +70,7 @@ struct CorrFit { O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgUseTransverseMomentum, bool, false, "Use transverse momentum for correlation container") O2_DEFINE_CONFIGURABLE(cfgQaCheck, bool, true, "Enable QA histograms for event selection") + O2_DEFINE_CONFIGURABLE(cfgStrictTrackCounter, bool, false, "Strict track counter for multiplicity correlation cut, counts only tracks that pass all cuts and are used in the correlation") struct : ConfigurableGroup{ O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") @@ -216,26 +218,6 @@ struct CorrFit { // define global variables TRandom3* gRandom = new TRandom3(); - enum EventCutTypes { - kFilteredEvents = 0, - kAfterSel8, - kUseNoTimeFrameBorder, - kUseNoITSROFrameBorder, - kUseNoSameBunchPileup, - kUseGoodZvtxFT0vsPV, - kUseNoCollInTimeRangeStandard, - kUseGoodITSLayersAll, - kUseGoodITSLayer0123, - kUseNoCollInRofStandard, - kUseNoHighMultCollInPrevRof, - kUseOccupancy, - kUseMultCorrCut, - kUseT0AV0ACut, - kUseVertexITSTPC, - kUseTVXinTRD, - kNEventCuts - }; - enum EventType { SameEvent = 1, MixedEvent = 3 @@ -246,26 +228,11 @@ struct CorrFit { kFT0C = 1 }; - enum DetectorChannels { - kFT0AInnerRingMin = 0, - kFT0AInnerRingMax = 31, - kFT0AOuterRingMin = 32, - kFT0AOuterRingMax = 95, - kFT0CInnerRingMin = 96, - kFT0CInnerRingMax = 143, - kFT0COuterRingMin = 144, - kFT0COuterRingMax = 207 - }; - - std::array, 16> eventCuts; + RCTFlagsChecker rctChecker{"CBT"}; void init(InitContext&) { - const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; - const AxisSpec axisEta{40, -1., 1., "#eta"}; - const AxisSpec axisEtaFull{90, -4., 5., "#eta"}; - ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); @@ -274,6 +241,9 @@ struct CorrFit { LOGF(info, "Starting init"); if (doprocessSameFt0aFt0c || doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTPC) { + registry.add("hEventCountRct", "Number of Event;; Count", {HistType::kTH1D, {{2, 0, 2}}}); + registry.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(1, "rct fail"); + registry.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(2, "rct pass"); registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); @@ -291,7 +261,7 @@ struct CorrFit { } if ((doprocessSameFt0aFt0c || doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTPC) && cfgQaCheck) { - registry.add("hPassedEventSelection", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); + registry.add("hPassedEventSelection", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(1, "all tracks"); registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(2, "after sel8"); registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); @@ -304,7 +274,6 @@ struct CorrFit { registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(10, "kNoCollInRofStandard"); registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoHighMultCollInPrevRof"); registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(12, "occupancy"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); } if (doprocessSameTPC || doprocessSameFt0aFt0c || doprocessSameTpcFt0a || doprocessSameTpcFt0c) { @@ -405,9 +374,23 @@ struct CorrFit { LOGF(info, "End of init"); } + template + bool eventRct(TCollision const& collision, const bool fillCounter) + { + if (!rctChecker(collision)) { + if (fillCounter) + registry.fill(HIST("hEventCountRct"), 0.5); + + return 0; + } + if (fillCounter) + registry.fill(HIST("hEventCountRct"), 1.5); + + return 1; + } template - bool eventSelected(TCollision collision, const int multTrk, const bool fillCounter) + bool eventSelected(TCollision const& collision, const int multTrk, const bool fillCounter) { registry.fill(HIST("hEventCountSpecific"), 0.5); if (cfgEventSelection.cfgEvSelkNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { @@ -505,7 +488,7 @@ struct CorrFit { } template - void eventSelectedIndividually(TCollision collision) + void eventSelectedIndividually(TCollision const& collision) { registry.fill(HIST("hPassedEventSelection"), 0.5); @@ -549,6 +532,11 @@ struct CorrFit { if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { registry.fill(HIST("hPassedEventSelection"), 10.5); } + + auto occupancy = collision.trackOccupancyInTimeRange(); + if (cfgEventSelection.cfgEvSelOccupancy && (occupancy < cfgEventSelection.cfgCutOccupancyLow || occupancy > cfgEventSelection.cfgCutOccupancyHigh)) { + registry.fill(HIST("hPassedEventSelection"), 11.5); + } } double getPhiFT0(uint64_t chno, int i) @@ -591,13 +579,13 @@ struct CorrFit { } template - bool trackSelected(TTrack track) + bool trackSelected(TTrack const& track) { return ((track.tpcNClsFound() >= cfgTrackCuts.cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgTrackCuts.cfgCutITSclu)); } template - bool trackSelectedSystematics(TTrack track) + bool trackSelectedSystematics(TTrack const& track) { return ((track.tpcNClsFound() >= cfgSystematics.cfgSystematicsCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgSystematics.cfgSystematicsCutTPCCrossedRows) && (track.itsNCls() >= cfgSystematics.cfgSystematicsCutITSclu)); } @@ -752,25 +740,21 @@ struct CorrFit { } template - void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float multiplicity, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int multiplicity, int corType, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { - if (system == SameEvent) { - registry.fill(HIST("Nch"), multiplicity); - } - int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); float triggerWeight = 1.0f; // loop over all tracks for (auto const& track1 : tracks1) { + if (!trackSelected(track1)) + continue; + if (cfgSystematics.cfgSystematicsVariation) { if (!trackSelectedSystematics(track1)) continue; - } else { - if (!trackSelected(track1)) - continue; } if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) @@ -806,12 +790,14 @@ struct CorrFit { if (system == SameEvent) { if (corType == kFT0A) { if (cfgQaCheck) { + registry.fill(HIST("Nch"), multiplicity); registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { if (cfgQaCheck) { + registry.fill(HIST("Nch"), multiplicity); registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } @@ -861,10 +847,13 @@ struct CorrFit { } template - void fillCorrelationsFT0AFT0C(TFT0s const& ft0Col1, TFT0s const& ft0Col2, float posZ, int system, float multiplicity, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelationsFT0AFT0C(TFT0s const& ft0Col1, TFT0s const& ft0Col2, float posZ, int system, int multiplicity, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + if (cfgQaCheck) { + registry.fill(HIST("Nch"), multiplicity); + } float triggerWeight = 1.0f; std::size_t channelASize = ft0Col1.channelA().size(); std::size_t channelCSize = ft0Col2.channelC().size(); @@ -907,7 +896,7 @@ struct CorrFit { } template - void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, float multiplicity, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int multiplicity, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); @@ -917,12 +906,12 @@ struct CorrFit { // loop over all tracks for (auto const& track1 : tracks1) { + if (!trackSelected(track1)) + continue; + if (cfgSystematics.cfgSystematicsVariation) { if (!trackSelectedSystematics(track1)) continue; - } else { - if (!trackSelected(track1)) - continue; } if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) @@ -993,6 +982,9 @@ struct CorrFit { if (!collision.sel8()) return; + if (!eventRct(collision, true)) + return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) @@ -1012,8 +1004,14 @@ struct CorrFit { fillYield(collision, tracks); + int multiplicity = tracks.size(); + + if (cfgStrictTrackCounter) { + trackCounter(tracks, multiplicity); + } + const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0A, tracks.size(), eventWeight); + fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, multiplicity, kFT0A, eventWeight); } PROCESS_SWITCH(CorrFit, processSameTpcFt0a, "Process same event for TPC-FT0 correlation", false); @@ -1038,6 +1036,9 @@ struct CorrFit { if (!collision1.sel8() || !collision2.sel8()) continue; + if (!eventRct(collision1, false) || !eventRct(collision2, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) continue; if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) @@ -1053,8 +1054,14 @@ struct CorrFit { loadCorrection(bc.timestamp()); float eventWeight = 1.0f; + int multiplicity = tracks1.size(); + + if (cfgStrictTrackCounter) { + trackCounter(tracks1, multiplicity); + } + const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, tracks1.size(), eventWeight); + fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, multiplicity, kFT0A, eventWeight); } } PROCESS_SWITCH(CorrFit, processMixedTpcFt0a, "Process mixed events for TPC-FT0A correlation", false); @@ -1068,6 +1075,10 @@ struct CorrFit { if (!collision.sel8()) return; + + if (!eventRct(collision, true)) + return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) @@ -1084,10 +1095,13 @@ struct CorrFit { const auto& ft0 = collision.foundFT0(); - int multiplicity = 0; - trackCounter(tracks, multiplicity); + int multiplicity = tracks.size(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0C, multiplicity, 1.0f); + if (cfgStrictTrackCounter) { + trackCounter(tracks, multiplicity); + } + + fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, multiplicity, kFT0C, 1.0f); } PROCESS_SWITCH(CorrFit, processSameTpcFt0c, "Process same event for TPC-FT0C correlation", false); @@ -1111,6 +1125,9 @@ struct CorrFit { if (!collision1.sel8() || !collision2.sel8()) continue; + if (!eventRct(collision1, false) || !eventRct(collision2, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) continue; @@ -1127,11 +1144,13 @@ struct CorrFit { float eventWeight = 1.0f; const auto& ft0 = collision2.foundFT0(); + int multiplicity = tracks1.size(); - int multiplicity = 0; - trackCounter(tracks1, multiplicity); + if (cfgStrictTrackCounter) { + trackCounter(tracks, multiplicity); + } - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, multiplicity, eventWeight); + fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, multiplicity, kFT0C, eventWeight); } } PROCESS_SWITCH(CorrFit, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); @@ -1145,6 +1164,10 @@ struct CorrFit { if (!collision.sel8()) return; + + if (!eventRct(collision, true)) + return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) @@ -1159,11 +1182,17 @@ struct CorrFit { float eventWeight = 1.0f; const auto& ft0 = collision.foundFT0(); - int multiplicity = 0; - trackCounter(tracks, multiplicity); fillYield(collision, tracks); + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + int multiplicity = tracks.size(); + + if (cfgStrictTrackCounter) { + trackCounter(tracks, multiplicity); + } + fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), SameEvent, multiplicity, eventWeight); } PROCESS_SWITCH(CorrFit, processSameFt0aFt0c, "Process same event for FT0A-FT0C correlation", true); @@ -1190,6 +1219,9 @@ struct CorrFit { if (!collision1.sel8() || !collision2.sel8()) continue; + if (!eventRct(collision1, false) || !eventRct(collision2, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) continue; if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) @@ -1206,9 +1238,13 @@ struct CorrFit { const auto& ft0Col1 = collision1.foundFT0(); const auto& ft0Col2 = collision2.foundFT0(); - int multiplicity = 0; + int multiplicity = tracks1.size(); - trackCounter(tracks, multiplicity); + if (cfgStrictTrackCounter) { + trackCounter(tracks1, multiplicity); + } + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin fillCorrelationsFT0AFT0C(ft0Col1, ft0Col2, collision1.posZ(), MixedEvent, multiplicity, eventWeight); } @@ -1221,6 +1257,8 @@ struct CorrFit { if (cfgQaCheck) { eventSelectedIndividually(collision); } + if (!eventRct(collision, true)) + return; if (!collision.sel8()) return; @@ -1232,12 +1270,15 @@ struct CorrFit { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - int multiplicity = 0; - trackCounter(tracks, multiplicity); - fillYield(collision, tracks); - fillCorrelations(tracks, tracks, collision.posZ(), multiplicity, SameEvent, getMagneticField(bc.timestamp())); + int multiplicity = tracks.size(); + + if (cfgStrictTrackCounter) { + trackCounter(tracks, multiplicity); + } + + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, multiplicity, getMagneticField(bc.timestamp())); } PROCESS_SWITCH(CorrFit, processSameTPC, "Process same event for TPC-TPC correlation", false); @@ -1258,6 +1299,10 @@ struct CorrFit { Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (!eventRct(collision1, false) || !eventRct(collision2, false)) + continue; + if (!collision1.sel8() || !collision2.sel8()) continue; @@ -1268,10 +1313,13 @@ struct CorrFit { registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - int multiplicity = 0; - trackCounter(tracks1, multiplicity); + int multiplicity = tracks1.size(); + + if (cfgStrictTrackCounter) { + trackCounter(tracks1, multiplicity); + } - fillCorrelations(tracks1, tracks2, collision1.posZ(), multiplicity, MixedEvent, getMagneticField(collision1.bc_as().timestamp())); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, multiplicity, getMagneticField(collision1.bc_as().timestamp())); } } PROCESS_SWITCH(CorrFit, processMixedTPC, "Process mixed events for TPC-TPC correlation", false); From 6ce2513c62427dac9d7d86a4eace50b277c55695 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Fri, 8 May 2026 17:17:04 +0200 Subject: [PATCH 102/449] [PWGJE,PWGEM-36] Add new Clusterizer options (#16170) --- PWGJE/DataModel/EMCALClusters.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index 5f85849bcc6..d711a5e08b9 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -50,6 +50,8 @@ const EMCALClusterDefinition kV3MostSplitSmallTimeDiff(ClusterAlgorithm_t::kV3, const EMCALClusterDefinition kV3MostSplitSmallerTimeDiff(ClusterAlgorithm_t::kV3, 44, 1, "kV3MostSplitSmallerTimeDiff", 0.5, 0.1, -10000, 10000, 100, true, 0., false); const EMCALClusterDefinition kV3MostSplitSmallestTimeDiff(ClusterAlgorithm_t::kV3, 45, 1, "kV3MostSplitSmallestTimeDiff", 0.5, 0.1, -10000, 10000, 50, true, 0., false); const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowestSeed(ClusterAlgorithm_t::kV3, 50, 1, "kV3MostSplitSmallestTimeDiffLowestSeed", 0.1, 0.1, -10000, 10000, 50, true, 0., false); +const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowSeed(ClusterAlgorithm_t::kV3, 51, 1, "kV3MostSplitSmallestTimeDiffLowSeed", 0.3, 0.1, -10000, 10000, 50, true, 0., false); +const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowerSeed(ClusterAlgorithm_t::kV3, 52, 1, "kV3MostSplitSmallestTimeDiffLowerSeed", 0.2, 0.1, -10000, 10000, 50, true, 0., false); /// \brief function returns EMCALClusterDefinition for the given name /// \param name name of the cluster definition @@ -92,6 +94,10 @@ inline const EMCALClusterDefinition getClusterDefinitionFromString(const std::st return kV3MostSplitSmallestTimeDiff; } else if (clusterDefinitionName == "kV3MostSplitSmallestTimeDiffLowestSeed") { return kV3MostSplitSmallestTimeDiffLowestSeed; + } else if (clusterDefinitionName == "kV3MostSplitSmallestTimeDiffLowSeed") { + return kV3MostSplitSmallestTimeDiffLowSeed; + } else if (clusterDefinitionName == "kV3MostSplitSmallestTimeDiffLowerSeed") { + return kV3MostSplitSmallestTimeDiffLowerSeed; } else { throw std::invalid_argument("Cluster definition name not recognized"); } From 66195c966d2d8cc0d2196ae3bc0ef1005b883b06 Mon Sep 17 00:00:00 2001 From: losiash <57404687+losiash@users.noreply.github.com> Date: Fri, 8 May 2026 21:23:37 +0200 Subject: [PATCH 103/449] [PWGCF] Update pp ESE flow fluctuation task (#16171) --- PWGCF/Flow/Tasks/flowFlucGfwPp.cxx | 168 ++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 27 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx index 1405b0a60b0..14de3f9093e 100644 --- a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx +++ b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx @@ -11,7 +11,7 @@ /// \file flowFlucGfwPp.cxx /// \brief GFW task for Event Shape Engineering studies in pp collisions -/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch, Wenya Wu, TUM, wenya.wu@cern.ch +/// \author Wenya Wu, TUM, wenya.wu@cern.ch, David Krylenkov, TUM #include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" @@ -23,7 +23,6 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" #include @@ -106,6 +105,7 @@ std::vector firstRunsOfFill; struct FlowFlucGfwPp { static constexpr int kInvalidQnBin = -999; static constexpr float kInvalidQnSeparator = -999.f; + static constexpr float kTPCSubeventEtaGapHalfWidth = 0.1f; static constexpr int kRequireBothEtaSides = 1; static constexpr int kRequireFullFourParticleTracks = 2; @@ -120,6 +120,7 @@ struct FlowFlucGfwPp { O2_DEFINE_CONFIGURABLE(cfgIsMC, bool, false, "Is MC event") O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FV0A, 4:NTPV, 5:NGlobals, 6:MFT") O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Do correlations as function of Nch") + O2_DEFINE_CONFIGURABLE(cfgQvecQA, bool, false, "Enable filling QA for q-Vec of TPC") O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, false, "Fill NUA weights") O2_DEFINE_CONFIGURABLE(cfgRunByRun, bool, false, "Fill histograms on a run-by-run basis") O2_DEFINE_CONFIGURABLE(cfgFillFlowRunByRun, bool, false, "Fill flow profile run-by-run (only for v22)") @@ -165,6 +166,10 @@ struct FlowFlucGfwPp { O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 100, "Maximum of centrality or multiplicity"); O2_DEFINE_CONFIGURABLE(cfgEvtSelCent, bool, true, "Choose event selector as centrality(true) or multicplity(false)"); O2_DEFINE_CONFIGURABLE(cfgUseNegativeEtaHalfForq2, bool, true, "If true, use -eta half for q2 selection; otherwise use +eta half"); + O2_DEFINE_CONFIGURABLE(cfgMinPtOnTPC, float, 0.2, "minimum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"); + O2_DEFINE_CONFIGURABLE(cfgMaxPtOnTPC, float, 5., "maximum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"); + O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8, "Maximum pseudorapidiy for charged track"); + O2_DEFINE_CONFIGURABLE(cfgEtaMin, float, -0.8, "Minimum pseudorapidiy for charged track"); Configurable> qnBinSeparator{"qnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; struct : ConfigurableGroup { @@ -325,11 +330,26 @@ struct FlowFlucGfwPp { o2::framework::expressions::Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgVtxZ; o2::framework::expressions::Filter mcParticlesFilter = (aod::mcparticle::eta > o2::analysis::gfwflowflucpp::etalow && aod::mcparticle::eta < o2::analysis::gfwflowflucpp::etaup && aod::mcparticle::pt > o2::analysis::gfwflowflucpp::ptlow && aod::mcparticle::pt < o2::analysis::gfwflowflucpp::ptup); - using GFWTracks = soa::Filtered>; + using GFWTracks = soa::Filtered>; void init(InitContext const&) { LOGF(info, "FlowFlucGfwPp::init()"); + if (static_cast(cfgMinPtOnTPC) < static_cast(cfgPtmin) || + static_cast(cfgMaxPtOnTPC) > static_cast(cfgPtmax) || + static_cast(cfgEtaMax) > static_cast(cfgEta) || + static_cast(cfgEtaMin) < -static_cast(cfgEta)) { + LOGF(warning, + "The Q-vector loop sees only tracks that passed the main trackFilter. " + "[pt %.3g, %.3g], [eta %.3g, %.3g] and input cuts [pt %.3g, %.3g], |eta|<%.3g", + static_cast(cfgMinPtOnTPC), + static_cast(cfgMaxPtOnTPC), + static_cast(cfgEtaMin), + static_cast(cfgEtaMax), + static_cast(cfgPtmin), + static_cast(cfgPtmax), + static_cast(cfgEta)); + } o2::analysis::gfwflowflucpp::regions.SetNames(cfgRegions->GetNames()); o2::analysis::gfwflowflucpp::regions.SetEtaMin(cfgRegions->GetEtaMin()); o2::analysis::gfwflowflucpp::regions.SetEtaMax(cfgRegions->GetEtaMax()); @@ -427,6 +447,19 @@ struct FlowFlucGfwPp { int ptbins = o2::analysis::gfwflowflucpp::ptbinning.size() - 1; fSecondAxis = (cfgTimeDependent) ? new TAxis(timeAxis.binEdges.size() - 1, &(timeAxis.binEdges[0])) : new TAxis(ptbins, &o2::analysis::gfwflowflucpp::ptbinning[0]); + if (cfgQvecQA && (doprocessData || doprocessq2)) { + // qVectorsTable-equivalent TPC-track QA for the in-task raw TPC Q-vector loop. + AxisSpec qVecAxisPt = {40, 0.0, 4.0}; + AxisSpec qVecAxisEta = {32, -0.8, 0.8}; + AxisSpec qVecAxisPhi = {32, 0, constants::math::TwoPI}; + AxisSpec qVecAxisCent = {20, 0, 100}; + AxisSpec qVecAxisMulti = {20, 0, 1000}; + AxisSpec qVecAxis = {20, -10, 10}; + registry.add("qvecQA/ChTracks", ";pT;#eta;#phi", {HistType::kTHnSparseF, {qVecAxisPt, qVecAxisEta, qVecAxisPhi}}); + registry.add("qvecQA/CountEvt", ";Centrality;TrkSize;TrkSel;MultNTrkPV", {HistType::kTHnSparseF, {qVecAxisCent, qVecAxisMulti, qVecAxisMulti, qVecAxisMulti}}); + registry.add("qvecQA/QxQy", ";QxAll;QyAll;QxNeg;QyNeg;QxPos;QyPos", {HistType::kTHnSparseF, {qVecAxis, qVecAxis, qVecAxis, qVecAxis, qVecAxis, qVecAxis}}); + } + if (doprocessq2) { registry.add("mq2/eventcounter", "", HistType::kTH1F, {{10, 0, 10}}); registry.add("mq2/h2_cent_q2_etapos", ";Centrality;#it{q}_{2}^{#eta pos};", HistType::kTH2D, {{100, 0, 100}, {600, 0, 6}}); @@ -884,28 +917,108 @@ struct FlowFlucGfwPp { int nMid; }; - template - float computeqnVec(T const& col, bool useNegativeEtaHalf) + struct InTaskTPCQVector { + float qVectTPCPos[2] = {0.f, 0.f}; // Always computed + float qVectTPCNeg[2] = {0.f, 0.f}; // Always computed + float qVectTPCAll[2] = {0.f, 0.f}; // Always computed + + int nTrkTPCPos = 0; + int nTrkTPCNeg = 0; + int nTrkTPCAll = 0; + + std::vector trkTPCPosLabel{}; + std::vector trkTPCNegLabel{}; + std::vector trkTPCAllLabel{}; + }; + + template + bool selTrack(const TrackType track) { - if (col.qvecTPCposReVec().empty() || col.qvecTPCposImVec().empty() || - col.qvecTPCnegReVec().empty() || col.qvecTPCnegImVec().empty()) { - return -1.f; + if (track.pt() < cfgMinPtOnTPC) + return false; + if (track.pt() > cfgMaxPtOnTPC) + return false; + if (!track.passedITSNCls()) + return false; + if (!track.passedITSChi2NDF()) + return false; + if (!track.passedITSHits()) + return false; + if (!track.passedTPCCrossedRowsOverNCls()) + return false; + if (!track.passedTPCChi2NDF()) + return false; + if (!track.passedDCAxy()) + return false; + if (!track.passedDCAz()) + return false; + + return true; + } + + template + InTaskTPCQVector calcQVec(const Nmode nMode, const TrackType& tracks, const TCollision& collision) + { + InTaskTPCQVector qvec; + + double nTrkSel = 0.; + for (auto const& trk : tracks) { + if (!selTrack(trk)) { + continue; + } + if (trk.eta() > cfgEtaMax) { + continue; + } + if (trk.eta() < cfgEtaMin) { + continue; + } + qvec.qVectTPCAll[0] += trk.pt() * std::cos(trk.phi() * nMode); + qvec.qVectTPCAll[1] += trk.pt() * std::sin(trk.phi() * nMode); + qvec.trkTPCAllLabel.push_back(trk.globalIndex()); + qvec.nTrkTPCAll++; + nTrkSel++; + if (std::abs(trk.eta()) < kTPCSubeventEtaGapHalfWidth) { + continue; + } + if (cfgQvecQA) { + registry.fill(HIST("qvecQA/ChTracks"), trk.pt(), trk.eta(), trk.phi()); + } + + if (trk.eta() > 0) { + // In qVectorsTable this branch is additionally guarded by useDetector["QvectorTPCposs"] || useDetector["QvectorBPoss"]. + // Here TPCpos is always computed because the downstream ESE selector can require it. + qvec.qVectTPCPos[0] += trk.pt() * std::cos(trk.phi() * nMode); + qvec.qVectTPCPos[1] += trk.pt() * std::sin(trk.phi() * nMode); + qvec.trkTPCPosLabel.push_back(trk.globalIndex()); + qvec.nTrkTPCPos++; + } else if (trk.eta() < 0) { + // In qVectorsTable this branch is additionally guarded by useDetector["QvectorTPCnegs"] || useDetector["QvectorBNegs"]. + // Here TPCneg is always computed because the downstream ESE selector can require it. + qvec.qVectTPCNeg[0] += trk.pt() * std::cos(trk.phi() * nMode); + qvec.qVectTPCNeg[1] += trk.pt() * std::sin(trk.phi() * nMode); + qvec.trkTPCNegLabel.push_back(trk.globalIndex()); + qvec.nTrkTPCNeg++; + } } - if (col.nTrkTPCpos() <= 0 || col.nTrkTPCneg() <= 0) - return -1.f; + if (cfgQvecQA) { + registry.fill(HIST("qvecQA/CountEvt"), collision.centFT0C(), tracks.size(), nTrkSel, collision.multNTracksPV()); + registry.fill(HIST("qvecQA/QxQy"), qvec.qVectTPCAll[0], qvec.qVectTPCAll[1], qvec.qVectTPCNeg[0], qvec.qVectTPCNeg[1], qvec.qVectTPCPos[0], qvec.qVectTPCPos[1]); + } - const auto qvecPos = - std::sqrt(col.qvecTPCposReVec()[0] * col.qvecTPCposReVec()[0] + - col.qvecTPCposImVec()[0] * col.qvecTPCposImVec()[0]) * - std::sqrt(col.nTrkTPCpos()); + return qvec; + } - const auto qvecNeg = - std::sqrt(col.qvecTPCnegReVec()[0] * col.qvecTPCnegReVec()[0] + - col.qvecTPCnegImVec()[0] * col.qvecTPCnegImVec()[0]) * - std::sqrt(col.nTrkTPCneg()); + float computeqnVec(InTaskTPCQVector const& qvec, bool useNegativeEtaHalf) + { + if (qvec.nTrkTPCPos <= 0 || qvec.nTrkTPCNeg <= 0) { + return -1.f; + } - return useNegativeEtaHalf ? qvecNeg : qvecPos; + if (useNegativeEtaHalf) { + return std::hypot(qvec.qVectTPCNeg[0], qvec.qVectTPCNeg[1]) / std::sqrt(static_cast(qvec.nTrkTPCNeg)); + } + return std::hypot(qvec.qVectTPCPos[0], qvec.qVectTPCPos[1]) / std::sqrt(static_cast(qvec.nTrkTPCPos)); } /// \return the 1-d qn-vector separator to 2-d @@ -1230,8 +1343,7 @@ struct FlowFlucGfwPp { void processData(soa::Filtered>::iterator const& collision, + aod::CentMFTs>>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { auto bc = collision.bc_as(); @@ -1275,7 +1387,7 @@ struct FlowFlucGfwPp { const XAxis xaxis{ getCentrality(collision), - tracks.size(), + collision.multNTracksPV(), (cfgTimeDependent) ? getTimeSinceStartOfFill(bc.timestamp(), *firstRunOfCurrentFill) : -1.0}; if (cfgTimeDependent && run == *firstRunOfCurrentFill && @@ -1294,7 +1406,8 @@ struct FlowFlucGfwPp { if (cfgFillQA) fillEventQA(collision, xaxis); - float qn = computeqnVec(collision, cfgUseNegativeEtaHalfForq2); + const auto qvecTPC = calcQVec(2, tracks, collision); + float qn = computeqnVec(qvecTPC, cfgUseNegativeEtaHalfForq2); if (qn < 0) return; @@ -1307,7 +1420,7 @@ struct FlowFlucGfwPp { } PROCESS_SWITCH(FlowFlucGfwPp, processData, "Process analysis for non-derived data", false); - void processq2(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + void processq2(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { float count{0.5}; registry.fill(HIST("mq2/eventcounter"), count++); @@ -1323,14 +1436,15 @@ struct FlowFlucGfwPp { } registry.fill(HIST("mq2/eventcounter"), count++); - const XAxis xaxis{getCentrality(collision), tracks.size(), -1.0}; + const XAxis xaxis{getCentrality(collision), collision.multNTracksPV(), -1.0}; if (!eventSelected(collision, xaxis.multiplicity, xaxis.centrality, -1)) return; const auto centr = xaxis.centrality; const auto multi = xaxis.multiplicity; - const auto qvecPos = computeqnVec(collision, false); - const auto qvecNeg = computeqnVec(collision, true); + const auto qvecTPC = calcQVec(2, tracks, collision); + const auto qvecPos = computeqnVec(qvecTPC, false); + const auto qvecNeg = computeqnVec(qvecTPC, true); if (!std::isfinite(qvecPos) || !std::isfinite(qvecNeg) || qvecPos < 0 || qvecNeg < 0) { return; From b379dc944accfd6338b84a03013057b4a6c6fd0e Mon Sep 17 00:00:00 2001 From: bhattdurgesh921-sys Date: Sat, 9 May 2026 01:18:18 +0530 Subject: [PATCH 104/449] [PWGLF] fix O2-linter errors and rename filename (#16168) --- PWGLF/Tasks/Resonances/CMakeLists.txt | 2 +- ...nalysispo.cxx => lambda1520analysispo.cxx} | 829 +++++------------- 2 files changed, 213 insertions(+), 618 deletions(-) rename PWGLF/Tasks/Resonances/{lambda1520Analysispo.cxx => lambda1520analysispo.cxx} (60%) diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 03bc8d9a45f..4d987a4ddf4 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -315,6 +315,6 @@ o2physics_add_dpl_workflow(chk892li COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lambda1520-analysis-po - SOURCES lambda1520Analysispo.cxx + SOURCES lambda1520analysispo.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/lambda1520Analysispo.cxx b/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx similarity index 60% rename from PWGLF/Tasks/Resonances/lambda1520Analysispo.cxx rename to PWGLF/Tasks/Resonances/lambda1520analysispo.cxx index ce5adf03646..350c7dd9501 100644 --- a/PWGLF/Tasks/Resonances/lambda1520Analysispo.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx @@ -70,308 +70,110 @@ struct Lambda1520Analysispo { // ── Event-level configurables ──────────────────────────────────────────── // FIX name/configurable: lowerCamelCase, member name == JSON string, on one // line - Configurable applyOccupancyInTimeRangeCut{ - "applyOccupancyInTimeRangeCut", false, - "If true, apply a cut on the number of tracks in a time window around " - "the collision (occupancy cut)"}; + Configurable applyOccupancyInTimeRangeCut{"applyOccupancyInTimeRangeCut", false, "If true, apply a cut on the number of tracks in a time window around the collision (occupancy cut)"}; // ── Histogram binning configurables ───────────────────────────────────── - Configurable numberOfPtBins{ - "numberOfPtBins", 100, - "Number of bins along the transverse momentum (pT) axis"}; - Configurable numberOfInvMassBins{ - "numberOfInvMassBins", 120, - "Number of bins along the invariant mass axis"}; + Configurable numberOfPtBins{"numberOfPtBins", 100, "Number of bins along the transverse momentum (pT) axis"}; + Configurable numberOfInvMassBins{"numberOfInvMassBins", 120, "Number of bins along the invariant mass axis"}; // ── Physics configurables ──────────────────────────────────────────────── - Configurable pdgCodeLambda1520{"pdgCodeLambda1520", 3124, - "PDG code of the Lambda(1520) resonance"}; - Configurable enableRotationalBackground{ - "enableRotationalBackground", true, - "If true, compute rotational background (kaon phi rotated by ~pi) to " - "estimate combinatorial background"}; + Configurable pdgCodeLambda1520{"pdgCodeLambda1520", 3124, "PDG code of the Lambda(1520) resonance"}; + Configurable enableRotationalBackground{"enableRotationalBackground", true, "If true, compute rotational background (kaon phi rotated by ~pi) to estimate combinatorial background"}; // ── Track quality cuts ─────────────────────────────────────────────────── - Configurable minTrackPt{ - "minTrackPt", 0.15f, "Minimum transverse momentum pT of a track [GeV/c]"}; - Configurable minTrackMomentum{ - "minTrackMomentum", 0.f, "Minimum total momentum p of a track [GeV/c]"}; - Configurable minPseudorapidity{ - "minPseudorapidity", -0.8f, - "Minimum pseudorapidity eta (detector acceptance)"}; - Configurable maxPseudorapidity{ - "maxPseudorapidity", 0.8f, - "Maximum pseudorapidity eta (detector acceptance)"}; - Configurable maxDCAz{ - "maxDCAz", 1.0f, - "Maximum allowed distance of closest approach along z-axis (DCAz) [cm]"}; - Configurable minPairRapidity{ - "minPairRapidity", -0.5f, - "Minimum rapidity y of the reconstructed proton-kaon pair"}; - Configurable maxPairRapidity{ - "maxPairRapidity", 0.5f, - "Maximum rapidity y of the reconstructed proton-kaon pair"}; + Configurable minTrackPt{"minTrackPt", 0.15f, "Minimum transverse momentum pT of a track [GeV/c]"}; + Configurable minProtonMomentum{"minProtonMomentum", 0.f, "Minimum total momentum p for proton PID [GeV/c]"}; + Configurable minKaonMomentum{"minKaonMomentum", 0.f, "Minimum total momentum p for kaon PID [GeV/c]"}; + Configurable minPseudorapidity{"minPseudorapidity", -0.8f, "Minimum pseudorapidity eta (detector acceptance)"}; + Configurable maxPseudorapidity{"maxPseudorapidity", 0.8f, "Maximum pseudorapidity eta (detector acceptance)"}; + Configurable maxDCAz{"maxDCAz", 1.0f, "Maximum allowed distance of closest approach along z-axis (DCAz) [cm]"}; + Configurable minPairRapidity{"minPairRapidity", -0.5f, "Minimum rapidity y of the reconstructed proton-kaon pair"}; + Configurable maxPairRapidity{"maxPairRapidity", 0.5f, "Maximum rapidity y of the reconstructed proton-kaon pair"}; // ── TPC cluster quality cuts ───────────────────────────────────────────── - Configurable minTPCCrossedRows{ - "minTPCCrossedRows", 70, - "Minimum number of TPC crossed pad rows (track quality)"}; - Configurable applyCrossedRowsCut{ - "applyCrossedRowsCut", false, - "If true, require at least minTPCCrossedRows crossed rows in the TPC"}; - Configurable minTPCClustersFound{ - "minTPCClustersFound", 70, - "Minimum number of TPC clusters found on the track"}; - Configurable applyTPCClustersCut{ - "applyTPCClustersCut", false, - "If true, require at least minTPCClustersFound TPC clusters"}; + Configurable minTPCCrossedRows{"minTPCCrossedRows", 70, "Minimum number of TPC crossed pad rows (track quality)"}; + Configurable applyCrossedRowsCut{"applyCrossedRowsCut", false, "If true, require at least minTPCCrossedRows crossed rows in the TPC"}; + Configurable minTPCClustersFound{"minTPCClustersFound", 70, "Minimum number of TPC clusters found on the track"}; + Configurable applyTPCClustersCut{"applyTPCClustersCut", false, "If true, require at least minTPCClustersFound TPC clusters"}; // ── pT-dependent DCAxy cuts for Protons ───────────────────────────────── - Configurable> protonDCAPtBinEdges{ - "protonDCAPtBinEdges", - {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, - "Proton pT bin edges [GeV/c] for the pT-dependent DCAxy selection"}; - Configurable> protonMaxDCAxyPerPtBin{ - "protonMaxDCAxyPerPtBin", - {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, - "Maximum |DCAxy| [cm] for protons in each pT bin defined by " - "protonDCAPtBinEdges"}; + Configurable> protonDCAPtBinEdges{"protonDCAPtBinEdges", {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, "Proton pT bin edges [GeV/c] for the pT-dependent DCAxy selection"}; + Configurable> protonMaxDCAxyPerPtBin{"protonMaxDCAxyPerPtBin", {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, "Maximum |DCAxy| [cm] for protons in each pT bin defined by protonDCAPtBinEdges"}; // ── pT-dependent DCAxy cuts for Kaons ─────────────────────────────────── - Configurable> kaonDCAPtBinEdges{ - "kaonDCAPtBinEdges", - {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, - "Kaon pT bin edges [GeV/c] for the pT-dependent DCAxy selection"}; - Configurable> kaonMaxDCAxyPerPtBin{ - "kaonMaxDCAxyPerPtBin", - {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, - "Maximum |DCAxy| [cm] for kaons in each pT bin defined by " - "kaonDCAPtBinEdges"}; + Configurable> kaonDCAPtBinEdges{"kaonDCAPtBinEdges", {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, "Kaon pT bin edges [GeV/c] for the pT-dependent DCAxy selection"}; + Configurable> kaonMaxDCAxyPerPtBin{"kaonMaxDCAxyPerPtBin", {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, "Maximum |DCAxy| [cm] for kaons in each pT bin defined by kaonDCAPtBinEdges"}; // ── Analysis mode switches ─────────────────────────────────────────────── - Configurable runQualityChecksOnly{ - "runQualityChecksOnly", false, - "If true, only fill QA histograms and skip invariant mass computation"}; - Configurable applyDeepAngleCut{ - "applyDeepAngleCut", false, - "If true, reject proton-kaon pairs with very small opening angle " - "(removes split-track background)"}; - Configurable deepAngleCutValue{ - "deepAngleCutValue", 0.04, - "Minimum allowed opening angle [rad] between proton and kaon (used if " - "applyDeepAngleCut = true)"}; - Configurable applyKinematicPairCuts{ - "applyKinematicPairCuts", false, - "If true, apply additional kinematic cuts on the p-K opening angle"}; + Configurable runQualityChecksOnly{"runQualityChecksOnly", false, "If true, only fill QA histograms and skip invariant mass computation"}; + Configurable applyDeepAngleCut{"applyDeepAngleCut", false, "If true, reject proton-kaon pairs with very small opening angle (removes split-track background)"}; + Configurable deepAngleCutValue{"deepAngleCutValue", 0.04, "Minimum allowed opening angle [rad] between proton and kaon (used if applyDeepAngleCut = true)"}; + Configurable applyKinematicPairCuts{"applyKinematicPairCuts", false, "If true, apply additional kinematic cuts on the p-K opening angle"}; // ── Global track selection flags ───────────────────────────────────────── - Configurable requirePrimaryTrack{ - "requirePrimaryTrack", true, - "Require track to pass the 'isPrimaryTrack' flag (kGoldenChi2 | kDCAxy | " - "kDCAz)"}; - Configurable requireGlobalTrackNoDCA{ - "requireGlobalTrackNoDCA", true, - "Require track to pass 'isGlobalTrackWoDCA' (quality cuts without DCA " - "requirement)"}; - Configurable requirePVContributor{ - "requirePVContributor", true, - "Require track to be a contributor to the primary vertex reconstruction"}; + Configurable requirePrimaryTrack{"requirePrimaryTrack", true, "Require track to pass the 'isPrimaryTrack' flag (kGoldenChi2 | kDCAxy | kDCAz)"}; + Configurable requireGlobalTrackNoDCA{"requireGlobalTrackNoDCA", true, "Require track to pass 'isGlobalTrackWoDCA' (quality cuts without DCA requirement)"}; + Configurable requirePVContributor{"requirePVContributor", true, "Require track to be a contributor to the primary vertex reconstruction"}; // ── PID configurables ──────────────────────────────────────────────────── - Configurable requireTOFForProton{ - "requireTOFForProton", false, - "If true, only accept proton candidates that have a TOF measurement"}; - Configurable requireTOFForKaon{ - "requireTOFForKaon", false, - "If true, only accept kaon candidates that have a TOF measurement"}; - Configurable useTPCOnlyPID{ - "useTPCOnlyPID", false, - "If true, use only TPC nSigma for PID (ignore TOF even if available)"}; - - Configurable tpcNSigmaVetoOtherSpecies{ - "tpcNSigmaVetoOtherSpecies", 3.0f, - "Reject track if its TPC nSigma for a different species is below this " - "threshold (avoids misID)"}; - Configurable tpcNSigmaVetoPion{ - "tpcNSigmaVetoPion", 3.0f, - "TPC nSigma threshold below which a track is vetoed as a pion"}; - Configurable tpcNSigmaVetoKaonForProton{ - "tpcNSigmaVetoKaonForProton", 3.0f, - "TPC nSigma threshold: veto proton candidates that look like kaons"}; - Configurable tpcNSigmaVetoPionForKaon{ - "tpcNSigmaVetoPionForKaon", 3.0f, - "TPC nSigma threshold: veto kaon candidates that look like pions"}; - Configurable tpcNSigmaVetoProtonForKaon{ - "tpcNSigmaVetoProtonForKaon", 3.0f, - "TPC nSigma threshold: veto kaon candidates that look like protons"}; - - Configurable minTPCNSigmaKaon{ - "minTPCNSigmaKaon", -6.0f, "Minimum (most negative) TPC nSigma for kaon"}; - Configurable minTPCNSigmaProton{ - "minTPCNSigmaProton", -6.0f, - "Minimum (most negative) TPC nSigma for proton"}; - Configurable minTOFNSigmaKaon{ - "minTOFNSigmaKaon", -6.0f, "Minimum (most negative) TOF nSigma for kaon"}; - Configurable minTOFNSigmaProton{ - "minTOFNSigmaProton", -6.0f, - "Minimum (most negative) TOF nSigma for proton"}; - Configurable minCombinedTPCTOFNSigmaKaon{ - "minCombinedTPCTOFNSigmaKaon", -6.0f, - "Minimum combined TPC+TOF nSigma for kaon (used in combined PID mode)"}; - Configurable minCombinedTPCTOFNSigmaProton{ - "minCombinedTPCTOFNSigmaProton", -6.0f, - "Minimum combined TPC+TOF nSigma for proton (used in combined PID mode)"}; - - Configurable tpcNSigmaVetoThreshold{ - "tpcNSigmaVetoThreshold", 3.0f, - "General TPC nSigma veto cut to reject misidentified particles when TPC " - "bands overlap"}; - Configurable tofNSigmaVetoThreshold{ - "tofNSigmaVetoThreshold", 3.0f, - "General TOF nSigma veto cut to reject misidentified particles"}; + Configurable requireTOFForProton{"requireTOFForProton", false, "If true, only accept proton candidates that have a TOF measurement"}; + Configurable requireTOFForKaon{"requireTOFForKaon", false, "If true, only accept kaon candidates that have a TOF measurement"}; + Configurable useTPCOnlyPID{"useTPCOnlyPID", false, "If true, use only TPC nSigma for PID (ignore TOF even if available)"}; + + Configurable tpcNSigmaVetoOtherSpecies{"tpcNSigmaVetoOtherSpecies", 3.0f, "Reject track if its TPC nSigma for a different species is below this threshold (avoids misID)"}; + Configurable tpcNSigmaVetoPion{"tpcNSigmaVetoPion", 3.0f, "TPC nSigma threshold below which a track is vetoed as a pion"}; + Configurable tpcNSigmaVetoKaonForProton{"tpcNSigmaVetoKaonForProton", 3.0f, "TPC nSigma threshold: veto proton candidates that look like kaons"}; + Configurable tpcNSigmaVetoPionForKaon{"tpcNSigmaVetoPionForKaon", 3.0f, "TPC nSigma threshold: veto kaon candidates that look like pions"}; + Configurable tpcNSigmaVetoProtonForKaon{"tpcNSigmaVetoProtonForKaon", 3.0f, "TPC nSigma threshold: veto kaon candidates that look like protons"}; + + Configurable minTPCNSigmaKaon{"minTPCNSigmaKaon", -6.0f, "Minimum (most negative) TPC nSigma for kaon"}; + Configurable minTPCNSigmaProton{"minTPCNSigmaProton", -6.0f, "Minimum (most negative) TPC nSigma for proton"}; + Configurable minTOFNSigmaKaon{"minTOFNSigmaKaon", -6.0f, "Minimum (most negative) TOF nSigma for kaon"}; + Configurable minTOFNSigmaProton{"minTOFNSigmaProton", -6.0f, "Minimum (most negative) TOF nSigma for proton"}; + Configurable minCombinedTPCTOFNSigmaKaon{"minCombinedTPCTOFNSigmaKaon", -6.0f, "Minimum combined TPC+TOF nSigma for kaon (used in combined PID mode)"}; + Configurable minCombinedTPCTOFNSigmaProton{"minCombinedTPCTOFNSigmaProton", -6.0f, "Minimum combined TPC+TOF nSigma for proton (used in combined PID mode)"}; + + Configurable tpcNSigmaVetoThreshold{"tpcNSigmaVetoThreshold", 3.0f, "General TPC nSigma veto cut to reject misidentified particles when TPC bands overlap"}; + Configurable tofNSigmaVetoThreshold{"tofNSigmaVetoThreshold", 3.0f, "General TOF nSigma veto cut to reject misidentified particles"}; // ── Proton PID momentum-dependent TPC cuts ─────────────────────────────── - Configurable maxTPCNSigmaProton{ - "maxTPCNSigmaProton", 3.0, - "Maximum |TPC nSigma| for proton identification (symmetric cut)"}; - Configurable combinedNSigmaCutProton{ - "combinedNSigmaCutProton", 3.0, - "Cut on sqrt(nSigmaTPC^2 + nSigmaTOF^2) for proton. Negative value " - "switches to asymmetric mode."}; - Configurable> protonTPCPIDMomentumBins{ - "protonTPCPIDMomentumBins", - {0, 0.5, 0.7, 0.8}, - "Momentum p bin edges [GeV/c] for momentum-dependent TPC PID cuts on " - "protons"}; - Configurable> protonTPCNSigmaCutPerBin{ - "protonTPCNSigmaCutPerBin", - {5., 3.5, 2.5}, - "Maximum TPC nSigma for proton in each momentum bin (tighter at higher " - "p)"}; - Configurable> protonTOFPIDMomentumBins{ - "protonTOFPIDMomentumBins", - {0., 999.}, - "Momentum p bin edges [GeV/c] for momentum-dependent TOF PID cuts on " - "protons"}; - Configurable> protonTOFNSigmaCutPerBin{ - "protonTOFNSigmaCutPerBin", - {3.0}, - "Maximum TOF nSigma for proton in each momentum bin"}; + Configurable maxTPCNSigmaProton{"maxTPCNSigmaProton", 3.0, "Maximum |TPC nSigma| for proton identification (symmetric cut)"}; + Configurable combinedNSigmaCutProton{"combinedNSigmaCutProton", 3.0, "Cut on sqrt(nSigmaTPC^2 + nSigmaTOF^2) for proton. Negative value switches to asymmetric mode."}; + Configurable> protonTPCPIDMomentumBins{"protonTPCPIDMomentumBins", {0, 0.5, 0.7, 0.8}, "Momentum p bin edges [GeV/c] for momentum-dependent TPC PID cuts on protons"}; + Configurable> protonTPCNSigmaCutPerBin{"protonTPCNSigmaCutPerBin", {5., 3.5, 2.5}, "Maximum TPC nSigma for proton in each momentum bin (tighter at higher p)"}; + Configurable> protonTOFPIDMomentumBins{"protonTOFPIDMomentumBins", {0., 999.}, "Momentum p bin edges [GeV/c] for momentum-dependent TOF PID cuts on protons"}; + Configurable> protonTOFNSigmaCutPerBin{"protonTOFNSigmaCutPerBin", {3.0}, "Maximum TOF nSigma for proton in each momentum bin"}; // ── Kaon PID momentum-dependent TPC cuts ──────────────────────────────── - Configurable maxTPCNSigmaKaon{ - "maxTPCNSigmaKaon", 3.0, - "Maximum |TPC nSigma| for kaon identification (symmetric cut)"}; - Configurable combinedNSigmaCutKaon{ - "combinedNSigmaCutKaon", 3.0, - "Cut on sqrt(nSigmaTPC^2 + nSigmaTOF^2) for kaon. Negative value " - "switches to asymmetric mode."}; - Configurable> kaonTPCPIDMomentumBins{ - "kaonTPCPIDMomentumBins", - {0., 0.25, 0.3, 0.45}, - "Momentum p bin edges [GeV/c] for momentum-dependent TPC PID cuts on " - "kaons"}; - Configurable> kaonTPCNSigmaCutPerBin{ - "kaonTPCNSigmaCutPerBin", - {6, 3.5, 2.5}, - "Maximum TPC nSigma for kaon in each momentum bin"}; - Configurable> kaonTOFPIDMomentumBins{ - "kaonTOFPIDMomentumBins", - {0., 999.}, - "Momentum p bin edges [GeV/c] for momentum-dependent TOF PID cuts on " - "kaons"}; - Configurable> kaonTOFNSigmaCutPerBin{ - "kaonTOFNSigmaCutPerBin", - {3.0}, - "Maximum TOF nSigma for kaon in each momentum bin"}; + Configurable maxTPCNSigmaKaon{"maxTPCNSigmaKaon", 3.0, "Maximum |TPC nSigma| for kaon identification (symmetric cut)"}; + Configurable combinedNSigmaCutKaon{"combinedNSigmaCutKaon", 3.0, "Cut on sqrt(nSigmaTPC^2 + nSigmaTOF^2) for kaon. Negative value switches to asymmetric mode."}; + Configurable> kaonTPCPIDMomentumBins{"kaonTPCPIDMomentumBins", {0., 0.25, 0.3, 0.45}, "Momentum p bin edges [GeV/c] for momentum-dependent TPC PID cuts on kaons"}; + Configurable> kaonTPCNSigmaCutPerBin{"kaonTPCNSigmaCutPerBin", {6, 3.5, 2.5}, "Maximum TPC nSigma for kaon in each momentum bin"}; + Configurable> kaonTOFPIDMomentumBins{"kaonTOFPIDMomentumBins", {0., 999.}, "Momentum p bin edges [GeV/c] for momentum-dependent TOF PID cuts on kaons"}; + Configurable> kaonTOFNSigmaCutPerBin{"kaonTOFNSigmaCutPerBin", {3.0}, "Maximum TOF nSigma for kaon in each momentum bin"}; // ── Event mixing configurables ─────────────────────────────────────────── - Configurable numberOfEventsToMix{ - "numberOfEventsToMix", 20, - "Number of events to mix with each signal event for background " - "estimation"}; - ConfigurableAxis dcaZMixingBins{ - "dcaZMixingBins", - {VARIABLE_WIDTH, -1.2f, -1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, - -0.4f, -0.3f, -0.2f, -0.1f, 0.f, 0.1f, 0.2f, 0.3f, - 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f}, - "DCAz vertex bins used for event mixing pairing"}; - ConfigurableAxis vertexZMixingBins{ - "vertexZMixingBins", - {VARIABLE_WIDTH, - -10.f, - -9.f, - -8.f, - -7.f, - -6.f, - -5.f, - -4.f, - -3.f, - -2.f, - -1.f, - 0.f, - 1.f, - 2.f, - 3.f, - 4.f, - 5.f, - 6.f, - 7.f, - 8.f, - 9.f, - 10.f}, - "Primary vertex z-position bins used for event mixing pairing"}; - ConfigurableAxis centralityMixingBins{ - "centralityMixingBins", - {VARIABLE_WIDTH, 0.f, 10.f, 20.f, 30.f, 40.f, 50.f, 60.f, 70.f, 80.f, - 90.f, 100.f, 200.f}, - "Centrality (FT0 %) bins used for event mixing pairing"}; - ConfigurableAxis eventPlaneMixingBins{ - "eventPlaneMixingBins", - {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, - 0.628319f, 0.942478f, 1.25664f, 1.5708f}, - "Event plane angle bins used for event mixing (EP-dependent analysis)"}; - ConfigurableAxis occupancyBins{ - "occupancyBins", - {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, - 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, - 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, - "Track occupancy bins in the time range around the collision"}; + Configurable numberOfEventsToMix{"numberOfEventsToMix", 20, "Number of events to mix with each signal event for background estimation"}; + ConfigurableAxis dcaZMixingBins{"dcaZMixingBins", {VARIABLE_WIDTH, -1.2f, -1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f, 0.f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f}, "DCAz vertex bins used for event mixing pairing"}; + ConfigurableAxis vertexZMixingBins{"vertexZMixingBins", {VARIABLE_WIDTH, -12.f, -10.f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 12.f}, "Primary vertex z-position bins used for event mixing pairing"}; + ConfigurableAxis centralityMixingBins{"centralityMixingBins", {VARIABLE_WIDTH, 0.f, 10.f, 20.f, 30.f, 40.f, 50.f, 60.f, 70.f, 80.f, 90.f, 100.f, 200.f}, "Centrality (FT0 %) bins used for event mixing pairing"}; + ConfigurableAxis eventPlaneMixingBins{"eventPlaneMixingBins", {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, 0.628319f, 0.942478f, 1.25664f, 1.5708f}, "Event plane angle bins used for event mixing (EP-dependent analysis)"}; + ConfigurableAxis occupancyBins{"occupancyBins", {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, "Track occupancy bins in the time range around the collision"}; // ── Rotational background configurables ───────────────────────────────── - Configurable numberOfRotations{"numberOfRotations", 10, - "How many times to rotate the kaon phi " - "for the rotational background estimate"}; - Configurable rotationAngleWindow{ - "rotationAngleWindow", 6.f, - "The kaon is rotated by angles near PI, within a window of " - "PI/rotationAngleWindow"}; + Configurable numberOfRotations{"numberOfRotations", 10, "How many times to rotate the kaon phi for the rotational background estimate"}; + Configurable rotationAngleWindow{"rotationAngleWindow", 6.f, "The kaon is rotated by angles near PI, within a window of PI/rotationAngleWindow"}; // ── MC event selection flags ───────────────────────────────────────────── - Configurable mcRequireAfterAllCuts{ - "mcRequireAfterAllCuts", false, - "MC event selection: require isInAfterAllCuts flag"}; - Configurable mcRequireINELgt0{"mcRequireINELgt0", false, - "MC event selection: require at least 1 " - "charged particle in |eta|<1 (INEL>0)"}; - Configurable mcRequireSel8{ - "mcRequireSel8", false, - "MC event selection: require the standard Sel8 event selection"}; - Configurable mcRequireVtxWithin10cm{ - "mcRequireVtxWithin10cm", false, - "MC event selection: require primary vertex |z| < 10 cm"}; - Configurable mcRequireTriggerTVX{ - "mcRequireTriggerTVX", false, - "MC event selection: require the TVX (T0 vertex) trigger"}; - Configurable mcRequireRecoINELgt0{ - "mcRequireRecoINELgt0", false, - "MC event selection: require reconstructed INEL>0 condition"}; + Configurable mcRequireAfterAllCuts{"mcRequireAfterAllCuts", false, "MC event selection: require isInAfterAllCuts flag"}; + Configurable mcRequireINELgt0{"mcRequireINELgt0", false, "MC event selection: require at least 1 charged particle in |eta|<1 (INEL>0)"}; + Configurable mcRequireSel8{"mcRequireSel8", false, "MC event selection: require the standard Sel8 event selection"}; + Configurable mcRequireVtxWithin10cm{"mcRequireVtxWithin10cm", false, "MC event selection: require primary vertex |z| < 10 cm"}; + Configurable mcRequireTriggerTVX{"mcRequireTriggerTVX", false, "MC event selection: require the TVX (T0 vertex) trigger"}; + Configurable cEvtRecINELgt0{"cEvtRecINELgt0", false, "MC event selection: require reconstructed INEL>0 condition"}; // ── Histogram registry ─────────────────────────────────────────────────── - HistogramRegistry allHistograms{ - "allHistograms", - {}, - OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry allHistograms{"allHistograms", {}, OutputObjHandlingPolicy::AnalysisObject}; // ============================================================ // init() @@ -390,270 +192,101 @@ struct Lambda1520Analysispo { const AxisSpec axisTPCdEdx(380, 10, 200, "#frac{dE}{dx}"); const AxisSpec axisVertexZ(120, -12, 12, "v_{z} (cm)"); const AxisSpec axisEventPlaneAngle(120, -3.14, 3.14, "#theta (rad)"); - const AxisSpec axisInvariantMass(numberOfInvMassBins, 1.4, 2.0, - "M_{inv} (GeV/c^{2})"); + const AxisSpec axisInvariantMass(numberOfInvMassBins, 1.4, 2.0, "M_{inv} (GeV/c^{2})"); AxisSpec axisOccupancy = {occupancyBins, "Track occupancy [-40,100]"}; AxisSpec axisDCAz = {dcaZMixingBins, "DCA_{z} (cm)"}; - allHistograms.add("Event/centralityVsOccupancy", - "Collision centrality vs track occupancy", kTH2F, - {axisCentralityPercent, axisOccupancy}); - allHistograms.add("Event/primaryVertexZ", - "Primary vertex z-position distribution", kTH1F, - {{100, -15., 15.}}); + allHistograms.add("Event/centralityVsOccupancy", "Collision centrality vs track occupancy", kTH2F, {axisCentralityPercent, axisOccupancy}); + allHistograms.add("Event/primaryVertexZ", "Primary vertex z-position distribution", kTH1F, {{100, -15., 15.}}); if (doprocessMix || doprocessMixDF || doprocessMixepDF) { - allHistograms.add( - "Event/mixingBins_centralityVsVtxZVsEventPlane", - "Event mixing bin occupancy: centrality vs vtxZ vs event plane", - kTH3F, {axisCentralityPercent, axisVertexZ, axisEventPlaneAngle}); + allHistograms.add("Event/mixingBins_centralityVsVtxZVsEventPlane", "Event mixing bin occupancy: centrality vs vtxZ vs event plane", kTH3F, {axisCentralityPercent, axisVertexZ, axisEventPlaneAngle}); } - allHistograms.add("QAbefore/trackEta", "Track pseudorapidity (before cuts)", - kTH1F, {{50, -1.0, 1.0}}); - allHistograms.add("QAbefore/trackPt", "Track pT (before cuts)", kTH1F, - {axisMomentumForPID}); - allHistograms.add("QAbefore/trackPhi", - "Track azimuthal angle (before cuts)", kTH1F, - {{72, 0, 6.2832}}); - allHistograms.add("QAbefore/trackEtaVsPhi", - "Track eta vs phi (before cuts)", kTH2F, - {axisPseudorapidity, {72, 0, 6.2832}}); - - allHistograms.add("QAbefore/Proton/tpcNSigmaVsMomentum", - "TPC nSigma proton vs momentum (before PID cuts)", kTH2F, - {axisMomentumForPID, axisTPCNSigma}); - allHistograms.add("QAbefore/Proton/tofNSigmaVsMomentum", - "TOF nSigma proton vs momentum (before PID cuts)", kTH2F, - {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAbefore/Proton/tofNSigmaVsTPCNSigma", - "TOF nSigma vs TPC nSigma proton (before PID cuts)", - kTH2F, {axisTPCNSigma, axisTOFNSigma}); - - allHistograms.add("QAbefore/Kaon/tpcNSigmaVsMomentum", - "TPC nSigma kaon vs momentum (before PID cuts)", kTH2F, - {axisMomentumForPID, axisTPCNSigma}); - allHistograms.add("QAbefore/Kaon/tofNSigmaVsMomentum", - "TOF nSigma kaon vs momentum (before PID cuts)", kTH2F, - {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAbefore/Kaon/tofNSigmaVsTPCNSigma", - "TOF nSigma vs TPC nSigma kaon (before PID cuts)", kTH2F, - {axisTPCNSigma, axisTOFNSigma}); - - allHistograms.add("QAafter/Proton/ptVsCentrality", - "Proton pT vs centrality (after cuts)", kTH2F, - {axisPtForPID, axisCentralityPercent}); - allHistograms.add("QAafter/Proton/dcaZVsPt", - "Proton DCAz vs pT (after cuts)", kTH2F, - {axisPtForPID, axisDCAz}); - allHistograms.add("QAafter/Proton/dcaXYVsPt", - "Proton DCAxy vs pT (after cuts)", kTH2F, - {axisPtForPID, axisDCAxy}); - allHistograms.add("QAafter/Proton/tpcDedxVsMomentum", - "Proton TPC dE/dx signal vs momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTPCdEdx}); - allHistograms.add("QAafter/Proton/tpcNSigmaVsPt", - "Proton TPC nSigma vs pT (after cuts)", kTH2F, - {axisPtForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Proton/tpcNSigmaPionContamVsPt", - "Proton track: TPC nSigma pion contamination check", - kTH2F, {axisPtForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Proton/tpcNSigmaKaonContamVsPt", - "Proton track: TPC nSigma kaon contamination check", - kTH2F, {axisPtForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Proton/tpcNSigmaVsMomentum", - "Proton TPC nSigma vs total momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Proton/tofNSigmaVsPt", - "Proton TOF nSigma vs pT (after cuts)", kTH2F, - {axisPtForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Proton/tofNSigmaVsMomentum", - "Proton TOF nSigma vs total momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Proton/tofNSigmaPionContamVsMomentum", - "Proton track: TOF nSigma pion contamination check", - kTH2F, {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Proton/tofNSigmaKaonContamVsMomentum", - "Proton track: TOF nSigma kaon contamination check", - kTH2F, {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Proton/tofNSigmaVsTPCNSigma", - "Proton TOF nSigma vs TPC nSigma (after cuts)", kTH2F, - {axisTPCNSigma, axisTOFNSigma}); - allHistograms.add("QAafter/Proton/tpcCrossedRowsVsPt", - "Proton TPC crossed rows vs pT", kTH2F, - {axisPtForPID, {200, 0, 200}}); - allHistograms.add("QAafter/Proton/tpcClustersFoundVsPt", - "Proton TPC clusters found vs pT", kTH2F, - {axisPtForPID, {200, 0, 200}}); - - allHistograms.add("QAafter/Kaon/ptVsCentrality", - "Kaon pT vs centrality (after cuts)", kTH2F, - {axisPtForPID, axisCentralityPercent}); - allHistograms.add("QAafter/Kaon/dcaZVsPt", "Kaon DCAz vs pT (after cuts)", - kTH2F, {axisPtForPID, axisDCAz}); - allHistograms.add("QAafter/Kaon/dcaXYVsPt", "Kaon DCAxy vs pT (after cuts)", - kTH2F, {axisPtForPID, axisDCAxy}); - allHistograms.add("QAafter/Kaon/tpcDedxVsMomentum", - "Kaon TPC dE/dx signal vs momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTPCdEdx}); - allHistograms.add("QAafter/Kaon/tpcNSigmaPionContamVsPt", - "Kaon track: TPC nSigma pion contamination check", kTH2F, - {axisPtForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum", - "Kaon track: TPC nSigma proton contamination check", - kTH2F, {axisMomentumForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Kaon/tpcNSigmaVsPt", - "Kaon TPC nSigma vs pT (after cuts)", kTH2F, - {axisPtForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Kaon/tpcNSigmaVsMomentum", - "Kaon TPC nSigma vs total momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTPCNSigma}); - allHistograms.add("QAafter/Kaon/tofNSigmaVsPt", - "Kaon TOF nSigma vs pT (after cuts)", kTH2F, - {axisPtForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Kaon/tofNSigmaVsMomentum", - "Kaon TOF nSigma vs total momentum (after cuts)", kTH2F, - {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Kaon/tofNSigmaPionContamVsMomentum", - "Kaon track: TOF nSigma pion contamination check", kTH2F, - {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Kaon/tofNSigmaProtonContamVsMomentum", - "Kaon track: TOF nSigma proton contamination check", - kTH2F, {axisMomentumForPID, axisTOFNSigma}); - allHistograms.add("QAafter/Kaon/tofNSigmaVsTPCNSigma", - "Kaon TOF nSigma vs TPC nSigma (after cuts)", kTH2F, - {axisTPCNSigma, axisTOFNSigma}); - allHistograms.add("QAafter/Kaon/tpcCrossedRowsVsPt", - "Kaon TPC crossed rows vs pT", kTH2F, - {axisPtForPID, {200, 0, 200}}); - allHistograms.add("QAafter/Kaon/tpcClustersFoundVsPt", - "Kaon TPC clusters found vs pT", kTH2F, - {axisPtForPID, {200, 0, 200}}); + allHistograms.add("QAbefore/trackEta", "Track pseudorapidity (before cuts)", kTH1F, {{50, -1.0, 1.0}}); + allHistograms.add("QAbefore/trackPt", "Track pT (before cuts)", kTH1F, {axisMomentumForPID}); + allHistograms.add("QAbefore/trackPhi", "Track azimuthal angle (before cuts)", kTH1F, {{72, 0, 6.2832}}); + allHistograms.add("QAbefore/trackEtaVsPhi", "Track eta vs phi (before cuts)", kTH2F, {axisPseudorapidity, {72, 0, 6.2832}}); + + allHistograms.add("QAbefore/Proton/tpcNSigmaVsMomentum", "TPC nSigma proton vs momentum (before PID cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAbefore/Proton/tofNSigmaVsMomentum", "TOF nSigma proton vs momentum (before PID cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAbefore/Proton/tofNSigmaVsTPCNSigma", "TOF nSigma vs TPC nSigma proton (before PID cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); + + allHistograms.add("QAbefore/Kaon/tpcNSigmaVsMomentum", "TPC nSigma kaon vs momentum (before PID cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAbefore/Kaon/tofNSigmaVsMomentum", "TOF nSigma kaon vs momentum (before PID cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAbefore/Kaon/tofNSigmaVsTPCNSigma", "TOF nSigma vs TPC nSigma kaon (before PID cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); + + allHistograms.add("QAafter/Proton/ptVsCentrality", "Proton pT vs centrality (after cuts)", kTH2F, {axisPtForPID, axisCentralityPercent}); + allHistograms.add("QAafter/Proton/dcaZVsPt", "Proton DCAz vs pT (after cuts)", kTH2F, {axisPtForPID, axisDCAz}); + allHistograms.add("QAafter/Proton/dcaXYVsPt", "Proton DCAxy vs pT (after cuts)", kTH2F, {axisPtForPID, axisDCAxy}); + allHistograms.add("QAafter/Proton/tpcDedxVsMomentum", "Proton TPC dE/dx signal vs momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCdEdx}); + allHistograms.add("QAafter/Proton/tpcNSigmaVsPt", "Proton TPC nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Proton/tpcNSigmaPionContamVsPt", "Proton track: TPC nSigma pion contamination check", kTH2F, {axisPtForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Proton/tpcNSigmaKaonContamVsPt", "Proton track: TPC nSigma kaon contamination check", kTH2F, {axisPtForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Proton/tpcNSigmaVsMomentum", "Proton TPC nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaVsPt", "Proton TOF nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaVsMomentum", "Proton TOF nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaPionContamVsMomentum", "Proton track: TOF nSigma pion contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaKaonContamVsMomentum", "Proton track: TOF nSigma kaon contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaVsTPCNSigma", "Proton TOF nSigma vs TPC nSigma (after cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tpcCrossedRowsVsPt", "Proton TPC crossed rows vs pT", kTH2F, {axisPtForPID, {200, 0, 200}}); + allHistograms.add("QAafter/Proton/tpcClustersFoundVsPt", "Proton TPC clusters found vs pT", kTH2F, {axisPtForPID, {200, 0, 200}}); + + allHistograms.add("QAafter/Kaon/ptVsCentrality", "Kaon pT vs centrality (after cuts)", kTH2F, {axisPtForPID, axisCentralityPercent}); + allHistograms.add("QAafter/Kaon/dcaZVsPt", "Kaon DCAz vs pT (after cuts)", kTH2F, {axisPtForPID, axisDCAz}); + allHistograms.add("QAafter/Kaon/dcaXYVsPt", "Kaon DCAxy vs pT (after cuts)", kTH2F, {axisPtForPID, axisDCAxy}); + allHistograms.add("QAafter/Kaon/tpcDedxVsMomentum", "Kaon TPC dE/dx signal vs momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCdEdx}); + allHistograms.add("QAafter/Kaon/tpcNSigmaPionContamVsPt", "Kaon track: TPC nSigma pion contamination check", kTH2F, {axisPtForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum", "Kaon track: TPC nSigma proton contamination check", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Kaon/tpcNSigmaVsPt", "Kaon TPC nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Kaon/tpcNSigmaVsMomentum", "Kaon TPC nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaVsPt", "Kaon TOF nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaVsMomentum", "Kaon TOF nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaPionContamVsMomentum", "Kaon track: TOF nSigma pion contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaProtonContamVsMomentum", "Kaon track: TOF nSigma proton contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaVsTPCNSigma", "Kaon TOF nSigma vs TPC nSigma (after cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tpcCrossedRowsVsPt", "Kaon TPC crossed rows vs pT", kTH2F, {axisPtForPID, {200, 0, 200}}); + allHistograms.add("QAafter/Kaon/tpcClustersFoundVsPt", "Kaon TPC clusters found vs pT", kTH2F, {axisPtForPID, {200, 0, 200}}); if (!doprocessMC) { - allHistograms.add( - "Analysis/invMass_UnlikeSign_ProtonPlusKaonMinus", - "Invariant mass: p^{+}K^{-} (Lambda(1520) signal)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_UnlikeSign_ProtonMinusKaonPlus", - "Invariant mass: p^{-}K^{+} (anti-Lambda(1520) signal)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_LikeSign_ProtonPlusKaonPlus", - "Invariant mass: p^{+}K^{+} (like-sign background)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_LikeSign_ProtonMinusKaonMinus", - "Invariant mass: p^{-}K^{-} (like-sign background)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Rotated_ProtonPlusKaonMinus", - "Invariant mass: rotational background (Lambda(1520))", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Rotated_ProtonMinusKaonPlus", - "Invariant mass: rotational background (anti-Lambda(1520))", - kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Mixed_ProtonPlusKaonMinus", - "Invariant mass: mixed events p^{+}K^{-} (background)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Mixed_ProtonMinusKaonPlus", - "Invariant mass: mixed events p^{-}K^{+} (background)", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Mixed_LikeSign_PlusPlus", - "Invariant mass: mixed events like-sign ++", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); - allHistograms.add( - "Analysis/invMass_Mixed_LikeSign_MinusMinus", - "Invariant mass: mixed events like-sign --", kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_UnlikeSign_ProtonPlusKaonMinus", "Invariant mass: p^{+}K^{-} (Lambda(1520) signal)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_UnlikeSign_ProtonMinusKaonPlus", "Invariant mass: p^{-}K^{+} (anti-Lambda(1520) signal)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_LikeSign_ProtonPlusKaonPlus", "Invariant mass: p^{+}K^{+} (like-sign background)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_LikeSign_ProtonMinusKaonMinus", "Invariant mass: p^{-}K^{-} (like-sign background)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Rotated_ProtonPlusKaonMinus", "Invariant mass: rotational background (Lambda(1520))", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Rotated_ProtonMinusKaonPlus", "Invariant mass: rotational background (anti-Lambda(1520))", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Mixed_ProtonPlusKaonMinus", "Invariant mass: mixed events p^{+}K^{-} (background)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Mixed_ProtonMinusKaonPlus", "Invariant mass: mixed events p^{-}K^{+} (background)", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Mixed_LikeSign_PlusPlus", "Invariant mass: mixed events like-sign ++", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); + allHistograms.add("Analysis/invMass_Mixed_LikeSign_MinusMinus", "Invariant mass: mixed events like-sign --", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent, axisOccupancy}); } if (doprocessMC) { - allHistograms.add( - "Event/mcEventSelectionCutflow", - "MC event selection cutflow (how many events pass each cut)", kTH1F, - {{7, 0, 7}}); - allHistograms.add("QAChecks/protonRecoLevelPt", - "Reconstructed proton pT (after PID cuts) - MC", kTH1F, - {axisPtForPID}); - allHistograms.add("QAChecks/kaonRecoLevelPt", - "Reconstructed kaon pT (after PID cuts) - MC", kTH1F, - {axisPtForPID}); - allHistograms.add("QAChecks/protonGenLevelPt", - "Generated proton pT (truth level) - MC", kTH1F, - {axisPtForPID}); - allHistograms.add("QAChecks/kaonGenLevelPt", - "Generated kaon pT (truth level) - MC", kTH1F, - {axisPtForPID}); - allHistograms.add( - "Analysis/mcGenerated_Lambda1520", - "Generated Lambda(1520) invariant mass vs pT vs centrality", - kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); - allHistograms.add( - "Analysis/mcGenerated_AntiLambda1520", - "Generated anti-Lambda(1520) invariant mass vs pT vs centrality", - kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); - allHistograms.add( - "Analysis/mcReconstructed_Lambda1520", - "Reconstructed Lambda(1520) invariant mass vs pT vs centrality - MC", - kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); - allHistograms.add("Analysis/mcReconstructed_AntiLambda1520", - "Reconstructed anti-Lambda(1520) invariant mass vs pT " - "vs centrality - MC", - kTHnSparseF, - {axisInvariantMass, axisPt, axisCentralityPercent}); - allHistograms.add("Analysis/mcMassResolution_Lambda1520", - "Mass resolution (Mreco - Mgen) vs pT - Lambda(1520)", - kTHnSparseF, - {{200, -0.05, 0.05}, axisPt, axisCentralityPercent}); - allHistograms.add( - "Analysis/mcMassResolution_AntiLambda1520", - "Mass resolution (Mreco - Mgen) vs pT - anti-Lambda(1520)", - kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCentralityPercent}); + allHistograms.add("Event/mcEventSelectionCutflow", "MC event selection cutflow (how many events pass each cut)", kTH1F, {{7, 0, 7}}); + allHistograms.add("QAChecks/protonRecoLevelPt", "Reconstructed proton pT (after PID cuts) - MC", kTH1F, {axisPtForPID}); + allHistograms.add("QAChecks/kaonRecoLevelPt", "Reconstructed kaon pT (after PID cuts) - MC", kTH1F, {axisPtForPID}); + allHistograms.add("QAChecks/protonGenLevelPt", "Generated proton pT (truth level) - MC", kTH1F, {axisPtForPID}); + allHistograms.add("QAChecks/kaonGenLevelPt", "Generated kaon pT (truth level) - MC", kTH1F, {axisPtForPID}); + allHistograms.add("Analysis/mcGenerated_Lambda1520", "Generated Lambda(1520) invariant mass vs pT vs centrality", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); + allHistograms.add("Analysis/mcGenerated_AntiLambda1520", "Generated anti-Lambda(1520) invariant mass vs pT vs centrality", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); + allHistograms.add("Analysis/mcReconstructed_Lambda1520", "Reconstructed Lambda(1520) invariant mass vs pT vs centrality - MC", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); + allHistograms.add("Analysis/mcReconstructed_AntiLambda1520", "Reconstructed anti-Lambda(1520) invariant mass vs pT vs centrality - MC", kTHnSparseF, {axisInvariantMass, axisPt, axisCentralityPercent}); + allHistograms.add("Analysis/mcMassResolution_Lambda1520", "Mass resolution (Mreco - Mgen) vs pT - Lambda(1520)", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCentralityPercent}); + allHistograms.add("Analysis/mcMassResolution_AntiLambda1520", "Mass resolution (Mreco - Mgen) vs pT - anti-Lambda(1520)", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCentralityPercent}); } if (doprocessMCGen) { - allHistograms.add("SignalLoss/mcEventSelectionCutflow", - "MC event selection cutflow (signal loss study)", kTH1F, - {{7, 0, 7}}); - allHistograms.add("SignalLoss/mTScaled_fromProton", - "mT-scaled Lambda(1520) pT from proton parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add( - "SignalLoss/mTScaled_fromAntiProton", - "mT-scaled anti-Lambda(1520) pT from anti-proton parent", kTHnSparseF, - {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromLambda0", - "mT-scaled Lambda(1520) pT from Lambda0 parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add( - "SignalLoss/mTScaled_fromAntiLambda0", - "mT-scaled anti-Lambda(1520) pT from anti-Lambda0 parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromXiMinus", - "mT-scaled Lambda(1520) pT from Xi- parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromXiPlus", - "mT-scaled anti-Lambda(1520) pT from Xi+ parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromXi0", - "mT-scaled Lambda(1520) pT from Xi0 parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromAntiXi0", - "mT-scaled anti-Lambda(1520) pT from anti-Xi0 parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromOmegaMinus", - "mT-scaled Lambda(1520) pT from Omega- parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); - allHistograms.add("SignalLoss/mTScaled_fromOmegaPlus", - "mT-scaled anti-Lambda(1520) pT from Omega+ parent", - kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mcEventSelectionCutflow", "MC event selection cutflow (signal loss study)", kTH1F, {{7, 0, 7}}); + allHistograms.add("SignalLoss/mTScaled_fromProton", "mT-scaled Lambda(1520) pT from proton parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromAntiProton", "mT-scaled anti-Lambda(1520) pT from anti-proton parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromLambda0", "mT-scaled Lambda(1520) pT from Lambda0 parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromAntiLambda0", "mT-scaled anti-Lambda(1520) pT from anti-Lambda0 parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromXiMinus", "mT-scaled Lambda(1520) pT from Xi- parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromXiPlus", "mT-scaled anti-Lambda(1520) pT from Xi+ parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromXi0", "mT-scaled Lambda(1520) pT from Xi0 parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromAntiXi0", "mT-scaled anti-Lambda(1520) pT from anti-Xi0 parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromOmegaMinus", "mT-scaled Lambda(1520) pT from Omega- parent", kTHnSparseF, {axisPt, axisCentralityPercent}); + allHistograms.add("SignalLoss/mTScaled_fromOmegaPlus", "mT-scaled anti-Lambda(1520) pT from Omega+ parent", kTHnSparseF, {axisPt, axisCentralityPercent}); } } @@ -769,7 +402,7 @@ struct Lambda1520Analysispo { if (track.tofNSigmaPr() < minTOFNSigmaProton) return false; - if (combinedNSigmaCutProton < 0 && totalMomentum >= minTrackMomentum) { + if (combinedNSigmaCutProton < 0 && totalMomentum >= minProtonMomentum) { for (int i = 0; i < nTOFBins - 1; ++i) { if (totalMomentum >= tofMomBins[i] && totalMomentum < tofMomBins[i + 1] && @@ -786,7 +419,7 @@ struct Lambda1520Analysispo { tpcPIDPassed = true; } - if ((combinedNSigmaCutProton > 0) && totalMomentum >= minTrackMomentum && + if ((combinedNSigmaCutProton > 0) && totalMomentum >= minProtonMomentum && (combinedNSigProton < circularCutSquared && combinedNSigPion > circularRejCutSquared && combinedNSigKaon > circularRejCutSquared)) { @@ -794,7 +427,7 @@ struct Lambda1520Analysispo { tpcPIDPassed = true; } - if (totalMomentum < minTrackMomentum && + if (totalMomentum < minProtonMomentum && tpcNSigProton < maxTPCNSigmaProton) { tofPIDPassed = true; tpcPIDPassed = true; @@ -853,7 +486,7 @@ struct Lambda1520Analysispo { if (track.tofNSigmaKa() < minTOFNSigmaKaon) return false; - if (combinedNSigmaCutKaon < 0 && totalMomentum >= minTrackMomentum) { + if (combinedNSigmaCutKaon < 0 && totalMomentum >= minKaonMomentum) { for (int i = 0; i < nTOFBins - 1; ++i) { if (totalMomentum >= tofMomBins[i] && totalMomentum < tofMomBins[i + 1] && @@ -870,7 +503,7 @@ struct Lambda1520Analysispo { tpcPIDPassed = true; } - if ((combinedNSigmaCutKaon > 0) && totalMomentum >= minTrackMomentum && + if ((combinedNSigmaCutKaon > 0) && totalMomentum >= minKaonMomentum && (combinedNSigKaon < circularCutSquared && combinedNSigPion > circularRejCutSquared && combinedNSigProton > circularRejCutSquared)) { @@ -878,7 +511,7 @@ struct Lambda1520Analysispo { tpcPIDPassed = true; } - if (totalMomentum < minTrackMomentum && tpcNSigKaon < maxTPCNSigmaKaon) { + if (totalMomentum < minKaonMomentum && tpcNSigKaon < maxTPCNSigmaKaon) { tofPIDPassed = true; tpcPIDPassed = true; } @@ -931,24 +564,18 @@ struct Lambda1520Analysispo { if (!isMixedEvent) { auto tpcNSigProton = protonTrack.tpcNSigmaPr(); - allHistograms.fill(HIST("QAbefore/Proton/tpcNSigmaVsMomentum"), - protonTotalMomentum, tpcNSigProton); + allHistograms.fill(HIST("QAbefore/Proton/tpcNSigmaVsMomentum"), protonTotalMomentum, tpcNSigProton); if (protonTrack.hasTOF()) { auto tofNSigProton = protonTrack.tofNSigmaPr(); - allHistograms.fill(HIST("QAbefore/Proton/tofNSigmaVsMomentum"), - protonTotalMomentum, tofNSigProton); - allHistograms.fill(HIST("QAbefore/Proton/tofNSigmaVsTPCNSigma"), - tpcNSigProton, tofNSigProton); + allHistograms.fill(HIST("QAbefore/Proton/tofNSigmaVsMomentum"), protonTotalMomentum, tofNSigProton); + allHistograms.fill(HIST("QAbefore/Proton/tofNSigmaVsTPCNSigma"), tpcNSigProton, tofNSigProton); } auto tpcNSigKaon = kaonTrack.tpcNSigmaKa(); - allHistograms.fill(HIST("QAbefore/Kaon/tpcNSigmaVsMomentum"), - kaonTotalMomentum, tpcNSigKaon); + allHistograms.fill(HIST("QAbefore/Kaon/tpcNSigmaVsMomentum"), kaonTotalMomentum, tpcNSigKaon); if (kaonTrack.hasTOF()) { auto tofNSigKaon = kaonTrack.tofNSigmaKa(); - allHistograms.fill(HIST("QAbefore/Kaon/tofNSigmaVsMomentum"), - kaonTotalMomentum, tofNSigKaon); - allHistograms.fill(HIST("QAbefore/Kaon/tofNSigmaVsTPCNSigma"), - tpcNSigKaon, tofNSigKaon); + allHistograms.fill(HIST("QAbefore/Kaon/tofNSigmaVsMomentum"), kaonTotalMomentum, tofNSigKaon); + allHistograms.fill(HIST("QAbefore/Kaon/tofNSigmaVsTPCNSigma"), tpcNSigKaon, tofNSigKaon); } } @@ -976,80 +603,47 @@ struct Lambda1520Analysispo { auto ptProton = protonTrack.pt(); auto tpcNSigProton = protonTrack.tpcNSigmaPr(); - allHistograms.fill(HIST("QAafter/Proton/ptVsCentrality"), ptProton, - centralityPercent); - allHistograms.fill(HIST("QAafter/Proton/dcaZVsPt"), ptProton, - protonTrack.dcaZ()); - allHistograms.fill(HIST("QAafter/Proton/dcaXYVsPt"), ptProton, - protonTrack.dcaXY()); - allHistograms.fill(HIST("QAafter/Proton/tpcDedxVsMomentum"), - protonTotalMomentum, protonTrack.tpcSignal()); - allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaPionContamVsPt"), - protonTotalMomentum, protonTrack.tpcNSigmaPi()); - allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaKaonContamVsPt"), - protonTotalMomentum, protonTrack.tpcNSigmaKa()); - allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsMomentum"), - protonTotalMomentum, tpcNSigProton); - allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsPt"), ptProton, - tpcNSigProton); - allHistograms.fill(HIST("QAafter/Proton/tpcCrossedRowsVsPt"), ptProton, - protonTrack.tpcNClsCrossedRows()); - allHistograms.fill(HIST("QAafter/Proton/tpcClustersFoundVsPt"), - ptProton, protonTrack.tpcNClsFound()); + allHistograms.fill(HIST("QAafter/Proton/ptVsCentrality"), ptProton, centralityPercent); + allHistograms.fill(HIST("QAafter/Proton/dcaZVsPt"), ptProton, protonTrack.dcaZ()); + allHistograms.fill(HIST("QAafter/Proton/dcaXYVsPt"), ptProton, protonTrack.dcaXY()); + allHistograms.fill(HIST("QAafter/Proton/tpcDedxVsMomentum"), protonTotalMomentum, protonTrack.tpcSignal()); + allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaPionContamVsPt"), protonTotalMomentum, protonTrack.tpcNSigmaPi()); + allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaKaonContamVsPt"), protonTotalMomentum, protonTrack.tpcNSigmaKa()); + allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsMomentum"), protonTotalMomentum, tpcNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsPt"), ptProton, tpcNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tpcCrossedRowsVsPt"), ptProton, protonTrack.tpcNClsCrossedRows()); + allHistograms.fill(HIST("QAafter/Proton/tpcClustersFoundVsPt"), ptProton, protonTrack.tpcNClsFound()); if (!useTPCOnlyPID && protonTrack.hasTOF()) { auto tofNSigProton = protonTrack.tofNSigmaPr(); - allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsMomentum"), - protonTotalMomentum, tofNSigProton); - allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsPt"), ptProton, - tofNSigProton); - allHistograms.fill( - HIST("QAafter/Proton/tofNSigmaPionContamVsMomentum"), - protonTotalMomentum, protonTrack.tofNSigmaPi()); - allHistograms.fill( - HIST("QAafter/Proton/tofNSigmaKaonContamVsMomentum"), - protonTotalMomentum, protonTrack.tofNSigmaKa()); - allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsTPCNSigma"), - tpcNSigProton, tofNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsMomentum"), protonTotalMomentum, tofNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsPt"), ptProton, tofNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaPionContamVsMomentum"), protonTotalMomentum, protonTrack.tofNSigmaPi()); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaKaonContamVsMomentum"), protonTotalMomentum, protonTrack.tofNSigmaKa()); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsTPCNSigma"), tpcNSigProton, tofNSigProton); } auto ptKaon = kaonTrack.pt(); auto tpcNSigKaon = kaonTrack.tpcNSigmaKa(); - allHistograms.fill(HIST("QAafter/Kaon/ptVsCentrality"), ptKaon, - centralityPercent); - allHistograms.fill(HIST("QAafter/Kaon/dcaZVsPt"), ptKaon, - kaonTrack.dcaZ()); - allHistograms.fill(HIST("QAafter/Kaon/dcaXYVsPt"), ptKaon, - kaonTrack.dcaXY()); - allHistograms.fill(HIST("QAafter/Kaon/tpcDedxVsMomentum"), - kaonTotalMomentum, kaonTrack.tpcSignal()); - allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaPionContamVsPt"), - kaonTotalMomentum, kaonTrack.tpcNSigmaPi()); - allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum"), - kaonTotalMomentum, kaonTrack.tpcNSigmaPr()); - allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsMomentum"), - kaonTotalMomentum, tpcNSigKaon); - allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsPt"), ptKaon, - tpcNSigKaon); - allHistograms.fill(HIST("QAafter/Kaon/tpcCrossedRowsVsPt"), ptKaon, - kaonTrack.tpcNClsCrossedRows()); - allHistograms.fill(HIST("QAafter/Kaon/tpcClustersFoundVsPt"), ptKaon, - kaonTrack.tpcNClsFound()); + allHistograms.fill(HIST("QAafter/Kaon/ptVsCentrality"), ptKaon, centralityPercent); + allHistograms.fill(HIST("QAafter/Kaon/dcaZVsPt"), ptKaon, kaonTrack.dcaZ()); + allHistograms.fill(HIST("QAafter/Kaon/dcaXYVsPt"), ptKaon, kaonTrack.dcaXY()); + allHistograms.fill(HIST("QAafter/Kaon/tpcDedxVsMomentum"), kaonTotalMomentum, kaonTrack.tpcSignal()); + allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaPionContamVsPt"), kaonTotalMomentum, kaonTrack.tpcNSigmaPi()); + allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum"), kaonTotalMomentum, kaonTrack.tpcNSigmaPr()); + allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsMomentum"), kaonTotalMomentum, tpcNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsPt"), ptKaon, tpcNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tpcCrossedRowsVsPt"), ptKaon, kaonTrack.tpcNClsCrossedRows()); + allHistograms.fill(HIST("QAafter/Kaon/tpcClustersFoundVsPt"), ptKaon, kaonTrack.tpcNClsFound()); if (!useTPCOnlyPID && kaonTrack.hasTOF()) { auto tofNSigKaon = kaonTrack.tofNSigmaKa(); - allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsMomentum"), - kaonTotalMomentum, tofNSigKaon); - allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsPt"), ptKaon, - tofNSigKaon); - allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaPionContamVsMomentum"), - kaonTotalMomentum, kaonTrack.tofNSigmaPi()); - allHistograms.fill( - HIST("QAafter/Kaon/tofNSigmaProtonContamVsMomentum"), - kaonTotalMomentum, kaonTrack.tofNSigmaPr()); - allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsTPCNSigma"), - tpcNSigKaon, tofNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsMomentum"), kaonTotalMomentum, tofNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsPt"), ptKaon, tofNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaPionContamVsMomentum"), kaonTotalMomentum, kaonTrack.tofNSigmaPi()); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaProtonContamVsMomentum"), kaonTotalMomentum, kaonTrack.tofNSigmaPr()); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsTPCNSigma"), tpcNSigKaon, tofNSigKaon); } } @@ -1060,13 +654,9 @@ struct Lambda1520Analysispo { std::array momKaon = {pxKaon, pyKaon, pzKaon}; std::array, 2> bothMomenta = {momProton, momKaon}; - float pairInvMass = - RecoDecay::m(bothMomenta, std::array{MassProton, MassKaonCharged}); - float pairPt = - RecoDecay::pt(std::array{pxProton + pxKaon, pyProton + pyKaon}); - float pairRapidity = RecoDecay::y( - std::array{pxProton + pxKaon, pyProton + pyKaon, pzProton + pzKaon}, - pairInvMass); + float pairInvMass = RecoDecay::m(bothMomenta, std::array{MassProton, MassKaonCharged}); + float pairPt = RecoDecay::pt(std::array{pxProton + pxKaon, pyProton + pyKaon}); + float pairRapidity = RecoDecay::y(std::array{pxProton + pxKaon, pyProton + pyKaon, pzProton + pzKaon}, pairInvMass); if (pairRapidity < minPairRapidity || pairRapidity > maxPairRapidity) continue; @@ -1074,13 +664,9 @@ struct Lambda1520Analysispo { if constexpr (!isMixedEvent && !isMCAnalysis) { if (protonTrack.sign() * kaonTrack.sign() < 0) { if (protonTrack.sign() > 0) - allHistograms.fill( - HIST("Analysis/invMass_UnlikeSign_ProtonPlusKaonMinus"), - pairInvMass, pairPt, centralityPercent, occupancyValue); + allHistograms.fill(HIST("Analysis/invMass_UnlikeSign_ProtonPlusKaonMinus"), pairInvMass, pairPt, centralityPercent, occupancyValue); else - allHistograms.fill( - HIST("Analysis/invMass_UnlikeSign_ProtonMinusKaonPlus"), - pairInvMass, pairPt, centralityPercent, occupancyValue); + allHistograms.fill(HIST("Analysis/invMass_UnlikeSign_ProtonMinusKaonPlus"), pairInvMass, pairPt, centralityPercent, occupancyValue); if (enableRotationalBackground) { for (int iRot = 0; iRot < numberOfRotations; iRot++) { @@ -1236,6 +822,9 @@ struct Lambda1520Analysispo { void processData(ResonanceCollisionsWithEP::iterator const& collision, ResonanceTrackTable const& tracks) { + if (cEvtRecINELgt0 && !collision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + allHistograms.fill(HIST("Event/centralityVsOccupancy"), collision.cent(), 100); allHistograms.fill(HIST("Event/primaryVertexZ"), collision.posZ()); @@ -1270,7 +859,7 @@ struct Lambda1520Analysispo { return; allHistograms.fill(HIST("Event/mcEventSelectionCutflow"), 4); - if (mcRequireRecoINELgt0 && !collision.isRecINELgt0()) + if (cEvtRecINELgt0 && !collision.isRecINELgt0()) return; allHistograms.fill(HIST("Event/mcEventSelectionCutflow"), 5); @@ -1370,7 +959,7 @@ struct Lambda1520Analysispo { if (mcRequireSel8 && !collision.isInSel8()) return; allHistograms.fill(HIST("SignalLoss/mcEventSelectionCutflow"), 4); - if (mcRequireRecoINELgt0 && !collision.isRecINELgt0()) + if (cEvtRecINELgt0 && !collision.isRecINELgt0()) return; allHistograms.fill(HIST("SignalLoss/mcEventSelectionCutflow"), 5); if (mcRequireAfterAllCuts && !collision.isInAfterAllCuts()) @@ -1479,6 +1068,8 @@ struct Lambda1520Analysispo { // FIX const-ref-in-for-loop: const auto& structured binding for (const auto& [col1, tracks1, col2, tracks2] : eventPairs) { + if (cEvtRecINELgt0 && !col1.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; allHistograms.fill(HIST("Event/mixingBins_centralityVsVtxZVsEventPlane"), col1.cent(), col1.posZ(), col1.evtPl()); fillInvariantMassHistograms(tracks1, tracks2, col1.cent()); @@ -1503,6 +1094,8 @@ struct Lambda1520Analysispo { if (doprocessData) LOG(error) << "Disable processData() first when using processDatadf()!"; + if (cEvtRecINELgt0 && !collision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; auto occupancyValue = 100; if (applyOccupancyInTimeRangeCut) occupancyValue = collision.trackOccupancyInTimeRange(); @@ -1538,6 +1131,8 @@ struct Lambda1520Analysispo { // FIX const-ref-in-for-loop: const auto& structured binding for (const auto& [col1, tracks1, col2, tracks2] : eventPairs) { + if (cEvtRecINELgt0 && !col1.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; auto occupancyValue = 100; if (applyOccupancyInTimeRangeCut) occupancyValue = col1.trackOccupancyInTimeRange(); From d897bc6935bcf0743a0457cba3b878252385e8b4 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Fri, 8 May 2026 22:41:43 +0200 Subject: [PATCH 105/449] [Common] Add example mult calib for pp using derived data (#16173) Co-authored-by: ALICE Builder --- Common/Tasks/CMakeLists.txt | 5 + Common/Tasks/centralityStudypp.cxx | 405 +++++++++++++++++++++++++++++ 2 files changed, 410 insertions(+) create mode 100644 Common/Tasks/centralityStudypp.cxx diff --git a/Common/Tasks/CMakeLists.txt b/Common/Tasks/CMakeLists.txt index e60d7838882..5c09a5e1d0d 100644 --- a/Common/Tasks/CMakeLists.txt +++ b/Common/Tasks/CMakeLists.txt @@ -84,6 +84,11 @@ o2physics_add_dpl_workflow(centrality-study PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(centrality-study-pp + SOURCES centralityStudypp.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flow-test SOURCES flowTest.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx new file mode 100644 index 00000000000..68d2e1c947c --- /dev/null +++ b/Common/Tasks/centralityStudypp.cxx @@ -0,0 +1,405 @@ +// 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. +// +// This task is dedicated to percentile calibration and event +// selection studies in pp collisions using derived data based on the +// multCentTable output + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +using BCsWithRun3Matchings = soa::Join; +#define getHist(type, name) std::get>(histPointers[name]) + +struct centralityStudypp { + // Raw multiplicities + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::map histPointers; + std::string histPath; + Service ccdb; + int mRunNumber; + uint64_t startOfRunTimestamp; + + // vertex Z equalization + TList* hCalibObjects; + TProfile* hVtxZFV0A; + TProfile* hVtxZFT0A; + TProfile* hVtxZFT0C; + TProfile* hVtxZNTracks; + TProfile* hVtxZNGlobals; + TProfile* hVtxZMFT; + TProfile* hVtxZFDDA; + TProfile* hVtxZFDDC; + + // Configurables + Configurable do2DPlots{"do2DPlots", true, "0 - no, 1 - yes"}; + // _______________________________________ + // event selection criteria + Configurable applyVertexZEqualization{"applyVertexZEqualization", false, "0 - no, 1 - yes"}; + Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; + Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; + Configurable requireINELgtZERO{"requireINELgtZERO", true, "0 no, 1 - yes"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", false, "reject events at ITS ROF border"}; + Configurable rejectTFBorder{"rejectTFBorder", false, "reject events at TF border"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", false, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference"}; + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC"}; + + // Configurable Axes for 2d plots, etc + // ConfigurableAxis axisMultFV0A{"axisMultFV0A", {1000, 0, 100000}, "FV0A amplitude"}; + // ConfigurableAxis axisMultFT0A{"axisMultFT0A", {1000, 0, 100000}, "FT0A amplitude"}; + // ConfigurableAxis axisMultFT0C{"axisMultFT0C", {1000, 0, 100000}, "FT0C amplitude"}; + // ConfigurableAxis axisMultFT0M{"axisMultFT0M", {1000, 0, 100000}, "FT0M amplitude"}; + // ConfigurableAxis axisMultFDDA{"axisMultFDDA", {1000, 0, 100000}, "FDDA amplitude"}; + // ConfigurableAxis axisMultFDDC{"axisMultFDDC", {1000, 0, 100000}, "FDDC amplitude"}; + // ConfigurableAxis axisMultPVContributors{"axisMultPVContributors", {200, 0, 6000}, "Number of PV Contributors"}; + // ConfigurableAxis axisMultGlobalTracks{"axisMultGlobalTracks", {500, 0, 5000}, "Number of global tracks"}; + // ConfigurableAxis axisMultMFTTracks{"axisMultMFTTracks", {500, 0, 5000}, "Number of MFT tracks"}; + + // For one-dimensional plots, where binning is no issue + ConfigurableAxis axisMultUltraFineFV0A{"axisMultUltraFineFV0A", {60000, 0, 60000}, "FV0A amplitude"}; + ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; + ConfigurableAxis axisMultUltraFineFT0C{"axisMultUltraFineFT0C", {60000, 0, 60000}, "FT0C amplitude"}; + ConfigurableAxis axisMultUltraFineFT0A{"axisMultUltraFineFT0A", {60000, 0, 60000}, "FT0A amplitude"}; + ConfigurableAxis axisMultUltraFinePVContributors{"axisMultUltraFinePVContributors", {10000, 0, 10000}, "Number of PV Contributors"}; + ConfigurableAxis axisMultUltraFineGlobalTracks{"axisMultUltraFineGlobalTracks", {5000, 0, 5000}, "Number of global tracks"}; + ConfigurableAxis axisMultUltraFineMFTTracks{"axisMultUltraFineMFTTracks", {5000, 0, 5000}, "Number of MFT tracks"}; + // For profile Z + ConfigurableAxis axisPVz{"axisPVz", {400, -20.0f, +20.0f}, "PVz (cm)"}; + ConfigurableAxis axisZN{"axisZN", {1100, -50.0f, +500.0f}, "ZN"}; + + // ccdb matters + Configurable ccdbURL{"ccdbURL", "http://alice-ccdb.cern.ch", "ccdb url"}; + Configurable pathGRPECSObject{"pathGRPECSObject", "GLO/Config/GRPECS", "Path to GRPECS object"}; + Configurable pathVertexZ{"pathVertexZ", "Users/d/ddobrigk/Centrality/Calibration", "Path to vertexZ profiles"}; + + void init(InitContext&) + { + hCalibObjects = nullptr; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZNTracks = nullptr; + hVtxZNGlobals = nullptr; + hVtxZMFT = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + + const AxisSpec axisCollisions{100, -0.5f, 99.5f, "Number of collisions"}; + histos.add("hCollisionSelection", "hCollisionSelection", kTH1D, {{20, -0.5f, +19.5f}}); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(6, "kIsVertexITSTPC"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(11, "Neighbour rejection"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(12, "no ITS in-ROF pileup (standard)"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(13, "no ITS in-ROF pileup (strict)"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(14, "is UPC event"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(15, "rejectCollInTimeRangeNarrow"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(16, "em/upc rejection"); + histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(17, "isFlangeEvent"); + + histos.add("hFT0A_Collisions", "hFT0A_Collisions", kTH1D, {axisMultUltraFineFT0A}); + histos.add("hFT0C_Collisions", "hFT0C_Collisions", kTH1D, {axisMultUltraFineFT0C}); + histos.add("hFT0M_Collisions", "hFT0M_Collisions", kTH1D, {axisMultUltraFineFT0M}); + histos.add("hFV0A_Collisions", "hFV0A_Collisions", kTH1D, {axisMultUltraFineFV0A}); + histos.add("hNGlobalTracks", "hNGlobalTracks", kTH1D, {axisMultUltraFineGlobalTracks}); + histos.add("hNMFTTracks", "hNMFTTracks", kTH1D, {axisMultUltraFineMFTTracks}); + histos.add("hNPVContributors", "hNPVContributors", kTH1D, {axisMultUltraFinePVContributors}); + + histos.add("hFT0AvsPVz_Collisions", "hFT0AvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hFT0CvsPVz_Collisions", "hFT0CvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hFV0AvsPVz_Collisions", "hFV0AvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hNGlobalTracksvsPVz_Collisions", "hNGlobalTracksvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hNMFTTracksvsPVz_Collisions", "hNMFTTracksvsPVz_Collisions", kTProfile, {axisPVz}); + } + + template + void initRun(const TCollision& collision) + { + if (mRunNumber == collision.multRunNumber()) { + return; + } + + mRunNumber = collision.multRunNumber(); + LOGF(info, "Setting up for run: %i", mRunNumber); + + if (applyVertexZEqualization.value) { + // acquire vertex-Z equalization histograms if requested + LOGF(info, "Acquiring vertex-Z profiles for run %i", mRunNumber); + hCalibObjects = ccdb->getForRun(pathVertexZ, mRunNumber); + + hVtxZFV0A = static_cast(hCalibObjects->FindObject("hVtxZFV0A")); + hVtxZFT0A = static_cast(hCalibObjects->FindObject("hVtxZFT0A")); + hVtxZFT0C = static_cast(hCalibObjects->FindObject("hVtxZFT0C")); + // hVtxZFDDA = static_cast(hCalibObjects->FindObject("hVtxZFDDA")); + // hVtxZFDDC = static_cast(hCalibObjects->FindObject("hVtxZFDDC")); + hVtxZNTracks = static_cast(hCalibObjects->FindObject("hVtxZNTracksPV")); + hVtxZNGlobals = static_cast(hCalibObjects->FindObject("hVtxZNGlobals")); + hVtxZMFT = static_cast(hCalibObjects->FindObject("hVtxZMFT")); + + // Capture error + if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZNTracks || !hVtxZNGlobals || !hVtxZMFT) { + LOGF(error, "Problem loading CCDB objects! Please check"); + } + } + + histPath = std::format("Run_{}/", mRunNumber); + + histPointers.insert({histPath + "hCollisionSelection", histos.add((histPath + "hCollisionSelection").c_str(), "hCollisionSelection", {kTH1D, {{20, -0.5f, +19.5f}}})}); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(1, "All collisions"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(2, "sel8 cut"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(3, "posZ cut"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(6, "kIsVertexITSTPC"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(11, "Pass INEL > 0"); + + histPointers.insert({histPath + "hFT0C_Collisions", histos.add((histPath + "hFT0C_Collisions").c_str(), "hFT0C_Collisions", {kTH1D, {{axisMultUltraFineFT0C}}})}); + histPointers.insert({histPath + "hFT0A_Collisions", histos.add((histPath + "hFT0A_Collisions").c_str(), "hFT0A_Collisions", {kTH1D, {{axisMultUltraFineFT0A}}})}); + histPointers.insert({histPath + "hFT0M_Collisions", histos.add((histPath + "hFT0M_Collisions").c_str(), "hFT0M_Collisions", {kTH1D, {{axisMultUltraFineFT0M}}})}); + histPointers.insert({histPath + "hFV0A_Collisions", histos.add((histPath + "hFV0A_Collisions").c_str(), "hFV0A_Collisions", {kTH1D, {{axisMultUltraFineFV0A}}})}); + histPointers.insert({histPath + "hNGlobalTracks", histos.add((histPath + "hNGlobalTracks").c_str(), "hNGlobalTracks", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); + histPointers.insert({histPath + "hNMFTTracks", histos.add((histPath + "hNMFTTracks").c_str(), "hNMFTTracks", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); + histPointers.insert({histPath + "hNPVContributors", histos.add((histPath + "hNPVContributors").c_str(), "hNPVContributors", {kTH1D, {{axisMultUltraFinePVContributors}}})}); + + if (applyVertexZEqualization) { + histPointers.insert({histPath + "hFT0C_Collisions_Unequalized", histos.add((histPath + "hFT0C_Collisions_Unequalized").c_str(), "hFT0C_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0C}}})}); + histPointers.insert({histPath + "hFT0M_Collisions_Unequalized", histos.add((histPath + "hFT0M_Collisions_Unequalized").c_str(), "hFT0M_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0M}}})}); + histPointers.insert({histPath + "hFV0A_Collisions_Unequalized", histos.add((histPath + "hFV0A_Collisions_Unequalized").c_str(), "hFV0A_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFV0A}}})}); + histPointers.insert({histPath + "hNGlobalTracks_Unequalized", histos.add((histPath + "hNGlobalTracks_Unequalized").c_str(), "hNGlobalTracks_Unequalized", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); + histPointers.insert({histPath + "hNMFTTracks_Unequalized", histos.add((histPath + "hNMFTTracks_Unequalized").c_str(), "hNMFTTracks_Unequalized", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); + histPointers.insert({histPath + "hNPVContributors_Unequalized", histos.add((histPath + "hNPVContributors_Unequalized").c_str(), "hNPVContributors_Unequalized", {kTH1D, {{axisMultUltraFinePVContributors}}})}); + } + + histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFT0CvsPVz_Collisions", histos.add((histPath + "hFT0CvsPVz_Collisions").c_str(), "hFT0CvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFV0AvsPVz_Collisions", histos.add((histPath + "hFV0AvsPVz_Collisions").c_str(), "hFV0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNGlobalTracksvsPVz_Collisions", histos.add((histPath + "hNGlobalTracksvsPVz_Collisions").c_str(), "hNGlobalTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNMFTTracksvsPVz_Collisions", histos.add((histPath + "hNMFTTracksvsPVz_Collisions").c_str(), "hNMFTTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNTPVvsPVz_Collisions", histos.add((histPath + "hNTPVvsPVz_Collisions").c_str(), "hNTPVvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + } + + template + void genericProcessCollision(const TCollision& collision) + // process this collisions + { + initRun(collision); + histos.fill(HIST("hCollisionSelection"), 0); // all collisions + getHist(TH1, histPath + "hCollisionSelection")->Fill(0); + + if (applySel8 && !collision.multSel8()) + return; + histos.fill(HIST("hCollisionSelection"), 1); + getHist(TH1, histPath + "hCollisionSelection")->Fill(1); + + // calculate vertex-Z-equalized quantities if desired + float multFV0A = collision.multFV0A(); + float multFT0A = collision.multFT0A(); + float multFT0C = collision.multFT0C(); + float multNTracksGlobal = collision.multNTracksGlobal(); + float mftNtracks = collision.mftNtracks(); + float multNTracksPV = collision.multNTracksPV(); + if (applyVertexZEqualization) { + float epsilon = 1e-2; // average value after which this collision will be disregarded + multFV0A = -1.0f; + multFT0A = -1.0f; + multFT0C = -1.0f; + multNTracksGlobal = -1.0f; + mftNtracks = -1.0f; + multNTracksPV = -1.0f; + + if (hVtxZFV0A->Interpolate(collision.multPVz()) > epsilon) { + multFV0A = hVtxZFV0A->Interpolate(0.0) * collision.multFV0A() / hVtxZFV0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0A->Interpolate(collision.multPVz()) > epsilon) { + multFT0A = hVtxZFT0A->Interpolate(0.0) * collision.multFT0A() / hVtxZFT0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0C->Interpolate(collision.multPVz()) > epsilon) { + multFT0C = hVtxZFT0C->Interpolate(0.0) * collision.multFT0C() / hVtxZFT0C->Interpolate(collision.multPVz()); + } + if (hVtxZNGlobals->Interpolate(collision.multPVz()) > epsilon) { + multNTracksGlobal = hVtxZNGlobals->Interpolate(0.0) * collision.multNTracksGlobal() / hVtxZNGlobals->Interpolate(collision.multPVz()); + } + if (hVtxZMFT->Interpolate(collision.multPVz()) > epsilon) { + mftNtracks = hVtxZMFT->Interpolate(0.0) * collision.mftNtracks() / hVtxZMFT->Interpolate(collision.multPVz()); + } + if (hVtxZNTracks->Interpolate(collision.multPVz()) > epsilon) { + multNTracksPV = hVtxZNTracks->Interpolate(0.0) * collision.multNTracksPV() / hVtxZNTracks->Interpolate(collision.multPVz()); + } + } + + bool passRejectITSROFBorder = !(rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)); + bool passRejectTFBorder = !(rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)); + bool passRequireIsVertexITSTPC = !(requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)); + bool passRequireIsGoodZvtxFT0VsPV = !(requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)); + bool passRequireIsVertexTOFmatched = !(requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)); + bool passRequireIsVertexTRDmatched = !(requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)); + bool passRejectSameBunchPileup = !(rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); + bool passINELgtZERO = !(requireINELgtZERO && !collision.isInelGt0()); + + // _______________________________________________________ + // sidestep vertex-Z rejection for vertex-Z profile histograms + if (passRejectITSROFBorder && passRejectTFBorder && passRequireIsVertexITSTPC && passRequireIsGoodZvtxFT0VsPV && + passRequireIsVertexTOFmatched && passRequireIsVertexTRDmatched && passRejectSameBunchPileup && passINELgtZERO) { + // all runs + histos.fill(HIST("hFT0AvsPVz_Collisions"), collision.multPVz(), collision.multFT0A()); + histos.fill(HIST("hFT0CvsPVz_Collisions"), collision.multPVz(), collision.multFT0C()); + histos.fill(HIST("hFV0AvsPVz_Collisions"), collision.multPVz(), collision.multFV0A()); + histos.fill(HIST("hNGlobalTracksvsPVz_Collisions"), collision.multPVz(), collision.multNTracksGlobal()); + histos.fill(HIST("hNMFTTracksvsPVz_Collisions"), collision.multPVz(), collision.mftNtracks()); + + // per run + getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C); + getHist(TProfile, histPath + "hFT0AvsPVz_Collisions")->Fill(collision.multPVz(), multFT0A); + getHist(TProfile, histPath + "hFV0AvsPVz_Collisions")->Fill(collision.multPVz(), multFV0A); + getHist(TProfile, histPath + "hNGlobalTracksvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksGlobal); + getHist(TProfile, histPath + "hNMFTTracksvsPVz_Collisions")->Fill(collision.multPVz(), mftNtracks); + getHist(TProfile, histPath + "hNTPVvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksPV); + } + + // _______________________________________________________ + + if (applyVtxZ && TMath::Abs(collision.multPVz()) > 10) + return; + histos.fill(HIST("hCollisionSelection"), 2); + getHist(TH1, histPath + "hCollisionSelection")->Fill(2); + + // _______________________________________________________ + // Extra event selections start here + if (!passRejectITSROFBorder) { + return; + } + histos.fill(HIST("hCollisionSelection"), 3 /* Not at ITS ROF border */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(3); + + if (!passRejectTFBorder) { + return; + } + histos.fill(HIST("hCollisionSelection"), 4 /* Not at TF border */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(4); + + if (!passRequireIsVertexITSTPC) { + return; + } + histos.fill(HIST("hCollisionSelection"), 5 /* Contains at least one ITS-TPC track */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(5); + + if (!passRequireIsGoodZvtxFT0VsPV) { + return; + } + histos.fill(HIST("hCollisionSelection"), 6 /* PV position consistency check */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(6); + + if (!passRequireIsVertexTOFmatched) { + return; + } + histos.fill(HIST("hCollisionSelection"), 7 /* PV with at least one contributor matched with TOF */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(7); + + if (!passRequireIsVertexTRDmatched) { + return; + } + histos.fill(HIST("hCollisionSelection"), 8 /* PV with at least one contributor matched with TRD */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(8); + + if (!passRejectSameBunchPileup) { + return; + } + histos.fill(HIST("hCollisionSelection"), 9 /* Not at same bunch pile-up */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(9); + + if (!passINELgtZERO) { + return; + } + histos.fill(HIST("hCollisionSelection"), 11 /* is INEL > 0 */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(11); + + // if we got here, we also finally fill the FT0C histogram, please + histos.fill(HIST("hNPVContributors"), collision.multNTracksPV()); + histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A()); + histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C()); + histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C())); + histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A()); + histos.fill(HIST("hNGlobalTracks"), collision.multNTracksGlobal()); + histos.fill(HIST("hNMFTTracks"), collision.mftNtracks()); + + // save vertex-Z equalized + getHist(TH1, histPath + "hNPVContributors")->Fill(multNTracksPV); + getHist(TH1, histPath + "hFT0A_Collisions")->Fill(multFT0A); + getHist(TH1, histPath + "hFT0C_Collisions")->Fill(multFT0C); + getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C)); + getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A); + getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); + getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); + + if (applyVertexZEqualization.value) { + // save unequalized for cross-checks + getHist(TH1, histPath + "hNPVContributors_Unequalized")->Fill(collision.multNTracksPV()); + getHist(TH1, histPath + "hFT0C_Collisions_Unequalized")->Fill(collision.multFT0C()); + getHist(TH1, histPath + "hFT0M_Collisions_Unequalized")->Fill((collision.multFT0A() + collision.multFT0C())); + getHist(TH1, histPath + "hFV0A_Collisions_Unequalized")->Fill(collision.multFV0A()); + getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); + getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); + } + } + + void process(soa::Join::iterator const& collision) + { + genericProcessCollision(collision); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From cbdf4096c30986e5ab09b2b941b75bb9fdd9e40f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 8 May 2026 23:06:25 +0200 Subject: [PATCH 106/449] [Common,PWGLF] Migrate the propagation service to CCDB tables (#16007) --- .claude/commands/migrate-ccdb.md | 148 +++++++++++++ Common/DataModel/GloCCDBObjects.h | 65 ++++++ Common/TableProducer/CMakeLists.txt | 6 + Common/TableProducer/propagationServiceV2.cxx | 194 ++++++++++++++++++ PWGLF/Utils/strangenessBuilderModule.h | 6 +- 5 files changed, 416 insertions(+), 3 deletions(-) create mode 100644 .claude/commands/migrate-ccdb.md create mode 100644 Common/DataModel/GloCCDBObjects.h create mode 100644 Common/TableProducer/propagationServiceV2.cxx diff --git a/.claude/commands/migrate-ccdb.md b/.claude/commands/migrate-ccdb.md new file mode 100644 index 00000000000..48d0f49c971 --- /dev/null +++ b/.claude/commands/migrate-ccdb.md @@ -0,0 +1,148 @@ +Migrate the specified file (or all files mentioned in the conversation) from `Service` to the declarative CCDB table approach. + +## Background + +The old approach uses `Service` and calls `ccdb->getForTimeStamp(path, timestamp)` at runtime. The new approach declares CCDB columns and timestamped tables using macros, so the framework fetches objects automatically and exposes them as columns on BC rows. + +**New API summary:** + +```cpp +// In namespace o2::aod (or a sub-namespace): +DECLARE_SOA_CCDB_COLUMN(StructName, getterName, ConcreteType, "CCDB/Object/Path"); + +DECLARE_SOA_TIMESTAMPED_TABLE(TableName, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "TABLEDESC", + ns::StructName, ns::OtherColumn); + +// In the task — basic usage: +using MyBCs = soa::Join; +void process(MyBCs const& bcs) { + for (auto const& bc : bcs) { + auto const& obj = bc.getterName(); // reference to cached deserialized object; treat as immutable + } +} +``` + +**Configurable CCDB paths** (`ConfigurableCCDBPath`): + +If the original task used a `Configurable` to supply the CCDB path, the path can remain user-overridable after migration using `ConfigurableCCDBPath`. This is a typed `Configurable` whose option name is automatically set to `"ccdb:" + Column::mLabel` (where `mLabel = "f" + StructName`), defaulting to the compile-time path in the column declaration. The framework reads this option name when resolving CCDB URLs, so users can still redirect the path via JSON config. + +The Configurable is purely declarative for the path-override mechanism: declaring it is sufficient — you do **not** pass `.value` to a getter or fetcher. The accessor remains `bc.getterName()`. The `.value` member is still available if the task wants to log the resolved path. + +```cpp +struct MyTask { + // Replaces: Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "..."}; + ConfigurableCCDBPath grpMagFieldPath; // option name = "ccdb:fGRPMagField" + + void process(MyBCs const& bcs) { + auto const& grpmag = bcs.iteratorAt(0).grpMagField(); // path override is honoured automatically + LOGP(info, "Using GRPMagField path: {}", grpMagFieldPath.value); + } +}; +``` + +Required headers (add if missing): ``, ``, `` +Headers to remove (if no longer needed): `` + +## What to do + +Read the target file(s) and perform the following migration. Do NOT do a complete migration if the patterns are ambiguous or out of scope — instead note what was skipped and why. + +### Step 1 — Inventory + +Find every `ccdb->getForTimeStamp(path, ts)` call (and variants like `fCCDB->getForTimeStamp`, `mCcdb->getForTimeStamp`). For each call record: +- The concrete C++ type `T` +- The CCDB path string (may be a `Configurable` variable — record the default value and the Configurable's name) +- The timestamp source (BC timestamp, computed value, etc.) +- Where the result is used + +**Deduplicate**: for the same (type, path) pair, declare only one CCDB column. Multiple call sites collapse into multiple uses of the same getter. + +### Step 2 — Identify scope + +Determine whether each fetch is: +- **Per-BC/per-collision** (called inside `process()` with a timestamp from a BC) — these can be migrated +- **Per-run** (called once when `runNumber` changes, guarded by `mRunNumber == ...`) — these can be migrated; the framework caches per unique timestamp automatically +- **Global/init-time** (called in `init()` with a fixed timestamp, not keyed to a BC) — these **cannot** be migrated to CCDB tables; leave them as-is and note this + +Skip the migration for any global/init-time fetches. Skip the whole file if all fetches are global. + +### Step 3 — Declare CCDB columns and table + +In the `o2::aod` namespace (or a private sub-namespace inside the file, before the task struct), declare: + +```cpp +namespace o2::aod +{ +namespace myccdbtask // use a short, unique snake_case name derived from the task name +{ +DECLARE_SOA_CCDB_COLUMN(StructName, getterName, fully::qualified::ConcreteType, "CCDB/Path"); //! +// one per unique (type, path) pair +} // namespace myccdbtask + +DECLARE_SOA_TIMESTAMPED_TABLE(MyTaskCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "MYTASKCCDB", //! + myccdbtask::StructName /*, ... */); +} // namespace o2::aod +``` + +Rules for naming: +- `StructName` / `getterName`: derive from the type name, e.g. `GRPMagField` / `grpMagField`, `MeanVertex` / `meanVertex` +- Table name: `CCDBObjects`, e.g. `SkimmerDalitzEECCDBObjects` +- `_Desc_` string: short ALL-CAPS string unique within the binary (≤ 16 chars to fit the AOD descriptor), e.g. `"DALZECC"`, `"TOFCALIB"` +- Namespace: lowercase snake-case derived from the task name (avoid collisions with other CCDB column namespaces in the file) +- Use the **default value** of any `Configurable` path as the compile-time path in the `DECLARE_SOA_CCDB_COLUMN` macro; if the path has no obvious default, leave a `// TODO: verify path` comment + +### Step 4 — Update the task struct + +1. **Remove** `Service ccdb;` (and any variant field name) +2. **Remove** `int mRunNumber;` (or similar run-caching variables) **only if** their sole purpose was to guard CCDB re-fetches +3. **Remove** `ccdb->setURL(...)`, `ccdb->setCaching(...)`, `ccdb->setLocalObjectValidityChecking()`, `ccdb->setCreatedNotAfter(...)`, `ccdb->setFatalWhenNull(...)` from `init()` +4. **Remove** the entire `initCCDB()`/`initMagField()` helper method if it only did CCDB fetching; otherwise remove just the CCDB lines from it +5. **Handle path Configurables** — for each `Configurable` that held a CCDB path: + - If the path was used as the sole argument to `getForTimeStamp` and the user may want to override it at runtime: **replace** it with `ConfigurableCCDBPath` (e.g. `ConfigurableCCDBPath grpMagFieldPath;`). The member name should match the getter for clarity. Keep a comment explaining what path it controls. + - If the path was never intended to be user-facing (e.g. internal fixed paths): **remove** it outright; the compile-time path in `DECLARE_SOA_CCDB_COLUMN` is sufficient. + - Always remove Configurables that were only used for CCDB manager setup and not for paths: `ccdb-url`, `ccdb-no-later-than`, `skipGRPOquery`, `d_bz_input` (if only used to bypass CCDB), etc. +6. **Remove** cached pointer member variables (e.g. `GRPMagField* grpmag = nullptr`) if they were only populated by CCDB fetches that are now replaced + +### Step 5 — Update process() signatures + +Define one alias near the top of the task or just below the table declaration: +```cpp +using MyBCs = soa::Join; +``` + +Then for each `process()` that used to call `getForTimeStamp`: + +- If `process()` already takes `aod::BCsWithTimestamps const&` directly: change it to `MyBCs const&`. +- If `process()` accesses BCs via `collision.bc_as()`: add `MyBCs const&` to the process signature (so the framework knows to provide it) and replace the `bc_as<>` type with `MyBCs`. +- If `process()` does not currently mention BCs but called `ccdb->getForTimeStamp(path, collision.bc_as<...>().timestamp())`: add `MyBCs const&` to the signature and obtain the BC via `collision.bc_as()`. +- Replace every `ccdb->getForTimeStamp(path, ts)` call with `bc.getterName()`. The returned reference is to a cached deserialized object; treat it as immutable. +- Null-pointer checks (`if (!grpmag)`) on the result become unnecessary — the framework guarantees the object is present (or the task fails early). Remove them. +- If a helper template like `initCCDB(collision)` was called per-collision, inline its remaining (non-CCDB) work or drop it. + +### Step 6 — Fix includes + +- Remove `#include ` if no other code in the file still uses `BasicCCDBManager` +- Ensure `#include ` is present (may already be included transitively) +- Keep all type headers (e.g. ``) since they are still needed for the concrete type + +### Step 7 — Final review + +After making changes: +- Check that every remaining use of `ccdb` / `fCCDB` / `mCcdb` has been handled +- Check that `mRunNumber` (or similar) is fully removed if unused +- Check that any leftover `Configurable` for a path is either replaced by `ConfigurableCCDBPath<>` or removed +- Search for stale references to removed Configurables (e.g. `grpmagPath.value` lingering in log messages — switch to `grpMagFieldPath.value`) +- If `init()` is now empty, it can be removed +- Note any patterns that were intentionally skipped + +## Important limitations — tell the user if any apply + +- **Configurable paths**: CCDB column paths are compile-time constants in the macro. Add `ConfigurableCCDBPath` to allow runtime override; its default is `Column::query` so it always agrees with the macro by construction. +- **`getRunDuration()` calls**: these use `BasicCCDBManager` statically and are unrelated to per-BC fetching — do not touch them. +- **`ctpRateFetcher` / other helpers**: out of scope. +- **Multiple tasks in one file**: tasks can share a single CCDB table declaration if they need the same objects; otherwise each task gets its own with a unique `_Desc_`. +- **Non-BC timestamps**: if the timestamp comes from something other than a BC (e.g. computed manually), the migration is non-trivial — flag it instead of forcing it. +- **Global/init-time fetches** (e.g. `efficiencyGlobal.cxx` style): not migratable — the timestamped-table mechanism requires a row in a BC-keyed table. +- **Magnetic-field side effects**: tasks that compute `d_bz` from a fetched `GRPMagField` and seed a propagator can keep that logic, just sourcing the object from `bc.grpMagField()` instead of `ccdb->getForTimeStamp(...)`. + +$ARGUMENTS diff --git a/Common/DataModel/GloCCDBObjects.h b/Common/DataModel/GloCCDBObjects.h new file mode 100644 index 00000000000..f97b684b0a1 --- /dev/null +++ b/Common/DataModel/GloCCDBObjects.h @@ -0,0 +1,65 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file GloCCDBObjects.h +/// \brief Declarative CCDB columns for the most-commonly needed GLO/ objects. +/// +/// Provides a single shared timestamped table (`aod::GloCCDBObjects`) that +/// tasks can join with `aod::BCsWithTimestamps` to obtain the four GLO/ +/// calibration objects without using `Service`. +/// +/// Usage: +/// \code +/// #include "Common/DataModel/GloCCDBObjects.h" +/// // ... +/// using BCsWithCCDB = soa::Join; +/// void process(BCsWithCCDB const& bcs) { +/// const auto& grpmag = bcs.begin().grpMagField(); +/// const auto& meanvtx = bcs.begin().meanVertex(); +/// const auto& grpecs = bcs.begin().grpECS(); +/// const auto& grplhcif= bcs.begin().grpLHCIF(); +/// } +/// \endcode +/// +/// If you need only a subset of the four objects, declare your own +/// `DECLARE_SOA_TIMESTAMPED_TABLE` with the relevant subset of columns from +/// the `o2::aod::ccdbGlo` namespace rather than joining `aod::GloCCDBObjects`. +/// +/// Note: MatLayerCylSet is intentionally omitted — it requires +/// `MatLayerCylSet::rectifyPtrFromFile()` after deserialisation, which the +/// CCDB column mechanism does not perform. + +#ifndef COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ +#define COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ + +#include +#include +#include +#include +#include +#include + +namespace o2::aod +{ +namespace ccdbGlo +{ +DECLARE_SOA_CCDB_COLUMN(GRPMagField, grpMagField, o2::parameters::GRPMagField, "GLO/Config/GRPMagField"); //! +DECLARE_SOA_CCDB_COLUMN(MeanVertex, meanVertex, o2::dataformats::MeanVertexObject, "GLO/Calib/MeanVertex"); //! +DECLARE_SOA_CCDB_COLUMN(GRPECSObject, grpECS, o2::parameters::GRPECSObject, "GLO/Config/GRPECS"); //! +DECLARE_SOA_CCDB_COLUMN(GRPLHCIFData, grpLHCIF, o2::parameters::GRPLHCIFData, "GLO/Config/GRPLHCIF"); //! +} // namespace ccdbGlo + +/// Full table — join with aod::BCsWithTimestamps to obtain all four objects. +DECLARE_SOA_TIMESTAMPED_TABLE(GloCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "GLOCCDBOBJ", //! + ccdbGlo::GRPMagField, ccdbGlo::MeanVertex, ccdbGlo::GRPECSObject, ccdbGlo::GRPLHCIFData); +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 69cd6084a09..26af3c092f1 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -74,11 +74,17 @@ o2physics_add_dpl_workflow(track-propagation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(propagationservice SOURCES propagationService.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(propagationservice-v2 + SOURCES propagationServiceV2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(propagationservice-run2 SOURCES propagationServiceRun2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager diff --git a/Common/TableProducer/propagationServiceV2.cxx b/Common/TableProducer/propagationServiceV2.cxx new file mode 100644 index 00000000000..da9667f7378 --- /dev/null +++ b/Common/TableProducer/propagationServiceV2.cxx @@ -0,0 +1,194 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file propagationServiceV2.cxx +/// \brief V2: GRPMagField and MeanVertexObject sourced from aod::GloCCDBObjects declarative CCDB table. +/// \author ALICE + +//=============================================================== +// +// Merged track propagation + strangeness building task +// +// Provides a common task to deal with track propagation and +// strangeness building in a single DPL device that is particularly +// adequate for pipelining. +// +//=============================================================== + +#include "PWGLF/Utils/strangenessBuilderModule.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/GloCCDBObjects.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/TrackTuner.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace o2; +using namespace o2::framework; + +// use parameters + cov mat non-propagated, aux info + (extension propagated) +using FullTracksExt = soa::Join; +using FullTracksExtIU = soa::Join; +using FullTracksExtWithPID = soa::Join; +using FullTracksExtIUWithPID = soa::Join; +using FullTracksExtLabeled = soa::Join; +using FullTracksExtLabeledIU = soa::Join; +using FullTracksExtLabeledWithPID = soa::Join; +using FullTracksExtLabeledIUWithPID = soa::Join; +using TracksWithExtra = soa::Join; + +// For dE/dx association in pre-selection +using TracksExtraWithPID = soa::Join; + +struct propagationServiceV2 { + // Service kept for MatLUT (rectifyPtrFromFile) and + // strangenessBuilderModule (V-drift via ccdb->instance()). + // GRPMagField and MeanVertex are sourced from CCDB columns instead. + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + // propagation stuff — ccdbLoader used only for lut + mMeanVtx (set from column) + runNumber + o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables; + o2::common::StandardCCDBLoader ccdbLoader; + + // Declarative CCDB path overrides (replace grpmagPath / mVtxPath in StandardCCDBLoaderConfigurables) + // Option names: "ccdb:fGRPMagField" and "ccdb:fMeanVertex" respectively. + o2::framework::ConfigurableCCDBPath grpmagPath; + o2::framework::ConfigurableCCDBPath mVtxPath; + + // boilerplate: strangeness builder stuff + o2::pwglf::strangenessbuilder::products products; + o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; + o2::pwglf::strangenessbuilder::v0Configurables v0BuilderOpts; + o2::pwglf::strangenessbuilder::cascadeConfigurables cascadeBuilderOpts; + o2::pwglf::strangenessbuilder::preSelectOpts preSelectOpts; + o2::pwglf::strangenessbuilder::BuilderModule strangenessBuilderModule; + + // the track tuner object -> needs to be here as it inherits from ConfigurableGroup (+ has its own copy of ccdbApi) + TrackTuner trackTunerObj; + + // track propagation + o2::common::TrackPropagationProducts trackPropagationProducts; + o2::common::TrackPropagationConfigurables trackPropagationConfigurables; + o2::common::TrackPropagationModule trackPropagation; + + using BCsWithCCDB = soa::Join; + + // registry + HistogramRegistry histos{"histos"}; + + void init(o2::framework::InitContext& initContext) + { + // Only needed for MatLUT fetch and strangenessBuilderModule V-drift + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + trackPropagation.init(trackPropagationConfigurables, trackTunerObj, histos, initContext); + strangenessBuilderModule.init(baseOpts, v0BuilderOpts, cascadeBuilderOpts, preSelectOpts, histos, initContext); + } + + // Load MatLUT once (needs rectifyPtrFromFile, kept manual), set B-field per run from + // GRPMagField CCDB column, and refresh mMeanVtx pointer every call (pointer into current + // BC table, valid only for the duration of this process() invocation). + template + void initCCDB(TBC const& bc0) + { + if (!ccdbLoader.lut) { + LOG(info) << "Loading material look-up table for run: " << bc0.runNumber(); + ccdbLoader.lut = o2::base::MatLayerCylSet::rectifyPtrFromFile( + ccdb->template getForRun(standardCCDBLoaderConfigurables.lutPath.value, bc0.runNumber())); + o2::base::Propagator::Instance()->setMatLUT(ccdbLoader.lut); + } + // Always refresh: pointer into current BC table, invalidated after process() returns + ccdbLoader.mMeanVtx = &bc0.meanVertex(); + if (ccdbLoader.runNumber != bc0.runNumber()) { + const auto& grpmag = bc0.grpMagField(); // from declarative CCDB column + LOG(info) << "Setting B-field to current " << grpmag.getL3Current() << " A for run " << bc0.runNumber() << " from GRPMagField CCDB column"; + o2::base::Propagator::initFieldFromGRP(&grpmag); + ccdbLoader.runNumber = bc0.runNumber(); + } + } + + void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, BCsWithCCDB const& bcs) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + } + + void processMonteCarlo(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIU const& tracks, BCsWithCCDB const& bcs, aod::McParticles const& mcParticles) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + } + + void processRealDataWithPID(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIUWithPID const& tracks, BCsWithCCDB const& bcs) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + } + + void processMonteCarloWithPID(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIUWithPID const& tracks, BCsWithCCDB const& bcs, aod::McParticles const& mcParticles) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + } + + PROCESS_SWITCH(propagationServiceV2, processRealData, "process real data", true); + PROCESS_SWITCH(propagationServiceV2, processMonteCarlo, "process monte carlo", false); + PROCESS_SWITCH(propagationServiceV2, processRealDataWithPID, "process real data", false); + PROCESS_SWITCH(propagationServiceV2, processMonteCarloWithPID, "process monte carlo", false); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGLF/Utils/strangenessBuilderModule.h b/PWGLF/Utils/strangenessBuilderModule.h index 2af133c228b..3079cab56f1 100644 --- a/PWGLF/Utils/strangenessBuilderModule.h +++ b/PWGLF/Utils/strangenessBuilderModule.h @@ -728,10 +728,10 @@ class BuilderModule return idx; } - template - bool initCCDB(TCCDB& ccdb, aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) + template + bool initCCDB(TCCDB& ccdb, TBCs const& bcs, TCollisions const& collisions) { - auto bc = collisions.size() ? collisions.begin().template bc_as() : bcs.begin(); + auto bc = collisions.size() ? collisions.begin().template bc_as() : bcs.begin(); if (!bcs.size()) { LOGF(warn, "No BC found, skipping this DF."); return false; // signal to skip this DF From 6010a0ea117089319f44b9e586303b0c693e30f0 Mon Sep 17 00:00:00 2001 From: Rashi gupta <167059733+rashigupt@users.noreply.github.com> Date: Sat, 9 May 2026 14:29:02 +0530 Subject: [PATCH 107/449] [PWGHF] Hadron Table Update for Event Mixing and High-p T Electron Cut (#16112) Co-authored-by: rashi.gupta@cern.ch --- .../TableProducer/correlatorHfeHadrons.cxx | 73 ++++++++++--------- PWGHF/HFL/DataModel/ElectronSelectionTable.h | 5 +- .../electronSelectionWithTpcEmcal.cxx | 9 ++- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx index 544559ca89e..e83da75ed36 100644 --- a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -231,46 +231,42 @@ struct HfCorrelatorHfeHadrons { registry.fill(HIST("hNevents"), 1); - // Add hadron Table For Mix Event Electron Hadron correlation + // fraction of event which used for Event mixing if (!skipEventTableFilling) { + registry.fill(HIST("hTracksBin"), poolBin); registry.fill(HIST("hZvertex"), collision.posZ()); - for (const auto& hTrack : tracks) { - if (!selAssoHadron(hTrack)) { - continue; - } + } + for (const auto& hTrack : tracks) { + if (!selAssoHadron(hTrack)) { + continue; + } - // Mc rec hadron efficiency - if constexpr (IsMc) { - if (hTrack.has_mcParticle()) { - auto mcParticle = hTrack.template mcParticle_as(); - if ((std::abs(mcParticle.pdgCode()) != kElectron) && (std::abs(mcParticle.pdgCode()) != kMuonMinus) && (std::abs(mcParticle.pdgCode()) != kPiPlus) && (std::abs(mcParticle.pdgCode()) != kKPlus) && (std::abs(mcParticle.pdgCode()) != kProton)) { - continue; - } + // Mc rec hadron efficiency + if constexpr (IsMc) { + if (hTrack.has_mcParticle()) { + auto mcParticle = hTrack.template mcParticle_as(); + if ((std::abs(mcParticle.pdgCode()) != kElectron) && (std::abs(mcParticle.pdgCode()) != kMuonMinus) && (std::abs(mcParticle.pdgCode()) != kPiPlus) && (std::abs(mcParticle.pdgCode()) != kKPlus) && (std::abs(mcParticle.pdgCode()) != kProton)) { + continue; + } - registry.fill(HIST("hptHadronMcRec"), hTrack.pt()); - if (mcParticle.isPhysicalPrimary()) { - - registry.fill(HIST("hptHadronMcRecPrimary"), hTrack.pt()); - - if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hMCRecptEleHadron"), hTrack.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hMCRecptMuonHadron"), hTrack.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hMCRecptPionHadron"), hTrack.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hMCRecptKaonHadron"), hTrack.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hMCRecptProtonHadron"), hTrack.pt()); - } + registry.fill(HIST("hptHadronMcRec"), hTrack.pt()); + if (mcParticle.isPhysicalPrimary()) { + + registry.fill(HIST("hptHadronMcRecPrimary"), hTrack.pt()); + + if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hMCRecptEleHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hMCRecptMuonHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hMCRecptPionHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hMCRecptKaonHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hMCRecptProtonHadron"), hTrack.pt()); } } } - registry.fill(HIST("hTracksBin"), poolBin); - - registry.fill(HIST("hptHadron"), hTrack.pt()); - - entryHadron(hTrack.phi(), hTrack.eta(), hTrack.pt(), poolBin, gCollisionId, timeStamp); } } @@ -279,7 +275,7 @@ struct HfCorrelatorHfeHadrons { double ptElectron = -999; double phiElectron = -999; double etaElectron = -999; - + int cntEle = 0; for (const auto& eTrack : electrons) { ptElectron = eTrack.ptTrack(); phiElectron = eTrack.phiTrack(); @@ -377,10 +373,17 @@ struct HfCorrelatorHfeHadrons { ++nElHadUSCorr; } } + entryElectronHadronPair(deltaPhi, deltaEta, ptElectron, ptHadron, eTrack.eopEl(), eTrack.m02El(), eTrack.tpcNSigmaElTrack(), eTrack.tofNSigmaElTrack(), eTrack.tpcNClsCrRowsTrack(), eTrack.tpcCrRowsRatioTrack(), eTrack.itsChi2NClTrack(), eTrack.tpcChi2NClTrack(), eTrack.dcaXYTrack(), eTrack.dcaZTrack(), hTrack.tpcNClsCrossedRows(), hTrack.tpcCrossedRowsOverFindableCls(), hTrack.itsChi2NCl(), hTrack.tpcChi2NCl(), hTrack.dcaXY(), hTrack.dcaZ(), poolBin, nElHadLSCorr, nElHadUSCorr); + if (!skipEventTableFilling) { + if (cntEle == 0) { + registry.fill(HIST("hptHadron"), hTrack.pt()); + entryHadron(hTrack.phi(), hTrack.eta(), hTrack.pt(), poolBin, gCollisionId, timeStamp); + } + } } // end Hadron Track loop - + cntEle++; } // end Electron loop } diff --git a/PWGHF/HFL/DataModel/ElectronSelectionTable.h b/PWGHF/HFL/DataModel/ElectronSelectionTable.h index 4906b01d229..d819332e3ba 100644 --- a/PWGHF/HFL/DataModel/ElectronSelectionTable.h +++ b/PWGHF/HFL/DataModel/ElectronSelectionTable.h @@ -93,8 +93,9 @@ DECLARE_SOA_COLUMN(TpcChi2NClTrack, tpcChi2NClTrack, float); //! Chi2 / DECLARE_SOA_COLUMN(DcaXYTrack, dcaXYTrack, float); //! dca of the electron in xy direction DECLARE_SOA_COLUMN(DcaZTrack, dcaZTrack, float); //! dca of the electron in z direction -DECLARE_SOA_COLUMN(M02El, m02El, float); //! M02 of the electron cluster -DECLARE_SOA_COLUMN(EopEl, eopEl, float); //! energy momentum ratio of the electron +DECLARE_SOA_COLUMN(EopEl, eopEl, float); //! energy momentum ratio of the electron +DECLARE_SOA_COLUMN(M02El, m02El, float); //! M02 of the electron cluster + DECLARE_SOA_COLUMN(LSMassEE, lSMassEE, std::vector); //! mass of the Like sign electron pair DECLARE_SOA_COLUMN(ULSMassEE, uLSMassEE, std::vector); //! mass of UnLike sign electron pair DECLARE_SOA_COLUMN(NElPairLS, nElPairLS, int); //! Number of Like sign electron pair diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index 358d5d3642b..e41f634964a 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -85,7 +85,8 @@ struct HfElectronSelectionWithTpcEmcal { Configurable dcaZTrackMax{"dcaZTrackMax", 1.0f, "DCA Z cut"}; Configurable etaTrackMax{"etaTrackMax", 0.6f, "Eta range for electron tracks"}; Configurable etaTrackMin{"etaTrackMin", -0.6f, "Eta range for electron tracks"}; - Configurable ptTrackMin{"ptTrackMin", 3.0f, "Transverse MOmentum range for electron tracks"}; + Configurable ptTrackMin{"ptTrackMin", 3.0f, "Min Transverse MOmentum range for electron tracks"}; + Configurable ptTrackMax{"ptTrackMax", 12.0f, "Max Transverse MOmentum range for electron tracks"}; Configurable tpccrossCut{"tpccrossCut", 70, "TPC crossrows cut"}; Configurable itsChi2{"itsChi2", 36, "ITS chi2 cluster cut"}; Configurable tpcChi2NCl{"tpcChi2NCl", 4, "TPC chi2 cluster cut"}; @@ -286,7 +287,7 @@ struct HfElectronSelectionWithTpcEmcal { if ((track.phi() < phiTrackEMCalMin || track.phi() > phiTrackEMCalMax) && (track.phi() < phiTrackDCalMin || track.phi() > phiTrackDCalMax)) { return false; } - if (track.pt() < ptTrackMin) { + if (track.pt() < ptTrackMin || track.pt() > ptTrackMax) { return false; } return true; @@ -325,7 +326,7 @@ struct HfElectronSelectionWithTpcEmcal { if ((track.phi() < phiTrackEMCalMin || track.phi() > phiTrackEMCalMax) && (track.phi() < phiTrackDCalMin || track.phi() > phiTrackDCalMax)) { return false; } - if (track.pt() < ptTrackMin) { + if (track.pt() < ptTrackMin || track.pt() > ptTrackMax) { return false; } return true; @@ -589,7 +590,7 @@ struct HfElectronSelectionWithTpcEmcal { } // Pass multiplicities and other required parameters for this electron - hfElectronSelection(electron.collisionId(), electron.globalIndex(), electron.eta(), electron.phi(), electron.pt(), electron.tpcNSigmaEl(), electron.tofNSigmaEl(), electron.tpcNClsCrossedRows(), electron.tpcCrossedRowsOverFindableCls(), electron.itsChi2NCl(), electron.tpcChi2NCl(), electron.dcaXY(), electron.dcaZ(), m02, eop, vecLSMass, vecULSMass, nElPairsLS, nElPairsUS, isEMcal); + hfElectronSelection(electron.collisionId(), electron.globalIndex(), electron.eta(), electron.phi(), electron.pt(), electron.tpcNSigmaEl(), electron.tofNSigmaEl(), electron.tpcNClsCrossedRows(), electron.tpcCrossedRowsOverFindableCls(), electron.itsChi2NCl(), electron.tpcChi2NCl(), electron.dcaXY(), electron.dcaZ(), eop, m02, vecLSMass, vecULSMass, nElPairsLS, nElPairsUS, isEMcal); } // Electron Identification template From 9a31ae992ffb94f1ee3e4053249a36aab889eec1 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 9 May 2026 11:06:28 +0200 Subject: [PATCH 108/449] [PWGCF] Update lambdaR2Correlation.cxx (#15925) --- .../Tasks/lambdaR2Correlation.cxx | 1431 +++++++---------- 1 file changed, 585 insertions(+), 846 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index a8fdbe2e45c..45e9d661d4d 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -97,10 +97,7 @@ DECLARE_SOA_COLUMN(Rap, rap, float); DECLARE_SOA_COLUMN(Mass, mass, float); DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int64_t); DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int64_t); -DECLARE_SOA_COLUMN(CosPA, cosPA, float); -DECLARE_SOA_COLUMN(DcaDau, dcaDau, float); -DECLARE_SOA_COLUMN(V0Type, v0Type, int8_t); -DECLARE_SOA_COLUMN(V0PrmScd, v0PrmScd, int8_t); +DECLARE_SOA_COLUMN(PartType, partType, int8_t); DECLARE_SOA_COLUMN(CorrFact, corrFact, float); } // namespace lambdatrack DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, @@ -115,13 +112,40 @@ DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, lambdatrack::Mass, lambdatrack::PosTrackId, lambdatrack::NegTrackId, - lambdatrack::CosPA, - lambdatrack::DcaDau, - lambdatrack::V0Type, - lambdatrack::V0PrmScd, + lambdatrack::PartType, lambdatrack::CorrFact); using LambdaTrack = LambdaTracks::iterator; +namespace kaontrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaCollision, lambdaCollision); +DECLARE_SOA_COLUMN(Px, px, float); +DECLARE_SOA_COLUMN(Py, py, float); +DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(KaonTrackId, kaonTrackId, int64_t); +DECLARE_SOA_COLUMN(PartType, partType, int8_t); +DECLARE_SOA_COLUMN(CorrFact, corrFact, float); +} // namespace kaontrack +DECLARE_SOA_TABLE(KaonTracks, "AOD", "KAONTRACKS", o2::soa::Index<>, + kaontrack::LambdaCollisionId, + kaontrack::Px, + kaontrack::Py, + kaontrack::Pz, + kaontrack::Pt, + kaontrack::Eta, + kaontrack::Phi, + kaontrack::Rap, + kaontrack::Mass, + kaontrack::KaonTrackId, + kaontrack::PartType, + kaontrack::CorrFact); +using KaonTrack = KaonTracks::iterator; + namespace lambdatrackext { DECLARE_SOA_COLUMN(LambdaSharingDaughter, lambdaSharingDaughter, bool); @@ -151,12 +175,28 @@ DECLARE_SOA_TABLE(LambdaMcGenTracks, "AOD", "LMCGENTRACKS", o2::soa::Index<>, lambdatrack::Mass, lambdatrack::PosTrackId, lambdatrack::NegTrackId, - lambdatrack::V0Type, - lambdatrack::CosPA, - lambdatrack::DcaDau, - lambdatrack::V0PrmScd, + lambdatrack::PartType, lambdatrack::CorrFact); using LambdaMcGenTrack = LambdaMcGenTracks::iterator; + +namespace kaonmcgentrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaMcGenCollision, lambdaMcGenCollision); +} +DECLARE_SOA_TABLE(KaonMcGenTracks, "AOD", "KMCGENTRACKS", o2::soa::Index<>, + kaonmcgentrack::LambdaMcGenCollisionId, + o2::aod::mcparticle::Px, + o2::aod::mcparticle::Py, + o2::aod::mcparticle::Pz, + kaontrack::Pt, + kaontrack::Eta, + kaontrack::Phi, + kaontrack::Rap, + kaontrack::Mass, + kaontrack::KaonTrackId, + kaontrack::PartType, + kaontrack::CorrFact); +using KaonMcGenTrack = KaonMcGenTracks::iterator; } // namespace o2::aod enum CollisionLabels { @@ -168,30 +208,29 @@ enum CollisionLabels { enum TrackLabels { kTracksBeforeHasMcParticle = 1, kAllV0Tracks, - kV0KShortMassRej, - kNotLambdaNotAntiLambda, + kPassV0KinCuts, + kPassV0TopoSel, + kPassK0ShortMassRej, kV0IsBothLambdaAntiLambda, - kNotLambdaAfterSel, + kNotLambdaNotAntiLambda, kV0IsLambdaOrAntiLambda, kPassV0DauTrackSel, - kPassV0KinCuts, - kPassV0TopoSel, kAllSelPassed, - kPrimaryLambda, - kSecondaryLambda, - kLambdaDauNotMcParticle, - kLambdaNotPrPiMinus, - kAntiLambdaNotAntiPrPiPlus, - kPassTrueLambdaSel, kEffCorrPtCent, kEffCorrPtRapCent, + kMatchEffCorr, kNoEffCorr, - kPFCorrPtCent, - kPFCorrPtRapCent, - kNoPFCorr, kGenTotAccLambda, kGenLambdaNoDau, - kGenLambdaToPrPi +}; + +enum KaonLabels { + kKaonAllChargedTracks = 1, + kKaonPassKinSel, + kKaonPassGlobalSel, + kKaonPassDcaSel, + kKaonPassElRejSel, + kKaonPassAllSel }; enum CentEstType { @@ -199,20 +238,24 @@ enum CentEstType { kCentFT0C }; -enum RunType { - kRun3 = 0, - kRun2 -}; - enum ParticleType { kLambda = 0, - kAntiLambda + kAntiLambda, + kKaonPlus, + kKaonMinus }; enum ParticlePairType { kLambdaAntiLambda = 0, kLambdaLambda, - kAntiLambdaAntiLambda + kAntiLambdaAntiLambda, + kLambdaKaonPlus, + kLambdaKaonMinus, + kAntiLambdaKaonPlus, + kAntiLambdaKaonMinus, + kKaonPlusKaonMinus, + kKaonPlusKaonPlus, + kKaonMinusKaonMinus }; enum ShareDauLambda { @@ -236,24 +279,14 @@ enum CorrHistDim { ThreeDimCorr }; -enum PrmScdType { - kPrimary = 0, - kSecondary -}; - -enum PrmScdPairType { - kPP = 0, - kPS, - kSP, - kSS -}; - struct LambdaTableProducer { // Table Producers Produces lambdaCollisionTable; Produces lambdaTrackTable; + Produces kaonTrackTable; Produces lambdaMCGenCollisionTable; Produces lambdaMCGenTrackTable; + Produces kaonMCGenTrackTable; // Centrality Axis ConfigurableAxis cCentBins{"cCentBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 50.f, 80.0f, 100.f}, "Variable Centrality Bins"}; @@ -265,8 +298,6 @@ struct LambdaTableProducer { Configurable cMinCent{"cMinCent", 0., "Minumum Centrality"}; Configurable cMaxCent{"cMaxCent", 100.0, "Maximum Centrality"}; Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; - Configurable cInt7Trig{"cInt7Trig", false, "kINT7 MB Trigger"}; - Configurable cSel7Trig{"cSel7Trig", false, "Sel7 (V0A + V0C) Selection Run2"}; Configurable cTriggerTvxSel{"cTriggerTvxSel", false, "Trigger Time and Vertex Selection"}; Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; @@ -277,55 +308,54 @@ struct LambdaTableProducer { // Tracks Configurable cTrackMinPt{"cTrackMinPt", 0.1, "p_{T} minimum"}; - Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} maximum"}; Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 70, "TPC Min Crossed Rows"}; Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; Configurable cRemoveAmbiguousTracks{"cRemoveAmbiguousTracks", false, "Remove Ambiguous Tracks"}; + // Kaon Tracks + Configurable cKaonMinPt{"cKaonMinPt", 0.4, "Kaon Min pT"}; + Configurable cKaonMaxPt{"cKaonMaxPt", 2.2, "Kaon Max pT"}; + Configurable cKaonRapCut{"cKaonRapCut", 0.5, "Kaon |y| cut"}; + Configurable cKaonGlobalSel{"cKaonGlobalSel", true, "Global Track"}; + Configurable cKaonDcaXYCut{"cKaonDcaXYCut", 0.1, "DcaXY Cut"}; + Configurable cKaonDcaZCut{"cKaonDcaZCut", 1., "DcaXY Cut"}; + Configurable cTpcElRejCutMin{"cTpcElRejCutMin", -3., "Electron Rejection Cut Minimum"}; + Configurable cTpcElRejCutMax{"cTpcElRejCutMax", 5., "Electron Rejection Cut Maximum"}; + Configurable cKaonTpcNSigmaCut{"cKaonTpcNSigmaCut", 2, "TPC Kaon NSigma Cut"}; + Configurable cTpcRejCut{"cTpcRejCut", 3, "TPC Rej Cut"}; + Configurable cKaonTofNSigmaCut{"cKaonTofNSigmaCut", 2, "TOF Kaon NSigma Cut"}; + Configurable cTofRejCut{"cTofRejCut", 3, "TOF Rej Cut"}; + Configurable cKaonTpcPtSel{"cKaonTpcPtSel", 0.6, "Kaon TPC pT cutoff"}; + // V0s - Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; - Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.06, "Minimum Pion DCAr to PV"}; - Configurable cMinV0DcaDaughters{"cMinV0DcaDaughters", 0., "Minimum DCA between V0 daughters"}; - Configurable cMaxV0DcaDaughters{"cMaxV0DcaDaughters", 1., "Maximum DCA between V0 daughters"}; - Configurable cMinDcaV0ToPV{"cMinDcaV0ToPV", 0.0, "Minimum DCA V0 to PV"}; + Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.01, "Minimum Proton DCAr to PV"}; + Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.1, "Minimum Pion DCAr to PV"}; + Configurable cMaxDcaV0Daughters{"cMaxDcaV0Daughters", 1., "Maximum DCA between V0 daughters"}; Configurable cMaxDcaV0ToPV{"cMaxDcaV0ToPV", 999.0, "Maximum DCA V0 to PV"}; Configurable cMinV0TransRadius{"cMinV0TransRadius", 0.5, "Minimum V0 radius from PV"}; - Configurable cMaxV0TransRadius{"cMaxV0TransRadius", 999.0, "Maximum V0 radius from PV"}; - Configurable cMinV0CTau{"cMinV0CTau", 0.0, "Minimum ctau"}; Configurable cMaxV0CTau{"cMaxV0CTau", 30.0, "Maximum ctau"}; Configurable cMinV0CosPA{"cMinV0CosPA", 0.995, "Minimum V0 CosPA to PV"}; Configurable cKshortRejMassWindow{"cKshortRejMassWindow", 0.01, "Reject K0Short Candidates"}; - Configurable cKshortRejFlag{"cKshortRejFlag", true, "K0short Mass Rej Flag"}; - - // V0s kinmatic acceptance - Configurable cV0MassWindow{"cV0MassWindow", 0.007, "V0 Mass Window"}; - Configurable cMinV0Pt{"cMinV0Pt", 0.6, "Minimum V0 pT"}; - Configurable cMaxV0Pt{"cMaxV0Pt", 3.6, "Minimum V0 pT"}; - Configurable cMaxV0Rap{"cMaxV0Rap", 0.5, "|rap| cut"}; - Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Do Eta Analysis"}; - Configurable cV0TypeSelFlag{"cV0TypeSelFlag", true, "V0 Type Selection Flag"}; - Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; - // V0s MC - Configurable cHasMcFlag{"cHasMcFlag", true, "Has Mc Tag"}; - Configurable cSelectTrueLambda{"cSelectTrueLambda", false, "Select True Lambda"}; - Configurable cSelMCPSV0{"cSelMCPSV0", false, "Select Primary/Secondary V0"}; - Configurable cCheckRecoDauFlag{"cCheckRecoDauFlag", true, "Check for reco daughter PID"}; - Configurable cGenDecayChannel{"cGenDecayChannel", true, "Gen Level Decay Channel Flag"}; + // V0s acceptance + Configurable cLambdaMassWindow{"cLambdaMassWindow", 0.007, "Lambda Mass Window"}; + Configurable cLambdaMinPt{"cLambdaMinPt", 0.6, "Minimum Lambda pT"}; + Configurable cLambdaMaxPt{"cLambdaMaxPt", 3.6, "Minimum Lambda pT"}; + Configurable cLambdaRapCut{"cLambdaRapCut", 0.5, "Lambda |rap| cut"}; + Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; // Efficiency Correction - Configurable cCorrectionFlag{"cCorrectionFlag", false, "Correction Flag"}; + Configurable cGetCorrectionFlag{"cGetCorrectionFlag", false, "Apply correction flag"}; Configurable cGetEffFact{"cGetEffFact", false, "Get Efficiency Factor Flag"}; - Configurable cGetPrimFrac{"cGetPrimFrac", false, "Get Primary Fraction Flag"}; Configurable cGetMatchEff{"cGetMatchEff", false, "Get Matching Efficiency Flag"}; Configurable cCorrFactHist{"cCorrFactHist", 0, "Efficiency Factor Histogram"}; - Configurable cPrimFracHist{"cPrimFracHist", 0, "Primary Fraction Histogram"}; // CCDB Configurable cUrlCCDB{"cUrlCCDB", "http://alice-ccdb.cern.ch", "ALICE CCDB URL"}; - Configurable cPathCCDB{"cPathCCDB", "Users/y/ypatley/LHC22oPass7/LambdaCorrectionFactor", "Path for ccdb-object"}; - Configurable cPathCCDBMatchEff{"cPathCCDBMatchEff", "Users/y/ypatley/LHC22oPass7/ITSTPCMatchEff", "Path for ccdb-object for matching efficiency"}; + Configurable cPathCCDBRecoEff{"cPathCCDBRecoEff", "Users/y/ypatley/LBF/PP/RecoEfficiency", "Path for ccdb-object for reco efficiency"}; + Configurable cPathCCDBMatchEff{"cPathCCDBMatchEff", "Users/y/ypatley/LBF/PP/MatchEfficiency", "Path for ccdb-object for matching efficiency"}; + Configurable nolaterthan{"nolaterthan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; // Initialize CCDB Service Service ccdb; @@ -334,23 +364,25 @@ struct LambdaTableProducer { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // initialize corr_factor objects - std::vector> vCorrFactStrings = {{"hEffVsPtCentLambda", "hEffVsPtCentAntiLambda"}, - {"hEffVsPtYCentLambda", "hEffVsPtYCentAntiLambda"}, - {"hEffVsPtEtaCentLambda", "hEffVsPtEtaCentAntiLambda"}}; - - // initialize corr_factor objects - std::vector> vPrimFracStrings = {{"hPrimFracVsPtCentLambda", "hPrimFracVsPtCentAntiLambda"}, - {"hPrimFracVsPtYCentLambda", "hPrimFracVsPtYCentAntiLambda"}, - {"hPrimFracVsPtEtaCentLambda", "hPrimFracVsPtEtaCentAntiLambda"}}; + std::vector> vCorrFactStrings = {{"hEffVsPtCentLambda", "hEffVsPtCentAntiLambda", "hEffVsPtCentKaonPlus", "hEffVsPtCentKaonMinus"}, + {"hEffVsPtYCentLambda", "hEffVsPtYCentAntiLambda", "hEffVsPtYCentKaonPlus", "hEffVsPtYCentKaonMinus"}}; // Initialize Global Variables float cent = 0., mult = 0.; + TList *ccdbObjRecoEff, *ccdbObjMatchEff; + static constexpr std::string_view SubDir[] = {"QA/Lambda/", "QA/AntiLambda/", "QA/KaonPlus/", "QA/KaonMinus/"}; void init(InitContext const&) { // Set CCDB url ccdb->setURL(cUrlCCDB.value); ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(nolaterthan.value); + + // Get CCDB object + ccdbObjRecoEff = ccdb->getForTimeStamp(cPathCCDBRecoEff.value, nolaterthan.value); + ccdbObjMatchEff = ccdb->getForTimeStamp(cPathCCDBMatchEff.value, nolaterthan.value); // initialize axis specifications const AxisSpec axisCols(5, 0.5, 5.5, ""); @@ -374,16 +406,16 @@ struct LambdaTableProducer { const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); - const AxisSpec axisGCTau(2000, 0, 200, "#gammac#tau (cm)"); const AxisSpec axisAlpha(40, -1, 1, "#alpha"); const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); const AxisSpec axisITSTPCTrackPt(100, 0, 10, "p_{T} (GeV/#it{c})"); const AxisSpec axisTrackPt(40, 0, 4, "p_{T} (GeV/#it{c})"); const AxisSpec axisTrackDCA(200, -1, 1, "dca_{XY} (cm)"); - const AxisSpec axisMomPID(80, 0, 4, "p (GeV/#it{c})"); - const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); - const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); + const AxisSpec axisMomPID(80, 0, 4, "p_{T} (GeV/#it{c})"); + const AxisSpec axisTrackNsigma(401, -10.025, 10.025, {"n#sigma"}); + const AxisSpec axisTrackdEdx(360, 20, 200, "#frac{dE}{dx}"); + const AxisSpec axisTrackTofSignal(240, 0, 1.2, "#beta"); // Create Histograms. // Event histograms @@ -393,14 +425,15 @@ struct LambdaTableProducer { // QA histos.add("Tracks/h1f_tracks_info", "# of tracks", kTH1F, {axisTrks}); + histos.add("Tracks/h1f_kaon_sel", "Kaon selection", kTH1F, {axisTrks}); histos.add("Tracks/h2f_armpod_before_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); histos.add("Tracks/h2f_armpod_after_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); - histos.add("Tracks/h1f_lambda_pt_vs_invm", "p_{T} vs M_{#Lambda}", kTH2F, {axisV0Mass, axisV0Pt}); - histos.add("Tracks/h1f_antilambda_pt_vs_invm", "p_{T} vs M_{#bar{#Lambda}}", kTH2F, {axisV0Mass, axisV0Pt}); histos.add("Tracks/h2f_itstrack_centpt", "h2f_itstrack_centpt", kTH2F, {axisVarCent, axisITSTPCTrackPt}); histos.add("Tracks/h2f_itstpctrack_centpt", "h2f_itstpctrack_centpt", kTH2F, {axisVarCent, axisITSTPCTrackPt}); + histos.add("Tracks/h2f_itstpctoftrack_centpt", "h2f_itstpctoftrack_centpt", kTH2F, {axisVarCent, axisITSTPCTrackPt}); // QA Lambda + histos.add("QA/Lambda/h3f_centmasspt", "Invariant Mass", kTH3F, {axisCent, axisV0Mass, axisV0Pt}); histos.add("QA/Lambda/h2f_qt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); histos.add("QA/Lambda/h1f_dca_V0_daughters", "DCA between V0 daughters", kTH1F, {axisDcaDau}); histos.add("QA/Lambda/h1f_dca_pos_to_PV", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); @@ -409,40 +442,30 @@ struct LambdaTableProducer { histos.add("QA/Lambda/h1f_V0_cospa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); histos.add("QA/Lambda/h1f_V0_radius", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); histos.add("QA/Lambda/h1f_V0_ctau", "V_{0} c#tau", kTH1F, {axisCTau}); - histos.add("QA/Lambda/h1f_V0_gctau", "V_{0} #gammac#tau", kTH1F, {axisGCTau}); - - histos.add("QA/Lambda/h1f_pos_prong_pt", "Pos-Prong p_{T}", kTH1F, {axisTrackPt}); - histos.add("QA/Lambda/h1f_neg_prong_pt", "Neg-Prong p_{T}", kTH1F, {axisTrackPt}); - histos.add("QA/Lambda/h1f_pos_prong_eta", "Pos-Prong #eta-distribution", kTH1F, {axisV0Eta}); - histos.add("QA/Lambda/h1f_neg_prong_eta", "Neg-Prong #eta-distribution", kTH1F, {axisV0Eta}); - histos.add("QA/Lambda/h1f_pos_prong_phi", "Pos-Prong #phi-distribution", kTH1F, {axisV0Phi}); - histos.add("QA/Lambda/h1f_neg_prong_phi", "Neg-Prong #phi-distribution", kTH1F, {axisV0Phi}); - histos.add("QA/Lambda/h2f_pos_prong_xisqperclustertpc", "#chi^{2}/cluster TPC", kTH2F, {axisTrackPt, {200, 0, 50}}); - histos.add("QA/Lambda/h2f_pos_prong_xisqperclusterits", "#chi^{2}/cluster ITS", kTH2F, {axisTrackPt, {200, 0, 50}}); - histos.add("QA/Lambda/h2f_neg_prong_xisqperclustertpc", "#chi^{2}/cluster TPC", kTH2F, {axisTrackPt, {200, 0, 50}}); - histos.add("QA/Lambda/h2f_neg_prong_xisqperclusterits", "#chi^{2}/cluster ITS", kTH2F, {axisTrackPt, {200, 0, 50}}); - histos.add("QA/Lambda/h2f_pos_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); histos.add("QA/Lambda/h2f_neg_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); - histos.add("QA/Lambda/h2f_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("QA/Lambda/h2f_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - - // Kinematic Histograms - histos.add("McRec/Lambda/hPt", "Transverse Momentum", kTH1F, {axisV0Pt}); - histos.add("McRec/Lambda/hEta", "Pseudorapidity", kTH1F, {axisV0Eta}); - histos.add("McRec/Lambda/hRap", "Rapidity", kTH1F, {axisV0Rap}); - histos.add("McRec/Lambda/hPhi", "Azimuthal Angle", kTH1F, {axisV0Phi}); + histos.add("QA/Lambda/h2f_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisTrackdEdx}); + histos.add("QA/Lambda/h2f_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisTrackdEdx}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisTrackNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisTrackNsigma}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisTrackNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisTrackNsigma}); + + // QA Kaons + histos.add("QA/KaonPlus/hdEdX", "dE/dx vs pT", kTH2F, {axisMomPID, axisTrackdEdx}); + histos.add("QA/KaonPlus/hTOFSignal", "#beta_{TOF} vs p_{T}", kTH2F, {axisMomPID, axisTrackTofSignal}); + histos.add("QA/KaonPlus/hTPCNSigma", "n#sigma_{TPC} vs p_{T}", kTH2F, {axisMomPID, axisTrackNsigma}); + histos.add("QA/KaonPlus/hTOFNSigma", "n#sigma_{TOF} vs p_{T}", kTH2F, {axisMomPID, axisTrackNsigma}); // QA Anti-Lambda histos.addClone("QA/Lambda/", "QA/AntiLambda/"); histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); + // QA KaonMinus + histos.addClone("QA/KaonPlus/", "QA/KaonMinus/"); + // MC Generated Histograms - if (doprocessMCRun3 || doprocessMCRun2 || doprocessMCRecoRun3 || doprocessMCRecoRun2) { + if (doprocessMCRecoGen || doprocessMCReco) { // McReco Histos histos.add("Tracks/h2f_tracks_pid_before_sel", "PIDs", kTH2F, {axisPID, axisV0Pt}); histos.add("Tracks/h2f_tracks_pid_after_sel", "PIDs", kTH2F, {axisPID, axisV0Pt}); @@ -459,39 +482,22 @@ struct LambdaTableProducer { histos.addClone("McRec/", "McGen/"); - histos.add("McGen/Lambda/Proton/hPt", "Proton p_{T}", kTH1F, {axisTrackPt}); - histos.add("McGen/Lambda/Proton/hEta", "Proton #eta", kTH1F, {axisV0Eta}); - histos.add("McGen/Lambda/Proton/hRap", "Proton y", kTH1F, {axisV0Rap}); - histos.add("McGen/Lambda/Proton/hPhi", "Proton #phi", kTH1F, {axisV0Phi}); - - histos.addClone("McGen/Lambda/Proton/", "McGen/Lambda/Pion/"); - histos.addClone("McGen/Lambda/Proton/", "McGen/AntiLambda/Proton/"); - histos.addClone("McGen/Lambda/Pion/", "McGen/AntiLambda/Pion/"); - // set bin lables specific to MC histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotColBeforeHasMcCollision, "kTotColBeforeHasMcCollision"); histos.get(HIST("McGen/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); histos.get(HIST("McGen/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kTracksBeforeHasMcParticle, "kTracksBeforeHasMcParticle"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPrimaryLambda, "kPrimaryLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kSecondaryLambda, "kSecondaryLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kLambdaDauNotMcParticle, "kLambdaDauNotMcParticle"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kLambdaNotPrPiMinus, "kLambdaNotPrPiMinus"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAntiLambdaNotAntiPrPiPlus, "kAntiLambdaNotAntiPrPiPlus"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassTrueLambdaSel, "kPassTrueLambdaSel"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenTotAccLambda, "kGenTotAccLambda"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenLambdaNoDau, "kGenLambdaNoDau"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenLambdaToPrPi, "kGenLambdaToPrPi"); } // set bin labels histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllV0Tracks, "kAllV0Tracks"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0KShortMassRej, "kV0KShortMassRej"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassK0ShortMassRej, "kPassK0ShortMassRej"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaNotAntiLambda, "kNotLambdaNotAntiLambda"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsBothLambdaAntiLambda, "kV0IsBothLambdaAntiLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaAfterSel, "kNotLambdaAfterSel"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsLambdaOrAntiLambda, "kV0IsLambdaOrAntiLambda"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0DauTrackSel, "kPassV0DauTrackSel"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0KinCuts, "kPassV0KinCuts"); @@ -499,38 +505,33 @@ struct LambdaTableProducer { histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kEffCorrPtCent, "kEffCorrPtCent"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kEffCorrPtRapCent, "kEffCorrPtRapCent"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kMatchEffCorr, "kMatchEffCorr"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNoEffCorr, "kNoEffCorr"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtCent, "kPFCorrPtCent"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtRapCent, "kPFCorrPtRapCent"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNoPFCorr, "kNoPFCorr"); + + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonAllChargedTracks, "kKaonAllChargedTracks"); + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonPassKinSel, "kKaonPassKinSel"); + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonPassGlobalSel, "kKaonPassGlobalSel"); + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonPassDcaSel, "kKaonPassDcaSel"); + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonPassElRejSel, "kKaonPassElRejSel"); + histos.get(HIST("Tracks/h1f_kaon_sel"))->GetXaxis()->SetBinLabel(KaonLabels::kKaonPassAllSel, "kKaonPassAllSel"); } - template + template bool selCollision(C const& col) { - // VtxZ Selection + // Vz Selection if (col.posZ() <= cMinZVtx || col.posZ() >= cMaxZVtx) { return false; } - if constexpr (run == kRun3) { // Run3 Min-Bias Trigger - // select centrality estimator - if (cCentEstimator == kCentFT0M) { - cent = col.centFT0M(); - } else if (cCentEstimator == kCentFT0C) { - cent = col.centFT0C(); - } - if (cSel8Trig && !col.sel8()) { - return false; - } - } else { // Run2 Min-Bias Trigger - cent = col.centRun2V0M(); - if (cInt7Trig && !col.alias_bit(kINT7)) { - return false; - } - if (cSel7Trig && !col.sel7()) { - return false; - } + // Run 3 Min-Bias Trigger + if (cSel8Trig && !col.sel8()) { + return false; + } + if (cCentEstimator == kCentFT0M) { + cent = col.centFT0M(); + } else if (cCentEstimator == kCentFT0C) { + cent = col.centFT0C(); } if (cent <= cMinCent || cent >= cMaxCent) { // select centrality percentile class @@ -571,391 +572,276 @@ struct LambdaTableProducer { return true; } - // Kinematic Selection - bool kinCutSelection(float const& pt, float const& rap, float const& ptMin, float const& ptMax, float const& rapMax) - { - if (pt <= ptMin || pt >= ptMax || rap >= rapMax) { - return false; - } - - return true; - } - - // Track Selection - template - bool selTrack(T const& track) - { - if (!kinCutSelection(track.pt(), std::abs(track.eta()), cTrackMinPt, cTrackMaxPt, cTrackEtaCut)) { - return false; - } - - if (track.tpcNClsCrossedRows() <= cMinTpcCrossedRows) { - return false; - } - - return true; - } - - // Daughter Track Selection + // Ambiguous track rejection template - bool selDaughterTracks(V const& v0, T const&, ParticleType const& v0Type) + bool hasAmbiguousDaughters(V const& v0, T const&) { auto posTrack = v0.template posTrack_as(); auto negTrack = v0.template negTrack_as(); - if (!selTrack(posTrack) || !selTrack(negTrack)) { - return false; - } + auto posTrackCompCols = posTrack.compatibleCollIds(); + auto negTrackCompCols = negTrack.compatibleCollIds(); - // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters - float dcaProton = 0., dcaPion = 0.; - if (v0Type == kLambda) { - dcaProton = std::abs(v0.dcapostopv()); - dcaPion = std::abs(v0.dcanegtopv()); - } else if (v0Type == kAntiLambda) { - dcaPion = std::abs(v0.dcapostopv()); - dcaProton = std::abs(v0.dcanegtopv()); + // Check if daughter tracks belongs to more than one collision (Ambiguous Tracks) + if (posTrackCompCols.size() > 1 || negTrackCompCols.size() > 1) { + return true; } - if (dcaProton < cMinDcaProtonToPV || dcaPion < cMinDcaPionToPV) { - return false; + // Check if compatible collision index matches the track collision index + if (((posTrackCompCols.size() != 0) && (posTrackCompCols[0] != posTrack.collisionId())) || + ((negTrackCompCols.size() != 0) && (negTrackCompCols[0] != negTrack.collisionId()))) { + return true; } - return true; + // Pass as not ambiguous + return false; } - template - bool topoCutSelection(C const& col, V const& v0, T const&) + template + bool selLambdaDauTracks(const V& v0, const T& postrack, const T& negtrack, ParticleType& partType) { - // DCA - if (v0.dcaV0daughters() <= cMinV0DcaDaughters || v0.dcaV0daughters() >= cMaxV0DcaDaughters) { + // Kinematic selection + if (postrack.pt() <= cTrackMinPt || negtrack.pt() <= cTrackMinPt || std::abs(postrack.eta()) >= cTrackEtaCut || std::abs(negtrack.eta()) >= cTrackEtaCut || postrack.tpcNClsCrossedRows() <= cMinTpcCrossedRows || negtrack.tpcNClsCrossedRows() <= cMinTpcCrossedRows) { return false; } - if (v0.dcav0topv() <= cMinDcaV0ToPV || v0.dcav0topv() >= cMaxDcaV0ToPV) { + // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters + if (partType == kLambda) { + if (std::abs(v0.dcapostopv()) <= cMinDcaProtonToPV || std::abs(v0.dcanegtopv()) <= cMinDcaPionToPV) { + return false; + } + } else if (partType == kAntiLambda) { + if (std::abs(v0.dcapostopv()) <= cMinDcaPionToPV || std::abs(v0.dcanegtopv()) <= cMinDcaProtonToPV) { + return false; + } + } else { return false; } - if (v0.v0radius() <= cMinV0TransRadius || v0.v0radius() >= cMaxV0TransRadius) { - return false; - } + // Daughter track PID [Dau1 = PosTrack, Dau2 = NegTrack] + float tpcNSigmaDau1 = 0., tpcNSigmaDau2 = 0.; - // ctau - float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; - if (ctau <= cMinV0CTau || ctau >= cMaxV0CTau) { + if (partType == kLambda) { + tpcNSigmaDau1 = postrack.tpcNSigmaPr(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPi(); + } else if (partType == kAntiLambda) { + tpcNSigmaDau1 = postrack.tpcNSigmaPi(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPr(); + } else { + LOGF(fatal, "Particle call not Lambda !!!"); return false; } - // cosine of pointing angle - if (v0.v0cosPA() <= cMinV0CosPA) { + if (std::abs(tpcNSigmaDau1) >= cTpcNsigmaCut || std::abs(tpcNSigmaDau2) >= cTpcNsigmaCut) { return false; } - // all selection criterion passed (Return True) return true; } - template - bool selLambdaDauWithTpcPid(T const& postrack, T const& negtrack) + template + bool selLambda(C const& collision, V const& v0, T const& tracks, ParticleType& partType) { - bool returnFlag = false; - float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; - - switch (part) { - // postrack = Proton, negtrack = Pion - case kLambda: - tpcNSigmaPr = postrack.tpcNSigmaPr(); - tpcNSigmaPi = negtrack.tpcNSigmaPi(); - break; - - // negtrack = Proton, postrack = Pion - case kAntiLambda: - tpcNSigmaPr = negtrack.tpcNSigmaPr(); - tpcNSigmaPi = postrack.tpcNSigmaPi(); - break; + // Initialize daughter tracks + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + // Kinematic selections + if (v0.pt() <= cLambdaMinPt || v0.pt() >= cLambdaMaxPt || std::abs(v0.yLambda()) >= cLambdaRapCut) { + return false; } - if (std::abs(tpcNSigmaPr) < cTpcNsigmaCut && std::abs(tpcNSigmaPi) < cTpcNsigmaCut) { - returnFlag = true; + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0KinCuts); + + // Decay length + float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda0; + + // Topological selections + if (v0.dcaV0daughters() >= cMaxDcaV0Daughters || v0.dcav0topv() >= cMaxDcaV0ToPV || v0.v0radius() <= cMinV0TransRadius || v0.v0Type() != cV0TypeSelection || ctauLambda >= cMaxV0CTau || v0.v0cosPA() <= cMinV0CosPA) { + return false; } - return returnFlag; - } + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0TopoSel); - template - bool selLambdaMassWindow(V const& v0, T const&, ParticleType& v0type) - { - // Kshort mass rejection hypothesis - if (cKshortRejFlag && (std::abs(v0.mK0Short() - MassK0Short) <= cKshortRejMassWindow)) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kV0KShortMassRej); + // K0s mass rejection + if (std::abs(v0.mK0Short() - MassK0Short) <= cKshortRejMassWindow) { return false; } - // initialize daughter tracks - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassK0ShortMassRej); - // initialize selection flags + // Apply Lambda Mass Hypothesis bool lambdaFlag = false, antiLambdaFlag = false; - // get v0 track as lambda - if ((std::abs(v0.mLambda() - MassLambda0) <= cV0MassWindow) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + // Check for Lambda + if (std::abs(v0.mLambda() - MassLambda0) < cLambdaMassWindow) { lambdaFlag = true; - v0type = kLambda; + partType = kLambda; } - // get v0 track as anti-lambda - if (((std::abs(v0.mAntiLambda() - MassLambda0) <= cV0MassWindow)) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + // Check for AntiLambda + if (std::abs(v0.mAntiLambda() - MassLambda0) < cLambdaMassWindow) { antiLambdaFlag = true; - v0type = kAntiLambda; + partType = kAntiLambda; } - if (!lambdaFlag && !antiLambdaFlag) { // neither Lambda nor Anti-Lambda - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaNotAntiLambda); - return false; - } else if (lambdaFlag && antiLambdaFlag) { // check if the track is identified as lambda and anti-lambda both (DISCARD THIS TRACK) + // Check if the v0 is both Lambda and Anti-Lambda or neither + if (lambdaFlag && antiLambdaFlag) { histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsBothLambdaAntiLambda); return false; - } - - if (lambdaFlag || antiLambdaFlag) { - return true; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaAfterSel); - - return false; - } - - template - bool selV0Particle(C const& col, V const& v0, T const& tracks, ParticleType& v0Type) - { - // Apply Lambda Mass Hypothesis - if (!selLambdaMassWindow(v0, tracks, v0Type)) { + } else if (!lambdaFlag && !antiLambdaFlag) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaNotAntiLambda); return false; } histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsLambdaOrAntiLambda); - // Apply Daughter Track Selection - if (!selDaughterTracks(v0, tracks, v0Type)) { + // Select Lambda daughters + if (!selLambdaDauTracks(v0, postrack, negtrack, partType)) { return false; } histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0DauTrackSel); - // Apply Kinematic Selection - float rap = 0.; - if (!cDoEtaAnalysis) { - rap = std::abs(v0.yLambda()); - } else { - rap = std::abs(v0.eta()); - } - - if (!kinCutSelection(v0.pt(), rap, cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { + // Remove lambda with ambiguous daughters + if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { return false; } - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0KinCuts); - - // Apply Topological Selection - if (!topoCutSelection(col, v0, tracks)) { - return false; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0TopoSel); - // All Selection Criterion Passed return true; } - template - bool hasAmbiguousDaughters(V const& v0, T const&) + template + bool selKaonTrack(T const& track, float const& rap) { - auto posTrack = v0.template posTrack_as(); - auto negTrack = v0.template negTrack_as(); - - auto posTrackCompCols = posTrack.compatibleCollIds(); - auto negTrackCompCols = negTrack.compatibleCollIds(); - - // Check if daughter tracks belongs to more than one collision (Ambiguous Tracks) - if (posTrackCompCols.size() > 1 || negTrackCompCols.size() > 1) { - return true; + // Kinematic selection + if (track.pt() <= cKaonMinPt || track.pt() >= cKaonMaxPt || std::abs(rap) >= cKaonRapCut) { + return false; } - // Check if compatible collision index matches the track collision index - if (((posTrackCompCols.size() != 0) && (posTrackCompCols[0] != posTrack.collisionId())) || - ((negTrackCompCols.size() != 0) && (negTrackCompCols[0] != negTrack.collisionId()))) { - return true; - } + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonPassKinSel); - // Pass as not ambiguous - return false; - } + // Global track selection + if (cKaonGlobalSel && !track.isGlobalTrackWoDCA()) { + return false; + } - template - PrmScdType isPrimaryV0(V const& v0) - { - auto mcpart = v0.template mcParticle_as(); + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonPassGlobalSel); - // check for secondary lambda - if (!mcpart.isPhysicalPrimary()) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kSecondaryLambda); - return kSecondary; + // Dca selection + if (std::abs(track.dcaXY()) >= cKaonDcaXYCut || std::abs(track.dcaZ()) >= cKaonDcaZCut) { + return false; } - histos.fill(HIST("Tracks/h1f_tracks_info"), kPrimaryLambda); - return kPrimary; - } - - template - bool selTrueMcRecLambda(V const& v0, T const&) - { - auto mcpart = v0.template mcParticle_as(); + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonPassDcaSel); - // check if Lambda/AntiLambda - if (std::abs(mcpart.pdgCode()) != kLambda0) { + // Electron rejection + if (std::abs(track.tpcNSigmaPi()) > cTpcRejCut && std::abs(track.tpcNSigmaKa()) > cTpcRejCut && std::abs(track.tpcNSigmaPr()) > cTpcRejCut && track.tpcNSigmaEl() > cTpcElRejCutMin && track.tpcNSigmaEl() < cTpcElRejCutMax) { return false; } - // Check for daughters - if (cCheckRecoDauFlag) { - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonPassElRejSel); - // check if the daughters have corresponding mcparticle - if (!postrack.has_mcParticle() || !negtrack.has_mcParticle()) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kLambdaDauNotMcParticle); + // Kaon PID TPC + TOF + if (track.hasTOF()) { + if (std::abs(track.tofNSigmaKa()) >= cKaonTofNSigmaCut || std::abs(track.tofNSigmaPi()) < cTofRejCut || std::abs(track.tofNSigmaPr()) < cTofRejCut || std::abs(track.tpcNSigmaKa()) >= cKaonTpcNSigmaCut) { return false; } - - auto mcpostrack = postrack.template mcParticle_as(); - auto mcnegtrack = negtrack.template mcParticle_as(); - - if (mcpart.pdgCode() == kLambda0) { - if (mcpostrack.pdgCode() != kProton || mcnegtrack.pdgCode() != kPiMinus) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kLambdaNotPrPiMinus); - return false; - } - } else if (mcpart.pdgCode() == kLambda0Bar) { - if (mcpostrack.pdgCode() != kPiPlus || mcnegtrack.pdgCode() != kProtonBar) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kAntiLambdaNotAntiPrPiPlus); - return false; - } + } else { + if (track.pt() >= cKaonTpcPtSel || std::abs(track.tpcNSigmaKa()) >= cKaonTpcNSigmaCut || std::abs(track.tpcNSigmaPi()) < cTpcRejCut || std::abs(track.tpcNSigmaPr()) < cTpcRejCut) { + return false; } } + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonPassAllSel); + return true; } + // Correction factors template - float getCorrectionFactors(V const& v0, T const&) + float getCorrectionFactors(V const& v, T const&, float const& rap) { - // Check for efficiency correction flag - if (!cCorrectionFlag) { - return 1.; - } - - // Get from CCDB - auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, -1); - - // Check CCDB Object - if (!ccdbObj) { - LOGF(warning, "CCDB OBJECT NOT FOUND"); - return 1.; - } - - // initialize efficiency factor and primary fraction values - float effCorrFact = 1., primFrac = 1., matchEffFact = 1.; - float rap = (cDoEtaAnalysis) ? v0.eta() : v0.yLambda(); + // Initialize efficiency factor + float effCorrFact = 1., matchEffFact = 1.; // Get Efficiency Factor if (cGetEffFact) { - TObject* objEff = reinterpret_cast(ccdbObj->FindObject(Form("%s", vCorrFactStrings[cCorrFactHist][part].c_str()))); - TH1F* histEff = reinterpret_cast(objEff->Clone()); - if (histEff->GetDimension() == TwoDimCorr) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtCent); - effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt())); - } else if (histEff->GetDimension() == ThreeDimCorr) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtRapCent); - effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt(), rap)); - } else { - histos.fill(HIST("Tracks/h1f_tracks_info"), kNoEffCorr); - LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); - effCorrFact = 1.; - } - delete histEff; - } - - // Get Primary Fraction - // (The dimension of this could be different than efficiency because of large errors !!!) - if (cGetPrimFrac) { - TObject* objPrm = reinterpret_cast(ccdbObj->FindObject(Form("%s", vPrimFracStrings[cPrimFracHist][part].c_str()))); - TH1F* histPrm = reinterpret_cast(objPrm->Clone()); - if (histPrm->GetDimension() == TwoDimCorr) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtCent); - primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt())); - } else if (histPrm->GetDimension() == ThreeDimCorr) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtRapCent); - primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt(), rap)); + TObject* objEff = reinterpret_cast(ccdbObjRecoEff->FindObject(Form("%s", vCorrFactStrings[cCorrFactHist][part].c_str()))); + // check object + if (!objEff) { + LOGF(fatal, "Reco efficiency object not found !"); } else { - histos.fill(HIST("Tracks/h1f_tracks_info"), kNoPFCorr); - LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); - primFrac = 1.; + TH1F* histEff = reinterpret_cast(objEff->Clone()); + if (histEff->GetDimension() == TwoDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtCent); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v.pt())); + } else if (histEff->GetDimension() == ThreeDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtRapCent); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v.pt(), rap)); + } else { + histos.fill(HIST("Tracks/h1f_tracks_info"), kNoEffCorr); + LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); + effCorrFact = 1.; + } + delete histEff; } - delete histPrm; } // Get Matching Efficiency Correction if (cGetMatchEff) { - auto posTrack = v0.template posTrack_as(); - auto negTrack = v0.template negTrack_as(); - auto ccdbObjMatchEff = ccdb->getForTimeStamp(cPathCCDBMatchEff.value, -1); - TObject* objMatchEff = reinterpret_cast(ccdbObjMatchEff->FindObject("hITSTPCMatchingEfficiency")); - TH1F* histMatchEff = reinterpret_cast(objMatchEff->Clone()); - float posTrackMatchEff = histMatchEff->GetBinContent(histMatchEff->FindBin(cent, posTrack.pt())); - float negTrackMatchEff = histMatchEff->GetBinContent(histMatchEff->FindBin(cent, negTrack.pt())); - matchEffFact = posTrackMatchEff * negTrackMatchEff; - delete histMatchEff; - } - - return primFrac * effCorrFact * matchEffFact; - } + TObject* objITSTPCMatchEff = reinterpret_cast(ccdbObjMatchEff->FindObject("hITSTPCMatchingEfficiency")); + TObject* objITSTPCTOFMatchEff = reinterpret_cast(ccdbObjMatchEff->FindObject("hITSTPCTOFMatchingEfficiency")); + if (!objITSTPCMatchEff || !objITSTPCTOFMatchEff) { + LOGF(fatal, "Matching efficiency object not found !"); + } else { + TH1F* histITSTPCMatchEff = reinterpret_cast(objITSTPCMatchEff->Clone()); + TH1F* histITSTPCTOFMatchEff = reinterpret_cast(objITSTPCTOFMatchEff->Clone()); + // Lambda / Anti-Lambda + if constexpr (part == kLambda || part == kAntiLambda) { + auto posTrack = v.template posTrack_as(); + auto negTrack = v.template negTrack_as(); + float posTrackMatchEff = histITSTPCMatchEff->GetBinContent(histITSTPCMatchEff->FindBin(cent, posTrack.pt())); + float negTrackMatchEff = histITSTPCMatchEff->GetBinContent(histITSTPCMatchEff->FindBin(cent, negTrack.pt())); + matchEffFact = posTrackMatchEff * negTrackMatchEff; + } + // K+ /K- + if constexpr (part == kKaonPlus || part == kKaonMinus) { + float trackItsTpcMatchEff = histITSTPCMatchEff->GetBinContent(histITSTPCMatchEff->FindBin(cent, v.pt())); + float trackItsTpcTofMatchEff = histITSTPCTOFMatchEff->GetBinContent(histITSTPCTOFMatchEff->FindBin(cent, v.pt())); + matchEffFact = trackItsTpcMatchEff * trackItsTpcTofMatchEff; + } - template - void fillLambdaMothers(V const& v0, T const&, PrmScdType const& ps) - { - auto mcpart = v0.template mcParticle_as(); - auto lambdaMothers = mcpart.template mothers_as(); - if (ps == kPrimary) { - histos.fill(HIST("Tracks/h2f_primary_lambda_mothers_pdg"), lambdaMothers[0].pdgCode(), v0.pt()); - } else { - histos.fill(HIST("Tracks/h2f_secondary_lambda_mothers_pdg"), lambdaMothers[0].pdgCode(), v0.pt()); + histos.fill(HIST("Tracks/h1f_tracks_info"), kMatchEffCorr); + delete histITSTPCMatchEff; + delete histITSTPCTOFMatchEff; + } } + + return effCorrFact * matchEffFact; } + // Lambda QA template void fillLambdaQAHistos(C const& col, V const& v0, T const&) { - static constexpr std::string_view SubDir[] = {"QA/Lambda/", "QA/AntiLambda/"}; - - // daugthers + // Daugthers auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); - float mass = 0.; + // Mass + float mass = 0.; if constexpr (part == kLambda) { mass = v0.mLambda(); } else { mass = v0.mAntiLambda(); } - // ctau - float e = RecoDecay::e(v0.px(), v0.py(), v0.pz(), mass); - float gamma = e / mass; + // Decay length float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; - float gctau = ctau * gamma; + histos.fill(HIST(SubDir[part]) + HIST("h3f_centmasspt"), cent, mass, v0.pt()); histos.fill(HIST(SubDir[part]) + HIST("h2f_qt_vs_alpha"), v0.alpha(), v0.qtarm()); histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_daughters"), v0.dcaV0daughters()); histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_pos_to_PV"), v0.dcapostopv()); @@ -964,19 +850,6 @@ struct LambdaTableProducer { histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_cospa"), v0.v0cosPA()); histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_radius"), v0.v0radius()); histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_ctau"), ctau); - histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_gctau"), gctau); - - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_pt"), postrack.pt()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_eta"), postrack.eta()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_phi"), postrack.phi()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_xisqperclusterits"), postrack.pt(), postrack.itsChi2NCl()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_xisqperclustertpc"), postrack.pt(), postrack.tpcChi2NCl()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_pt"), negtrack.pt()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_eta"), negtrack.eta()); - histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_phi"), negtrack.phi()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_xisqperclusterits"), negtrack.pt(), negtrack.itsChi2NCl()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_xisqperclustertpc"), negtrack.pt(), negtrack.tpcChi2NCl()); - histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dcaXY_vs_pt"), postrack.pt(), postrack.dcaXY()); histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dcaXY_vs_pt"), negtrack.pt(), negtrack.dcaXY()); histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dEdx_vs_p"), postrack.tpcInnerParam(), postrack.tpcSignal()); @@ -987,19 +860,19 @@ struct LambdaTableProducer { histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pi_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); } - // Fill Lambda Kinematic Histograms - template - void fillKinematicHists(float const& pt, float const& eta, float const& y, float const& phi) + // Kaon QA + template + void fillKaonQA(T const& track) { - static constexpr std::string_view SubDirRG[] = {"McRec/", "McGen/"}; - static constexpr std::string_view SubDirPart[] = {"Lambda/", "AntiLambda/"}; - - histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hPt"), pt); - histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hEta"), eta); - histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hRap"), y); - histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hPhi"), phi); + histos.fill(HIST(SubDir[part]) + HIST("hdEdX"), track.pt(), track.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("hTPCNSigma"), track.pt(), track.tpcNSigmaKa()); + if (track.hasTOF()) { + histos.fill(HIST(SubDir[part]) + HIST("hTOFSignal"), track.pt(), track.beta()); + histos.fill(HIST(SubDir[part]) + HIST("hTOFNSigma"), track.pt(), track.tofNSigmaKa()); + } } + // Get matching efficiency template void getMatchEffHist(T const& tracks) { @@ -1017,19 +890,23 @@ struct LambdaTableProducer { if (track.pt() > cTrackMinPt && std::abs(track.eta()) < cTrackEtaCut && track.hasITS() && track.hasTPC() && track.isQualityTrackITS() && track.isQualityTrackTPC()) { histos.fill(HIST("Tracks/h2f_itstpctrack_centpt"), cent, track.pt()); } + // ITS+TPC+TOF track + if (track.pt() > cTrackMinPt && std::abs(track.eta()) < cTrackEtaCut && track.hasITS() && track.hasTPC() && track.isQualityTrackITS() && track.isQualityTrackTPC() && track.hasTOF()) { + histos.fill(HIST("Tracks/h2f_itstpctoftrack_centpt"), cent, track.pt()); + } } } // Reconstructed Level Tables - template - void fillLambdaRecoTables(C const& collision, V const& v0tracks, T const& tracks) + template + void fillLambdaRecoTables(C const& collision, B const&, V const& v0tracks, T const& tracks) { // Total Collisions histos.fill(HIST("Events/h1f_collisions_info"), kTotCol); // Select Collision (Only for Data... McRec has been selected already !!!) if constexpr (dmc == kData) { - if (!selCollision(collision)) { + if (!selCollision(collision)) { return; } } @@ -1043,17 +920,16 @@ struct LambdaTableProducer { lambdaCollisionTable(cent, mult, collision.posX(), collision.posY(), collision.posZ()); // initialize v0track objects - ParticleType v0Type = kLambda; - PrmScdType v0PrmScdType = kPrimary; - float mass = 0., corr_fact = 1.; + ParticleType partType = kLambda; + float lambdaMass = 0., lambdaCorrFact = 1.; - // Loop over V0s + // Loop over V0s to select Lambda for (auto const& v0 : v0tracks) { - // daugthers + // Daugthers auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); - // check for corresponding MCGen Particle + // Check for corresponding MCGen Particle if constexpr (dmc == kMC) { histos.fill(HIST("Tracks/h1f_tracks_info"), kTracksBeforeHasMcParticle); if (!v0.has_mcParticle() || !postrack.has_mcParticle() || !negtrack.has_mcParticle()) { // check corresponding MC particle @@ -1064,185 +940,158 @@ struct LambdaTableProducer { histos.fill(HIST("Tracks/h1f_tracks_info"), kAllV0Tracks); histos.fill(HIST("Tracks/h2f_armpod_before_sel"), v0.alpha(), v0.qtarm()); - // Select V0 Particle as Lambda/AntiLambda - if (!selV0Particle(collision, v0, tracks, v0Type)) { - continue; - } - - // Select V0 Type Selection - if (cV0TypeSelFlag && v0.v0Type() != cV0TypeSelection) { + // Select V0 as Lambda/AntiLambda + if (!selLambda(collision, v0, tracks, partType)) { continue; } // We have v0 as lambda histos.fill(HIST("Tracks/h1f_tracks_info"), kAllSelPassed); + histos.fill(HIST("Tracks/h2f_armpod_after_sel"), v0.alpha(), v0.qtarm()); - // Remove lambda with ambiguous daughters (Only for run3) - if constexpr (run == kRun3) { - if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { - continue; - } + // Get Lambda mass and correction factor + lambdaMass = (partType == kLambda) ? v0.mLambda() : v0.mAntiLambda(); + if (cGetCorrectionFlag) { + lambdaCorrFact = (partType == kLambda) ? getCorrectionFactors(v0, tracks, v0.yLambda()) : getCorrectionFactors(v0, tracks, v0.yLambda()); } - // Get Lambda mass and kinematic variables - mass = (v0Type == kLambda) ? v0.mLambda() : v0.mAntiLambda(); - - // do MC analysis - if constexpr (dmc == kMC) { - histos.fill(HIST("Tracks/h2f_tracks_pid_before_sel"), v0.mcParticle().pdgCode(), v0.pt()); + // fill lambda qa + if (partType == kLambda) { + fillLambdaQAHistos(collision, v0, tracks); + } else { + fillLambdaQAHistos(collision, v0, tracks); + } - // Get Primary/Secondary Lambda - if (cSelMCPSV0) { - v0PrmScdType = isPrimaryV0(v0); - } + // Fill Lambda/AntiLambda Table + lambdaTrackTable(lambdaCollisionTable.lastIndex(), v0.px(), v0.py(), v0.pz(), + v0.pt(), v0.eta(), v0.phi(), v0.yLambda(), lambdaMass, + v0.template posTrack_as().index(), v0.template negTrack_as().index(), + (int8_t)partType, lambdaCorrFact); + } - // check for true Lambda/Anti-Lambda - if (cSelectTrueLambda && !selTrueMcRecLambda(v0, tracks)) { + // Loop over tracks to select Kaon + float kaonCorrFact = 0.; + for (auto const& track : tracks) { + // Check corresponding MC particle + if constexpr (dmc == kMC) { + if (!track.has_mcParticle()) { continue; } - - // get mothers information - fillLambdaMothers(v0, tracks, v0PrmScdType); - - histos.fill(HIST("Tracks/h1f_tracks_info"), kPassTrueLambdaSel); - histos.fill(HIST("Tracks/h2f_tracks_pid_after_sel"), v0.mcParticle().pdgCode(), v0.pt()); } - histos.fill(HIST("Tracks/h2f_armpod_after_sel"), v0.alpha(), v0.qtarm()); + // All charged tracks + histos.fill(HIST("Tracks/h1f_kaon_sel"), kKaonAllChargedTracks); - // get correction factors - corr_fact = (v0Type == kLambda) ? getCorrectionFactors(v0, tracks) : getCorrectionFactors(v0, tracks); + // Kaon rapidity + std::array mom = {track.px(), track.py(), track.pz()}; + float rap = RecoDecay::y(mom, MassKPlus); + if (!selKaonTrack(track, rap)) { // Kaon selection + continue; + } - // fill lambda qa - if (v0Type == kLambda) { - histos.fill(HIST("Tracks/h1f_lambda_pt_vs_invm"), mass, v0.pt()); - fillLambdaQAHistos(collision, v0, tracks); - fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); + // K+ / K- + if (track.sign() >= 0) { + fillKaonQA(track); + partType = kKaonPlus; + } else if (track.sign() <= 0) { + fillKaonQA(track); + partType = kKaonMinus; } else { - histos.fill(HIST("Tracks/h1f_antilambda_pt_vs_invm"), mass, v0.pt()); - fillLambdaQAHistos(collision, v0, tracks); - fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); + continue; } - // Fill Lambda/AntiLambda Table - lambdaTrackTable(lambdaCollisionTable.lastIndex(), v0.px(), v0.py(), v0.pz(), - v0.pt(), v0.eta(), v0.phi(), v0.yLambda(), mass, - v0.template posTrack_as().index(), v0.template negTrack_as().index(), - v0.v0cosPA(), v0.dcaV0daughters(), (int8_t)v0Type, v0PrmScdType, corr_fact); + // Get Kaon correction factor + if (cGetCorrectionFlag) { + kaonCorrFact = (partType == kKaonPlus) ? getCorrectionFactors(track, track, rap) : getCorrectionFactors(track, track, rap); + } + + // Fill table + kaonTrackTable(lambdaCollisionTable.lastIndex(), track.px(), track.py(), track.pz(), + track.pt(), track.eta(), track.phi(), rap, MassKaonCharged, + track.globalIndex(), (int8_t)partType, kaonCorrFact); } } // MC Generater Level Tables - template + template void fillLambdaMcGenTables(C const& mcCollision, M const& mcParticles) { // Fill McGen Collision Table lambdaMCGenCollisionTable(cent, mult, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); // initialize track objects - ParticleType v0Type = kLambda; - PrmScdType v0PrmScdType = kPrimary; - float rap = 0.; + ParticleType partType = kLambda; // Loop over MC particles for (auto const& mcpart : mcParticles) { - // check for Lambda first - if (mcpart.pdgCode() == kLambda0) { - v0Type = kLambda; - } else if (mcpart.pdgCode() == kLambda0Bar) { - v0Type = kAntiLambda; + // Check for Primary Lambda/Anti-Lambda/K+/K- + if (mcpart.isPhysicalPrimary() && mcpart.pdgCode() == kLambda0) { + partType = kLambda; + } else if (mcpart.isPhysicalPrimary() && mcpart.pdgCode() == kLambda0Bar) { + partType = kAntiLambda; + } else if (mcpart.isPhysicalPrimary() && mcpart.pdgCode() == kKPlus) { + partType = kKaonPlus; + } else if (mcpart.isPhysicalPrimary() && mcpart.pdgCode() == kKMinus) { + partType = kKaonMinus; } else { continue; } - // check for Primary Lambda/AntiLambda - if (mcpart.isPhysicalPrimary()) { - v0PrmScdType = kPrimary; - } else { - v0PrmScdType = kSecondary; - } + // Fill Lambda Table + if (partType == kLambda || partType == kAntiLambda) { + // Kinematic selection + if (mcpart.pt() <= cLambdaMinPt || mcpart.pt() >= cLambdaMaxPt || std::abs(mcpart.y()) >= cLambdaRapCut) { + continue; + } - // Decide Eta/Rap - if (!cDoEtaAnalysis) { - rap = mcpart.y(); - } else { - rap = mcpart.eta(); - } + histos.fill(HIST("Tracks/h1f_tracks_info"), kGenTotAccLambda); - // Apply Kinematic Acceptance - if (!kinCutSelection(mcpart.pt(), std::abs(rap), cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { - continue; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kGenTotAccLambda); + // get daughter track info and check for decay channel flag + if (!mcpart.has_daughters()) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaNoDau); + continue; + } + auto dautracks = mcpart.template daughters_as(); + std::vector daughterPDGs, daughterIDs; + for (auto const& dautrack : dautracks) { + daughterPDGs.push_back(dautrack.pdgCode()); + daughterIDs.push_back(dautrack.globalIndex()); + } - // get daughter track info and check for decay channel flag - if (!mcpart.has_daughters()) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaNoDau); - continue; - } - auto dautracks = mcpart.template daughters_as(); - std::vector daughterPDGs, daughterIDs; - std::vector vDauPt, vDauEta, vDauRap, vDauPhi; - for (auto const& dautrack : dautracks) { - daughterPDGs.push_back(dautrack.pdgCode()); - daughterIDs.push_back(dautrack.globalIndex()); - vDauPt.push_back(dautrack.pt()); - vDauEta.push_back(dautrack.eta()); - vDauRap.push_back(dautrack.y()); - vDauPhi.push_back(dautrack.phi()); - } - if (cGenDecayChannel) { // check decay channel - if (v0Type == kLambda) { - if (daughterPDGs[0] != kProton || daughterPDGs[1] != kPiMinus) { - continue; - } - } else if (v0Type == kAntiLambda) { - if (daughterPDGs[0] != kProtonBar || daughterPDGs[1] != kPiPlus) { - continue; - } + if (partType == kLambda) { + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[0]); + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[1]); + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), mcpart.pdgCode()); + } else { + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[0]); + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[1]); + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), mcpart.pdgCode()); } + // Fill table + lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.px(), mcpart.py(), mcpart.pz(), + mcpart.pt(), mcpart.eta(), mcpart.phi(), mcpart.y(), RecoDecay::m(mcpart.p(), mcpart.e()), + daughterIDs[0], daughterIDs[1], (int8_t)partType, 1.); } - histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaToPrPi); - - if (v0Type == kLambda) { - histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[0]); - histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[1]); - histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), mcpart.pdgCode()); - histos.fill(HIST("McGen/Lambda/Proton/hPt"), vDauPt[0]); - histos.fill(HIST("McGen/Lambda/Proton/hEta"), vDauEta[0]); - histos.fill(HIST("McGen/Lambda/Proton/hRap"), vDauRap[0]); - histos.fill(HIST("McGen/Lambda/Proton/hPhi"), vDauPhi[0]); - histos.fill(HIST("McGen/Lambda/Pion/hPt"), vDauPt[1]); - histos.fill(HIST("McGen/Lambda/Pion/hEta"), vDauEta[1]); - histos.fill(HIST("McGen/Lambda/Pion/hRap"), vDauRap[1]); - histos.fill(HIST("McGen/Lambda/Pion/hPhi"), vDauPhi[1]); - fillKinematicHists(mcpart.pt(), mcpart.eta(), mcpart.y(), mcpart.phi()); - } else { - histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[0]); - histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[1]); - histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), mcpart.pdgCode()); - histos.fill(HIST("McGen/AntiLambda/Pion/hPt"), vDauPt[0]); - histos.fill(HIST("McGen/AntiLambda/Pion/hEta"), vDauEta[0]); - histos.fill(HIST("McGen/AntiLambda/Pion/hRap"), vDauRap[0]); - histos.fill(HIST("McGen/AntiLambda/Pion/hPhi"), vDauPhi[0]); - histos.fill(HIST("McGen/AntiLambda/Proton/hPt"), vDauPt[1]); - histos.fill(HIST("McGen/AntiLambda/Proton/hEta"), vDauEta[1]); - histos.fill(HIST("McGen/AntiLambda/Proton/hRap"), vDauRap[1]); - histos.fill(HIST("McGen/AntiLambda/Proton/hPhi"), vDauPhi[1]); - fillKinematicHists(mcpart.pt(), mcpart.eta(), mcpart.y(), mcpart.phi()); - } + // Fill Kaon Table + if (partType == kKaonPlus || partType == kKaonMinus) { + // Kinematic selection + if (mcpart.pt() <= cKaonMinPt || mcpart.pt() >= cKaonMaxPt || std::abs(mcpart.y()) >= cKaonRapCut) { + continue; + } + + // histos.fill(HIST("KaonTracks/h1f_tracks_info"), kGenAccKaon); - // Fill Lambda McGen Table - lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.px(), mcpart.py(), mcpart.pz(), + // Fill table + kaonMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.px(), mcpart.py(), mcpart.pz(), mcpart.pt(), mcpart.eta(), mcpart.phi(), mcpart.y(), RecoDecay::m(mcpart.p(), mcpart.e()), - daughterIDs[0], daughterIDs[1], (int8_t)v0Type, -999., -999., v0PrmScdType, 1.); + mcpart.globalIndex(), (int8_t)partType, 1.); + } } } - template - void analyzeMcRecoGen(M const& mcCollision, C const& collisions, V const& V0s, T const& tracks, P const& mcParticles) + template + void analyzeMcRecoGen(M const& mcCollision, C const& collisions, B const& bc, V const& V0s, T const& tracks, P const& mcParticles) { // Number of Rec Collisions Associated to the McGen Collision int nRecCols = collisions.size(); @@ -1255,50 +1104,43 @@ struct LambdaTableProducer { } histos.fill(HIST("McGen/h1f_collisions_info"), kTotCol); // Check the reco collision - if (!collisions.begin().has_mcCollision() || !selCollision(collisions.begin()) || collisions.begin().mcCollisionId() != mcCollision.globalIndex()) { + if (!collisions.begin().has_mcCollision() || !selCollision(collisions.begin()) || collisions.begin().mcCollisionId() != mcCollision.globalIndex()) { return; } histos.fill(HIST("McGen/h1f_collisions_info"), kPassSelCol); histos.fill(HIST("McGen/h2f_collision_posZ"), mcCollision.posZ(), collisions.begin().posZ()); - auto v0Tracks = V0s.sliceBy(perCollision, collisions.begin().globalIndex()); - fillLambdaRecoTables(collisions.begin(), v0Tracks, tracks); - fillLambdaMcGenTables(mcCollision, mcParticles); + auto v0Tracks = V0s.sliceBy(v0sPerCollision, collisions.begin().globalIndex()); + auto tracksThisCollision = tracks.sliceBy(tracksPerCollision, collisions.begin().globalIndex()); + fillLambdaRecoTables(collisions.begin(), bc, v0Tracks, tracksThisCollision); + fillLambdaMcGenTables(mcCollision, mcParticles); } - // Collision, tracks and V0s - using CollisionsRun3 = soa::Join; - using CollisionsRun2 = soa::Join; - using Tracks = soa::Join; - using TracksRun2 = soa::Join; + // BC, Collision, tracks and V0s + using BCsRun3 = soa::Join; + using Collisions = soa::Join; + using Tracks = soa::Join; using TracksMC = soa::Join; - using TracksMCRun2 = soa::Join; using McV0Tracks = soa::Join; SliceCache cache; - Preslice> perCollision = aod::v0data::collisionId; + Preslice> v0sPerCollision = aod::v0data::collisionId; + Preslice tracksPerCollision = aod::track::collisionId; - void processDummy(CollisionsRun3::iterator const&) {} + void processDummy(Collisions::iterator const&) {} PROCESS_SWITCH(LambdaTableProducer, processDummy, "Dummy Process", true); - void processDataRun3(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) + void processData(Collisions::iterator const& collision, BCsRun3 const& bc, aod::V0Datas const& V0s, Tracks const& tracks) { - fillLambdaRecoTables(collision, V0s, tracks); + fillLambdaRecoTables(collision, bc, V0s, tracks); } - PROCESS_SWITCH(LambdaTableProducer, processDataRun3, "Process for Run3 DATA", false); + PROCESS_SWITCH(LambdaTableProducer, processData, "Process for DATA", false); - void processDataRun2(CollisionsRun2::iterator const& collision, aod::V0Datas const& V0s, TracksRun2 const& tracks) - { - fillLambdaRecoTables(collision, V0s, tracks); - } - - PROCESS_SWITCH(LambdaTableProducer, processDataRun2, "Process for Run2 DATA", false); - - void processMatchEffData(CollisionsRun3::iterator const& collision, Tracks const& tracks) + void processMatchEffData(Collisions::iterator const& collision, Tracks const& tracks) { // check collision - if (!selCollision(collision)) { + if (!selCollision(collision)) { return; } // Get Matching Efficiency @@ -1307,34 +1149,22 @@ struct LambdaTableProducer { PROCESS_SWITCH(LambdaTableProducer, processMatchEffData, "Process for Matching Efficieny Calculation", false); - void processMCRecoRun3(soa::Join::iterator const& collision, aod::McCollisions const&, - McV0Tracks const& V0s, TracksMC const& tracks, aod::McParticles const&) - { - // check collision - if (!selCollision(collision)) { - return; - } - fillLambdaRecoTables(collision, V0s, tracks); - } - - PROCESS_SWITCH(LambdaTableProducer, processMCRecoRun3, "Process for Run3 McReco DATA", false); - - void processMCRecoRun2(soa::Join::iterator const& collision, aod::McCollisions const&, - McV0Tracks const& V0s, TracksMCRun2 const& tracks, aod::McParticles const&) + void processMCReco(soa::Join::iterator const& collision, aod::McCollisions const&, BCsRun3 const& bc, + McV0Tracks const& V0s, TracksMC const& tracks, aod::McParticles const&) { // check collision - if (!selCollision(collision)) { + if (!selCollision(collision)) { return; } - fillLambdaRecoTables(collision, V0s, tracks); + fillLambdaRecoTables(collision, bc, V0s, tracks); } - PROCESS_SWITCH(LambdaTableProducer, processMCRecoRun2, "Process for Run2 McReco DATA", false); + PROCESS_SWITCH(LambdaTableProducer, processMCReco, "Process for McReco DATA", false); - void processMatchEffMCReco(soa::Join::iterator const& collision, aod::McCollisions const&, TracksMC const& tracks, aod::McParticles const&) + void processMatchEffMCReco(soa::Join::iterator const& collision, aod::McCollisions const&, TracksMC const& tracks, aod::McParticles const&) { // check collision - if (!selCollision(collision)) { + if (!selCollision(collision)) { return; } // Get Matching Efficiency @@ -1343,25 +1173,15 @@ struct LambdaTableProducer { PROCESS_SWITCH(LambdaTableProducer, processMatchEffMCReco, "Process for Matching Efficieny Calculation at MC Reconstructed Level", false); - void processMCRun3(aod::McCollisions::iterator const& mcCollision, - soa::SmallGroups> const& collisions, - McV0Tracks const& V0s, TracksMC const& tracks, - aod::McParticles const& mcParticles) + void processMCRecoGen(aod::McCollisions::iterator const& mcCollision, + soa::SmallGroups> const& collisions, BCsRun3 const& bc, + McV0Tracks const& V0s, TracksMC const& tracks, + aod::McParticles const& mcParticles) { - analyzeMcRecoGen(mcCollision, collisions, V0s, tracks, mcParticles); + analyzeMcRecoGen(mcCollision, collisions, bc, V0s, tracks, mcParticles); } - PROCESS_SWITCH(LambdaTableProducer, processMCRun3, "Process for Run3 MC RecoGen", false); - - void processMCRun2(aod::McCollisions::iterator const& mcCollision, - soa::SmallGroups> const& collisions, - McV0Tracks const& V0s, TracksMCRun2 const& tracks, - aod::McParticles const& mcParticles) - { - analyzeMcRecoGen(mcCollision, collisions, V0s, tracks, mcParticles); - } - - PROCESS_SWITCH(LambdaTableProducer, processMCRun2, "Process for Run2 MC RecoGen", false); + PROCESS_SWITCH(LambdaTableProducer, processMCRecoGen, "Process for MC RecoGen", false); }; struct LambdaTracksExtProducer { @@ -1371,11 +1191,6 @@ struct LambdaTracksExtProducer { // Configurables Configurable cAcceptAllLambda{"cAcceptAllLambda", false, "Accept all Lambda"}; Configurable cRejAllLambdaShaDau{"cRejAllLambdaShaDau", true, "Reject all Lambda sharing daughters"}; - Configurable cSelLambdaMassPdg{"cSelLambdaMassPdg", false, "Select Lambda closest to Pdg Mass"}; - Configurable cSelLambdaTScore{"cSelLambdaTScore", false, "Select Lambda based on t-score"}; - Configurable cA{"cA", 0.6, "a * |lambdaMass - lambdaPdgMass|"}; - Configurable cB{"cB", 0.6, "b * DcaPrPi"}; - Configurable cC{"cC", 0.6, "c * Cos(theta_{PA})"}; // Histogram Registry. HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -1401,12 +1216,7 @@ struct LambdaTracksExtProducer { // InvMass, DcaDau and CosPA histos.add("Reco/h1f_lambda_invmass", "M_{p#pi}", kTH1F, {axisMass}); - histos.add("Reco/h1f_lambda_cospa", "cos(#theta_{PA})", kTH1F, {axisCPA}); - histos.add("Reco/h1f_lambda_dcadau", "DCA_{p#pi} at V0 Decay Vertex", kTH1F, {axisDcaDau}); histos.add("Reco/h1f_antilambda_invmass", "M_{p#pi}", kTH1F, {axisMass}); - histos.add("Reco/h1f_antilambda_cospa", "cos(#theta_{PA})", kTH1F, {axisCPA}); - histos.add("Reco/h1f_antilambda_dcadau", "DCA_{p#pi} at V0 Decay Vertex", kTH1F, {axisDcaDau}); - histos.addClone("Reco/", "SharingDau/"); } @@ -1415,14 +1225,10 @@ struct LambdaTracksExtProducer { { static constexpr std::string_view SubDir[] = {"Reco/", "SharingDau/"}; - if (track.v0Type() == kLambda) { + if (track.partType() == kLambda) { histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_invmass"), track.mass()); - histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_dcadau"), track.dcaDau()); - histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_cospa"), track.cosPA()); } else { histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_invmass"), track.mass()); - histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_dcadau"), track.dcaDau()); - histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_cospa"), track.cosPA()); } } @@ -1435,19 +1241,15 @@ struct LambdaTracksExtProducer { int nTotLambda = 0, nTotAntiLambda = 0, nSelLambda = 0, nSelAntiLambda = 0; for (auto const& lambda : tracks) { - bool lambdaMinDeltaMassFlag = true, lambdaMinTScoreFlag = true; bool lambdaSharingDauFlag = false, trueLambdaFlag = false; std::vector vSharedDauLambdaIndex; - float tLambda = 0., tTrack = 0.; - if (lambda.v0Type() == kLambda) { + if (lambda.partType() == kLambda) { ++nTotLambda; - } else if (lambda.v0Type() == kAntiLambda) { + } else if (lambda.partType() == kAntiLambda) { ++nTotAntiLambda; } - tLambda = (cA * std::abs(lambda.mass() - MassLambda0)) + (cB * lambda.dcaDau()) + (cC * std::abs(lambda.cosPA() - 1.)); - for (auto const& track : tracks) { // check lambda index (don't analyze same lambda track !!!) if (lambda.index() == track.index()) { @@ -1460,24 +1262,13 @@ struct LambdaTracksExtProducer { lambdaSharingDauFlag = true; // Fill DEta-DPhi Histogram - if ((lambda.v0Type() == kLambda && track.v0Type() == kAntiLambda) || (lambda.v0Type() == kAntiLambda && track.v0Type() == kLambda)) { + if ((lambda.partType() == kLambda && track.partType() == kAntiLambda) || (lambda.partType() == kAntiLambda && track.partType() == kLambda)) { histos.fill(HIST("h2d_n2_etaphi_LaP_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); - } else if (lambda.v0Type() == kLambda && track.v0Type() == kLambda) { + } else if (lambda.partType() == kLambda && track.partType() == kLambda) { histos.fill(HIST("h2d_n2_etaphi_LaP_LaP"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); - } else if (lambda.v0Type() == kAntiLambda && track.v0Type() == kAntiLambda) { + } else if (lambda.partType() == kAntiLambda && track.partType() == kAntiLambda) { histos.fill(HIST("h2d_n2_etaphi_LaM_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); } - - // decision based on mass closest to PdgMass of Lambda - if (std::abs(lambda.mass() - MassLambda0) > std::abs(track.mass() - MassLambda0)) { - lambdaMinDeltaMassFlag = false; - } - - // decisions based on t-score - tTrack = (cA * std::abs(track.mass() - MassLambda0)) + (cB * track.dcaDau()) + (cC * std::abs(track.cosPA() - 1.)); - if (tLambda > tTrack) { - lambdaMinTScoreFlag = false; - } } } @@ -1492,17 +1283,13 @@ struct LambdaTracksExtProducer { trueLambdaFlag = true; } else if (cRejAllLambdaShaDau && !lambdaSharingDauFlag) { // Reject all lambda sharing daughter trueLambdaFlag = true; - } else if (cSelLambdaMassPdg && lambdaMinDeltaMassFlag) { // Select lambda closest to pdg mass - trueLambdaFlag = true; - } else if (cSelLambdaTScore && lambdaMinTScoreFlag) { // Select lambda based on t-score - trueLambdaFlag = true; } // Multiplicity of selected lambda if (trueLambdaFlag) { - if (lambda.v0Type() == kLambda) { + if (lambda.partType() == kLambda) { ++nSelLambda; - } else if (lambda.v0Type() == kAntiLambda) { + } else if (lambda.partType() == kAntiLambda) { ++nSelAntiLambda; } } @@ -1534,19 +1321,18 @@ struct LambdaTracksExtProducer { struct LambdaR2Correlation { // Global Configurables - Configurable cNPtBins{"cNPtBins", 34, "N pT Bins"}; - Configurable cMinPt{"cMinPt", 0.8, "pT Min"}; - Configurable cMaxPt{"cMaxPt", 4.2, "pT Max"}; - Configurable cNRapBins{"cNRapBins", 20, "N Rapidity Bins"}; + Configurable cLambdaNPtBins{"cLambdaNPtBins", 34, "N pT Bins"}; + Configurable cLambdaPtMin{"cLambdaPtMin", 0.7, "Lambda pT Min"}; + Configurable cLambdaPtMax{"cLambdaPtMax", 3.4, "Lambda pT Max"}; + Configurable cKaonNPtBins{"cKaonNPtBins", 20, "N pT Bins"}; + Configurable cKaonPtMin{"cKaonPtMin", 0.4, "Kaon pT Min"}; + Configurable cKaonPtMax{"cKaonPtMax", 2.4, "Kaon pT Max"}; + + Configurable cNRapBins{"cNRapBins", 10, "N Rapidity Bins"}; Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; - Configurable cAnaSecondaries{"cAnaSecondaries", false, "Analysze Secondaries"}; Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; - Configurable cAnaSecondaryPairs{"cAnaSecondaryPairs", false, "Analyze Secondary Pairs Flag"}; - - // Eta/Rap Analysis - Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Eta/Rap Analysis Flag"}; // Centrality Axis ConfigurableAxis cCentBins{"cCentBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 50.f, 80.0f, 100.f}, "Variable Mult-Bins"}; @@ -1587,12 +1373,12 @@ struct LambdaR2Correlation { const AxisSpec axisChMult(200, 0, 200, "N_{ch}"); const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); const AxisSpec axisMass(100, 1.06, 1.16, "M_{#Lambda} (GeV/#it{c}^{2})"); - const AxisSpec axisPt(cNPtBins, cMinPt, cMaxPt, "p_{T} (GeV/#it{c})"); + const AxisSpec axisPtLambda(cLambdaNPtBins, cLambdaPtMin, cLambdaPtMax, "p_{T} (GeV/#it{c})"); + const AxisSpec axisPtKaon(cKaonNPtBins, cKaonPtMin, cKaonPtMax, "p_{T} (GeV/#it{c})"); const AxisSpec axisEta(cNRapBins, cMinRap, cMaxRap, "#eta"); const AxisSpec axisRap(cNRapBins, cMinRap, cMaxRap, "y"); const AxisSpec axisPhi(cNPhiBins, 0., TwoPI, "#varphi (rad)"); const AxisSpec axisRapPhi(knrapphibins, kminrapphi, kmaxrapphi, "y #varphi"); - const AxisSpec axisQinv(100, 0, 10, "q_{inv} (GeV/#it{c})"); // Create Histograms. // Event @@ -1604,56 +1390,42 @@ struct LambdaR2Correlation { // Efficiency Histograms // Single Particle Efficiencies - histos.add("Reco/Primary/Efficiency/h2f_n1_centpt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPt}); - histos.add("Reco/Primary/Efficiency/h2f_n1_centpt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPt}); - histos.add("Reco/Primary/Efficiency/h3f_n1_centptrap_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisRap}); - histos.add("Reco/Primary/Efficiency/h3f_n1_centptrap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisRap}); + histos.add("Reco/Efficiency/h2f_n1_centpt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPtLambda}); + histos.add("Reco/Efficiency/h2f_n1_centpt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPtLambda}); + histos.add("Reco/Efficiency/h2f_n1_centpt_KaP", "#rho_{1}^{K^{#plus}}", kTH2F, {axisCent, axisPtKaon}); + histos.add("Reco/Efficiency/h2f_n1_centpt_KaM", "#rho_{1}^{K^{#minus}}", kTH2F, {axisCent, axisPtKaon}); + histos.add("Reco/Efficiency/h3f_n1_centptrap_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPtLambda, axisRap}); + histos.add("Reco/Efficiency/h3f_n1_centptrap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPtLambda, axisRap}); + histos.add("Reco/Efficiency/h3f_n1_centptrap_KaP", "#rho_{1}^{K^{#plus}}", kTH3F, {axisCent, axisPtKaon, axisRap}); + histos.add("Reco/Efficiency/h3f_n1_centptrap_KaM", "#rho_{1}^{K^{#minus}}", kTH3F, {axisCent, axisPtKaon, axisRap}); // Single and Two Particle Densities // 1D Histograms - histos.add("Reco/Primary/h3f_n1_centmasspt_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisMass, axisPt}); - histos.add("Reco/Primary/h3f_n1_centmasspt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisMass, axisPt}); - histos.add("Reco/Primary/h4f_n1_ptrapphi_LaP", "#rho_{1}^{#Lambda}", kTHnSparseF, {axisCent, axisPt, axisRap, axisPhi}); - histos.add("Reco/Primary/h4f_n1_ptrapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTHnSparseF, {axisCent, axisPt, axisRap, axisPhi}); + histos.add("Reco/h3f_n1_centmasspt_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisMass, axisPtLambda}); + histos.add("Reco/h3f_n1_centmasspt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisMass, axisPtLambda}); + histos.add("Reco/h4f_n1_ptrapphi_LaP", "#rho_{1}^{#Lambda}", kTHnSparseF, {axisCent, axisPtLambda, axisRap, axisPhi}); + histos.add("Reco/h4f_n1_ptrapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTHnSparseF, {axisCent, axisPtLambda, axisRap, axisPhi}); + histos.add("Reco/h4f_n1_ptrapphi_KaP", "#rho_{1}^{K^{#plus}}", kTHnSparseF, {axisCent, axisPtKaon, axisRap, axisPhi}); + histos.add("Reco/h4f_n1_ptrapphi_KaM", "#rho_{1}^{K^{#minus}}", kTHnSparseF, {axisCent, axisPtKaon, axisRap, axisPhi}); // rho1 for R2 RapPhi - histos.add("Reco/Primary/h3f_n1_rapphi_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisRap, axisPhi}); - histos.add("Reco/Primary/h3f_n1_rapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisPhi}); - - // rho1 for Q_{inv} - histos.add("Reco/Primary/h3f_n1_ptrapphi_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisRapPhi}); - histos.add("Reco/Primary/h3f_n1_ptrapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisRapPhi}); - - // Clone Singles Primary/Secondary Histogram - if (cAnaSecondaries) { - histos.addClone("Reco/Primary/", "Reco/Secondary/"); - } + histos.add("Reco/h3f_n1_rapphi_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisRap, axisPhi}); + histos.add("Reco/h3f_n1_rapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisPhi}); + histos.add("Reco/h3f_n1_rapphi_KaP", "#rho_{1}^{K^{#plus}}", kTH3F, {axisCent, axisRap, axisPhi}); + histos.add("Reco/h3f_n1_rapphi_KaM", "#rho_{1}^{K^{#minus}}", kTH3F, {axisCent, axisRap, axisPhi}); if (cAnaPairs) { - // rho2 for numerator of R2 - histos.add("Reco/PP/h3f_n2_raprap_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisRap}); - histos.add("Reco/PP/h3f_n2_raprap_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisRap, axisRap}); - histos.add("Reco/PP/h3f_n2_raprap_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisRap}); - histos.add("Reco/PP/h3f_n2_phiphi_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); - histos.add("Reco/PP/h3f_n2_phiphi_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisPhi, axisPhi}); - histos.add("Reco/PP/h3f_n2_phiphi_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); - // rho2 for R2 Rap1Phi1Rap2Phi2 - histos.add("Reco/PP/h3f_n2_rapphi_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); - histos.add("Reco/PP/h3f_n2_rapphi_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); - histos.add("Reco/PP/h3f_n2_rapphi_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); - - // rho2 for R2 Qinv - histos.add("Reco/PP/h3f_n2_qinv_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTHnSparseF, {axisCent, axisPt, axisRapPhi, axisQinv}); - histos.add("Reco/PP/h3f_n2_qinv_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTHnSparseF, {axisCent, axisPt, axisRapPhi, axisQinv}); - histos.add("Reco/PP/h3f_n2_qinv_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTHnSparseF, {axisCent, axisPt, axisRapPhi, axisQinv}); - - // Clone Pairs Histograms - if (cAnaSecondaryPairs) { - histos.addClone("Reco/PP/", "Reco/PS/"); - histos.addClone("Reco/PP/", "Reco/SP/"); - histos.addClone("Reco/PP/", "Reco/SS/"); - } + histos.add("Reco/h3f_n2_rapphi_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaP_KaM", "#rho_{2}^{#LambdaK^{#minus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaP_KaP", "#rho_{2}^{#LambdaK^{#plus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaM_KaM", "#rho_{2}^{#bar{#Lambda}K^{#plus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_LaM_KaP", "#rho_{2}^{#bar{#Lambda}K^{#minus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_KaP_KaM", "#rho_{2}^{#LambdaK^{#minus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_KaP_KaP", "#rho_{2}^{#LambdaK^{#plus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/h3f_n2_rapphi_KaM_KaM", "#rho_{2}^{#bar{#Lambda}K^{#plus}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); } // MCGen @@ -1678,49 +1450,34 @@ struct LambdaR2Correlation { return rapphibin; } - template - void fillPairHistos(U& p1, U& p2) + template + void fillPairHistos(T1& p1, T2& p2) { static constexpr std::string_view SubDirRecGen[] = {"Reco/", "McGen/"}; - static constexpr std::string_view SubDirPrmScd[] = {"PP/", "PS/", "SP/", "SS/"}; - static constexpr std::string_view SubDirHist[] = {"LaP_LaM", "LaP_LaP", "LaM_LaM"}; - - float rap1 = (cDoEtaAnalysis) ? p1.eta() : p1.rap(); - float rap2 = (cDoEtaAnalysis) ? p2.eta() : p2.rap(); + static constexpr std::string_view SubDirHist[] = {"LaP_LaM", "LaP_LaP", "LaM_LaM", "LaP_KaP", "LaP_KaM", "LaM_KaP", "LaM_KaM", "KaP_KaM", "KaP_KaP", "KaM_KaM"}; - int rapbin1 = static_cast((rap1 - kminrap) / rapbinwidth); - int rapbin2 = static_cast((rap2 - kminrap) / rapbinwidth); + int rapbin1 = static_cast((p1.rap() - kminrap) / rapbinwidth); + int rapbin2 = static_cast((p2.rap() - kminrap) / rapbinwidth); int phibin1 = static_cast(p1.phi() / phibinwidth); int phibin2 = static_cast(p2.phi() / phibinwidth); float corfac = p1.corrFact() * p2.corrFact(); - // fill rho2 histograms - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_raprap_") + HIST(SubDirHist[part_pair]), cent, rap1, rap2, corfac); - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_phiphi_") + HIST(SubDirHist[part_pair]), cent, p1.phi(), p2.phi(), corfac); - if (rapbin1 >= 0 && rapbin2 >= 0 && phibin1 >= 0 && phibin2 >= 0 && rapbin1 < nrapbins && rapbin2 < nrapbins && phibin1 < nphibins && phibin2 < nphibins) { int rapphix = rapbin1 * nphibins + phibin1; int rapphiy = rapbin2 * nphibins + phibin2; - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_rapphi_") + HIST(SubDirHist[part_pair]), cent, rapphix + 0.5, rapphiy + 0.5, corfac); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("h3f_n2_rapphi_") + HIST(SubDirHist[part_pair]), cent, rapphix + 0.5, rapphiy + 0.5, corfac); } - - // qinv histograms - q = RecoDecay::p((p1.px() - p2.px()), (p1.py() - p2.py()), (p1.pz() - p2.pz())); - e = RecoDecay::e(p1.px(), p1.py(), p1.pz(), MassLambda0) - RecoDecay::e(p2.px(), p2.py(), p2.pz(), MassLambda0); - qinv = std::sqrt(-RecoDecay::m2(q, e)); - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_qinv_") + HIST(SubDirHist[part_pair]), cent, p1.pt(), getRapPhiBin(p1.rap(), p1.phi()), qinv, corfac); } - template + template void analyzeSingles(T const& tracks) { static constexpr std::string_view SubDirRecGen[] = {"Reco/", "McGen/"}; - static constexpr std::string_view SubDirPrmScd[] = {"Primary/", "Secondary/"}; - static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; + static constexpr std::string_view SubDirHist[] = {"LaP", "LaM", "KaP", "KaM"}; int ntrk = 0; @@ -1729,58 +1486,58 @@ struct LambdaR2Correlation { ++ntrk; // Efficiency Plots - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("Efficiency/h2f_n1_centpt_") + HIST(SubDirHist[part]), cent, track.pt()); - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("Efficiency/h3f_n1_centptrap_") + HIST(SubDirHist[part]), cent, track.pt(), track.rap()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("Efficiency/h2f_n1_centpt_") + HIST(SubDirHist[part]), cent, track.pt()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("Efficiency/h3f_n1_centptrap_") + HIST(SubDirHist[part]), cent, track.pt(), track.rap()); // QA Plots - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_centmasspt_") + HIST(SubDirHist[part]), cent, track.mass(), track.pt()); - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h4f_n1_ptrapphi_") + HIST(SubDirHist[part]), cent, track.pt(), track.rap(), track.phi(), track.corrFact()); + if (part == kLambda || part == kAntiLambda) { + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("h3f_n1_centmasspt_") + HIST(SubDirHist[part]), cent, track.mass(), track.pt()); + } + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("h4f_n1_ptrapphi_") + HIST(SubDirHist[part]), cent, track.pt(), track.rap(), track.phi(), track.corrFact()); // Rho1 for N1RapPhi - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_rapphi_") + HIST(SubDirHist[part]), cent, track.rap(), track.phi(), track.corrFact()); - - // Rho1 for Q_{inv} - histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_ptrapphi_") + HIST(SubDirHist[part]), cent, track.pt(), getRapPhiBin(track.rap(), track.phi()), track.corrFact()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST("h3f_n1_rapphi_") + HIST(SubDirHist[part]), cent, track.rap(), track.phi(), track.corrFact()); } // fill multiplicity histograms if (ntrk != 0) { if (part == kLambda) { histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_lambda_mult"), cent, ntrk); - } else { + } else if (part == kAntiLambda) { histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_antilambda_mult"), cent, ntrk); } } } - template - void analyzePairs(T const& trks_1, T const& trks_2) + template + void analyzePairs(T1 const& trks_1, T2 const& trks_2) { for (auto const& trk_1 : trks_1) { for (auto const& trk_2 : trks_2) { // check for same index for Lambda-Lambda / AntiLambda-AntiLambda - if (samelambda && ((trk_1.index() == trk_2.index()))) { + if (same && ((trk_1.index() == trk_2.index()))) { continue; } - fillPairHistos(trk_1, trk_2); + fillPairHistos(trk_1, trk_2); } } } using LambdaCollisions = aod::LambdaCollisions; using LambdaTracks = soa::Join; + using KaonTracks = aod::KaonTracks; SliceCache cache; - Partition partPrimLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); - Partition partPrimAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); - Partition partSecdLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); - Partition partSecdAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + Partition partLambdaTracks = (aod::lambdatrack::partType == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true); + Partition partAntiLambdaTracks = (aod::lambdatrack::partType == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true); + Partition partKaonPlusTracks = (aod::kaontrack::partType == (int8_t)kKaonPlus); + Partition partKaonMinusTracks = (aod::kaontrack::partType == (int8_t)kKaonMinus); void processDummy(aod::LambdaCollisions::iterator const&) {} PROCESS_SWITCH(LambdaR2Correlation, processDummy, "Dummy Process", true); - void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) + void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&, KaonTracks const&) { histos.fill(HIST("Event/Reco/h1f_collision_posz"), collision.posZ()); histos.fill(HIST("Event/Reco/h1f_ft0m_mult_percentile"), collision.cent()); @@ -1788,37 +1545,28 @@ struct LambdaR2Correlation { cent = collision.cent(); - auto lambdaPrimTracks = partPrimLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); - auto antiLambdaPrimTracks = partPrimAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); - auto lambdaSecdTracks = partSecdLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); - auto antiLambdaSecdTracks = partSecdAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto lambdaTracks = partLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto antiLambdaTracks = partAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto kaonPlusTracks = partKaonPlusTracks->sliceByCached(aod::kaontrack::lambdaCollisionId, collision.globalIndex(), cache); + auto kaonMinusTracks = partKaonMinusTracks->sliceByCached(aod::kaontrack::lambdaCollisionId, collision.globalIndex(), cache); - analyzeSingles(lambdaPrimTracks); - analyzeSingles(antiLambdaPrimTracks); - - if (cAnaSecondaries) { - analyzeSingles(lambdaSecdTracks); - analyzeSingles(antiLambdaSecdTracks); - } + analyzeSingles(lambdaTracks); + analyzeSingles(antiLambdaTracks); + analyzeSingles(kaonPlusTracks); + analyzeSingles(kaonMinusTracks); if (cAnaPairs) { - // Primary Pairs Only - analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); - analyzePairs(lambdaPrimTracks, lambdaPrimTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); - - // Secondary Pairs - if (cAnaSecondaryPairs) { - analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaPrimTracks, lambdaSecdTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, lambdaPrimTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, lambdaSecdTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); - } + // Pairs Only + analyzePairs(lambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, lambdaTracks); + analyzePairs(antiLambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, kaonPlusTracks); + analyzePairs(lambdaTracks, kaonMinusTracks); + analyzePairs(antiLambdaTracks, kaonPlusTracks); + analyzePairs(antiLambdaTracks, kaonMinusTracks); + analyzePairs(kaonPlusTracks, kaonMinusTracks); + analyzePairs(kaonPlusTracks, kaonPlusTracks); + analyzePairs(kaonMinusTracks, kaonMinusTracks); } } @@ -1826,14 +1574,15 @@ struct LambdaR2Correlation { using LambdaMcGenCollisions = aod::LambdaMcGenCollisions; using LambdaMcGenTracks = aod::LambdaMcGenTracks; + using KaonMcGenTracks = aod::KaonMcGenTracks; SliceCache cachemc; - Partition partMcPrimLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); - Partition partMcPrimAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); - Partition partMcSecdLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); - Partition partMcSecdAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + Partition partMcLambdaTracks = (aod::lambdatrack::partType == (int8_t)kLambda); + Partition partMcAntiLambdaTracks = (aod::lambdatrack::partType == (int8_t)kAntiLambda); + Partition partMcKaonPlusTracks = (aod::kaontrack::partType == (int8_t)kKaonPlus); + Partition partMcKaonMinusTracks = (aod::kaontrack::partType == (int8_t)kKaonMinus); - void processMCGen(LambdaMcGenCollisions::iterator const& mcgencol, LambdaMcGenTracks const&) + void processMCGen(LambdaMcGenCollisions::iterator const& mcgencol, LambdaMcGenTracks const&, KaonMcGenTracks const&) { histos.fill(HIST("Event/McGen/h1f_collision_posz"), mcgencol.posZ()); histos.fill(HIST("Event/McGen/h1f_ft0m_mult_percentile"), mcgencol.cent()); @@ -1841,37 +1590,27 @@ struct LambdaR2Correlation { cent = mcgencol.cent(); - auto lambdaPrimTracks = partMcPrimLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); - auto antiLambdaPrimTracks = partMcPrimAntiLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); - auto lambdaSecdTracks = partMcSecdLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); - auto antiLambdaSecdTracks = partMcSecdAntiLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); - - analyzeSingles(lambdaPrimTracks); - analyzeSingles(antiLambdaPrimTracks); + auto lambdaTracks = partMcLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cache); + auto antiLambdaTracks = partMcAntiLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cache); + auto kaonPlusTracks = partMcKaonPlusTracks->sliceByCached(aod::kaonmcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cache); + auto kaonMinusTracks = partMcKaonMinusTracks->sliceByCached(aod::kaonmcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cache); - if (cAnaSecondaries) { - analyzeSingles(lambdaSecdTracks); - analyzeSingles(antiLambdaSecdTracks); - } + analyzeSingles(lambdaTracks); + analyzeSingles(antiLambdaTracks); + analyzeSingles(kaonPlusTracks); + analyzeSingles(kaonMinusTracks); if (cAnaPairs) { - // Primary Pairs Only - analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); - analyzePairs(lambdaPrimTracks, lambdaPrimTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); - - // Secondary Pairs - if (cAnaSecondaryPairs) { - analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaPrimTracks, lambdaSecdTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, lambdaPrimTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, lambdaSecdTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); - } + analyzePairs(lambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, lambdaTracks); + analyzePairs(antiLambdaTracks, antiLambdaTracks); + analyzePairs(lambdaTracks, kaonPlusTracks); + analyzePairs(lambdaTracks, kaonMinusTracks); + analyzePairs(antiLambdaTracks, kaonPlusTracks); + analyzePairs(antiLambdaTracks, kaonMinusTracks); + analyzePairs(kaonPlusTracks, kaonMinusTracks); + analyzePairs(kaonPlusTracks, kaonPlusTracks); + analyzePairs(kaonMinusTracks, kaonMinusTracks); } } From 8bc93941e5d4dd3231f181014f336907835e148b Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Sat, 9 May 2026 04:09:34 -0600 Subject: [PATCH 109/449] [PWGLF] Histograms for the p to pT conversion were added (#16172) Co-authored-by: Paola Vargas Torres --- PWGLF/Tasks/Nuspex/multiplicityPt.cxx | 138 +++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx index 6aaebebc9dd..28531bd0446 100644 --- a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -67,6 +67,7 @@ struct MultiplicityPt { static constexpr int CentBinMax = 100; static constexpr int MultBinMax = 200; static constexpr int RecMultBinMax = 100; + static constexpr int ParticlesType = 4; enum INELCutSelection : int { INEL = 0, @@ -111,6 +112,16 @@ struct MultiplicityPt { Configurable cfgCutNsigmaPi{"cfgCutNsigmaPi", 3.0f, "nsigma cut for pions"}; Configurable cfgCutNsigmaKa{"cfgCutNsigmaKa", 2.5f, "nsigma cut for kaons"}; Configurable cfgCutNsigmaPr{"cfgCutNsigmaPr", 2.5f, "nsigma cut for protons"}; + // Histogram names for V0s dE/dx analysis + static constexpr std::string_view DedxvsMomentumPos[ParticlesType] = {"dEdx_vs_Momentum_all_Pos", "dEdx_vs_Momentum_Pi_v0_Pos", "dEdx_vs_Momentum_Pr_v0_Pos", "dEdx_vs_Momentum_El_v0_Pos"}; + static constexpr std::string_view DedxvsMomentumNeg[ParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; + // Particle fractions histograms + static constexpr std::string_view ParticleFractionsVsMomentumPos[ParticlesType + 1] = {"hFractionVsMomentum_Pion_Pos", "hFractionVsMomentum_Kaon_Pos", "hFractionVsMomentum_Proton_Pos", "hFractionVsMomentum_Electron_Pos", "hFractionVsMomentum_Muon_Pos"}; + + static constexpr std::string_view ParticleFractionsVsPtPos[ParticlesType + 1] = {"hFractionVsPt_Pion_Pos", "hFractionVsPt_Kaon_Pos", "hFractionVsPt_Proton_Pos", "hFractionVsPt_Electron_Pos", "hFractionVsPt_Muon_Pos"}; + static constexpr std::string_view ParticleFractionsVsMomentumNeg[ParticlesType + 1] = {"hFractionVsMomentum_Pion_Neg", "hFractionVsMomentum_Kaon_Neg", "hFractionVsMomentum_Proton_Neg", "hFractionVsMomentum_Electron_Neg", "hFractionVsMomentum_Muon_Neg"}; + + static constexpr std::string_view ParticleFractionsVsPtNeg[ParticlesType + 1] = {"hFractionVsPt_Pion_Neg", "hFractionVsPt_Kaon_Neg", "hFractionVsPt_Proton_Neg", "hFractionVsPt_Electron_Neg", "hFractionVsPt_Muon_Neg"}; TrackSelection customTrackCuts; TF1* fphiCutLow = nullptr; @@ -346,6 +357,9 @@ void MultiplicityPt::init(InitContext const&) // Axis definitions ConfigurableAxis ptBinning{"ptBinning", {VARIABLE_WIDTH, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, "pT bin limits"}; AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec dedxAxis{100, 0.0, 100.0, "dE/dx (a. u.)"}; + AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; + AxisSpec pAxis = {ptBinning, "#it{p} (GeV/#it{c})"}; std::vector centBinningStd = {0., 1., 5., 10., 15., 20., 30., 40., 50., 60., 70., 80., 90., 100.}; AxisSpec centAxis = {centBinningStd, "FT0M Centrality (%)"}; @@ -450,12 +464,48 @@ void MultiplicityPt::init(InitContext const&) ue.add("hEventsReco_Cent", "Reconstructed events vs centrality;FT0M Centrality (%);Counts", HistType::kTH1D, {centAxis}); ue.add("hEventsINEL_Cent", "INEL>0 events vs centrality;FT0M Centrality (%);Counts", HistType::kTH1D, {centAxis}); - ue.add("hNclFoundTPC", "Number of TPC found clusters", HistType::kTH1D, {{200, 0, 200}}); - ue.add("hNclPIDTPC", "Number of TPC PID clusters", HistType::kTH1D, {{200, 0, 200}}); + ue.add("hNclFoundTPCBefore", "Number of TPC found clusters before tkr cuts", HistType::kTH1D, {{200, 0, 200}}); + ue.add("hNclPIDTPCBefore", "Number of TPC PID clusters before tkr cuts", HistType::kTH1D, {{200, 0, 200}}); + ue.add("hNclFoundTPCAfter", "Number of TPC found after tkr cuts", HistType::kTH1D, {{200, 0, 200}}); + ue.add("hNclPIDTPCAfter", "Number of TPC PID after tkr cuts", HistType::kTH1D, {{200, 0, 200}}); ue.add("hEta", "Track eta;#eta;Counts", HistType::kTH1D, {{20, -0.8, 0.8}}); ue.add("hPhi", "Track phi;#varphi (rad);Counts", HistType::kTH1D, {{64, 0, TwoPI}}); ue.add("hvtxZ", "Vertex Z (data);Vertex Z (cm);Events", HistType::kTH1F, {{40, -20.0, 20.0}}); + // De/Dx for ch and v0 particles + for (int i = 0; i < ParticlesType; ++i) { + ue.add(("DedxVsMomentum/" + std::string(DedxvsMomentumPos[i])).c_str(), + "dE/dx vs Momentum Positive", HistType::kTH3F, + {{pAxis}, {dedxAxis}, {etaAxis}}); + ue.add(("DedxVsMomentum/" + std::string(DedxvsMomentumNeg[i])).c_str(), + "dE/dx vs Momentum Negative", HistType::kTH3F, + {{pAxis}, {dedxAxis}, {etaAxis}}); + } + + // ===== Particle Fractions as function of p and pT ===== + ue.add("ParticleFractions/hTotalCountsVsMomentumPos", "Total counts vs momentum;#it{p} (GeV/#it{c});Counts", HistType::kTH2D, {{etaAxis}, {pAxis}}); + ue.add("ParticleFractions/hTotalCountsVsPtPos", "Total counts vs pT;#it{p}_{T} (GeV/#it{c});Counts", HistType::kTH2D, {{etaAxis}, {ptAxis}}); + ue.add("ParticleFractions/hTotalCountsVsMomentumNeg", "Total counts vs momentum;#it{p} (GeV/#it{c});Counts", HistType::kTH2D, {{etaAxis}, {pAxis}}); + ue.add("ParticleFractions/hTotalCountsVsPtNeg", "Total counts vs pT;#it{p}_{T} (GeV/#it{c});Counts", HistType::kTH2D, {{etaAxis}, {ptAxis}}); + + for (int i = 0; i < ParticlesType + 1; ++i) { + ue.add(("ParticleFractions/" + std::string(ParticleFractionsVsMomentumPos[i])).c_str(), + "Particle fraction vs momentum", HistType::kTH2D, {{etaAxis}, {pAxis}}); + ue.add(("ParticleFractions/" + std::string(ParticleFractionsVsPtPos[i])).c_str(), + "Particle fraction vs pT", HistType::kTH2D, {{etaAxis}, {ptAxis}}); + ue.add(("ParticleFractions/" + std::string(ParticleFractionsVsMomentumNeg[i])).c_str(), + "Particle fraction vs momentum", HistType::kTH2D, {{etaAxis}, {pAxis}}); + ue.add(("ParticleFractions/" + std::string(ParticleFractionsVsPtNeg[i])).c_str(), + "Particle fraction vs pT", HistType::kTH2D, {{etaAxis}, {ptAxis}}); + } + // pt vs p + ue.add( + "heta_vs_pt_vs_p_all_Neg", "eta_vs_pT_vs_p", HistType::kTH3F, + {{etaAxis}, {ptAxis}, {pAxis}}); + ue.add( + "heta_vs_pt_vs_p_all_Pos", "eta_vs_pT_vs_p", HistType::kTH3F, + {{etaAxis}, {ptAxis}, {pAxis}}); + LOG(info) << "=== Initialization complete ==="; } @@ -679,27 +729,67 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, continue; if (track.collisionId() != collId) continue; + // Ncl distribution before cuts + ue.fill(HIST("hNclFoundTPCBefore"), track.tpcNClsFound()); + ue.fill(HIST("hNclPIDTPCBefore"), track.tpcNClsPID()); if (!passesTrackSelection(track, magField)) continue; nTracksInEvent++; - - ue.fill(HIST("hNclFoundTPC"), track.tpcNClsFound()); - ue.fill(HIST("hNclPIDTPC"), track.tpcNClsPID()); + // Ncl distribution before cuts + ue.fill(HIST("hNclFoundTPCAfter"), track.tpcNClsFound()); + ue.fill(HIST("hNclPIDTPCAfter"), track.tpcNClsPID()); ue.fill(HIST("hEta"), track.eta()); ue.fill(HIST("hPhi"), track.phi()); ue.fill(HIST("Inclusive/hPtReco"), track.pt()); + // ===== dE/dx and momentum for V0 cross-check histograms ===== + float tpcSignal = track.tpcSignal(); + float momentum = track.p(); // momentum total + float eta = track.eta(); + int charge = track.sign(); + + // dedx for all particles + if (charge > 0) { + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_all_Pos"), momentum, tpcSignal, eta); + ue.fill(HIST("heta_vs_pt_vs_p_all_Pos"), eta, track.pt(), momentum); + } else { + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_all_Neg"), momentum, tpcSignal, eta); + ue.fill(HIST("heta_vs_pt_vs_p_all_Neg"), eta, track.pt(), momentum); + } + if (track.has_mcParticle()) { const auto& particle = track.mcParticle(); int pdgCode = std::abs(particle.pdgCode()); + if (pdgCode == PDG_t::kPiPlus || pdgCode == PDG_t::kKPlus || pdgCode == PDG_t::kProton || pdgCode == PDG_t::kElectron || pdgCode == PDG_t::kMuonPlus) { + if (particle.isPhysicalPrimary()) { + // Fill total counts for fractions + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hTotalCountsVsMomentumPos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hTotalCountsVsPtPos"), eta, track.pt()); + } else { + ue.fill(HIST("ParticleFractions/hTotalCountsVsMomentumNeg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hTotalCountsVsPtNeg"), eta, track.pt()); + } + } + } if (pdgCode == PDG_t::kPiPlus) { ue.fill(HIST("Pion/hPtReco"), track.pt()); if (particle.isPhysicalPrimary()) { ue.fill(HIST("Pion/hPtPrimReco"), track.pt()); ue.fill(HIST("Inclusive/hPtPrimReco"), track.pt()); + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Pion_Pos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Pion_Pos"), eta, track.pt()); + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pi_v0_Pos"), momentum, tpcSignal, eta); + } else { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Pion_Neg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Pion_Neg"), eta, track.pt()); + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pi_v0_Neg"), momentum, tpcSignal, eta); + } + } else { ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); } @@ -708,6 +798,13 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, if (particle.isPhysicalPrimary()) { ue.fill(HIST("Kaon/hPtPrimReco"), track.pt()); ue.fill(HIST("Inclusive/hPtPrimReco"), track.pt()); + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Kaon_Pos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Kaon_Pos"), eta, track.pt()); + } else { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Kaon_Neg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Kaon_Neg"), eta, track.pt()); + } } else { ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); } @@ -716,9 +813,40 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, if (particle.isPhysicalPrimary()) { ue.fill(HIST("Proton/hPtPrimReco"), track.pt()); ue.fill(HIST("Inclusive/hPtPrimReco"), track.pt()); + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Proton_Pos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Proton_Pos"), eta, track.pt()); + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pr_v0_Pos"), momentum, tpcSignal, eta); + } else { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Proton_Neg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Proton_Neg"), eta, track.pt()); + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pr_v0_Neg"), momentum, tpcSignal, eta); + } } else { ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); } + } else if (pdgCode == PDG_t::kElectron) { + if (particle.isPhysicalPrimary()) { + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Electron_Pos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Electron_Pos"), eta, track.pt()); + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_El_v0_Pos"), momentum, tpcSignal, eta); + } else { + ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_El_v0_Neg"), momentum, tpcSignal, eta); + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Electron_Neg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Electron_Neg"), eta, track.pt()); + } + } + } else if (pdgCode == PDG_t::kMuonPlus) { + if (particle.isPhysicalPrimary()) { + if (charge > 0) { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Muon_Pos"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Muon_Pos"), eta, track.pt()); + } else { + ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Muon_Neg"), eta, momentum); + ue.fill(HIST("ParticleFractions/hFractionVsPt_Muon_Neg"), eta, track.pt()); + } + } } } From c127d674d0943bf92e87f69a746fde9575ecb4df Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Sat, 9 May 2026 19:47:13 +0800 Subject: [PATCH 110/449] [PWGCF] Add PID NUA (#16174) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 200 ++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 64 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index 69cf73a8a16..ef05ac8adbe 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -401,6 +401,12 @@ struct PidFlowPtCorr { // Add some output objects to the histogram registry registry.add("hPhi", "", {HistType::kTH1D, {cfgaxisPhi}}); registry.add("hPhicorr", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhiPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhicorrPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhiKa", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhicorrKa", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhiPr", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("hPhicorrPr", "", {HistType::kTH1D, {cfgaxisPhi}}); registry.add("hEta", "", {HistType::kTH1D, {cfgaxisEta}}); registry.add("hVtxZ", "", {HistType::kTH1D, {cfgaxisVertex}}); registry.add("hMult", "", {HistType::kTH1D, {cfgaxisNch}}); @@ -483,9 +489,16 @@ struct PidFlowPtCorr { if (switchsOpts.cfgOutputrunbyrun.value) { // hist for NUA registry.add("correction/hRunNumberPhiEtaVertex", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); + registry.add("correction/hRunNumberPhiEtaVertexPion", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); + registry.add("correction/hRunNumberPhiEtaVertexKaon", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); + registry.add("correction/hRunNumberPhiEtaVertexProton", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); + // set "correction/hRunNumberPhiEtaVertex" axis0 label for (uint64_t idx = 1; idx <= runNumbers.size(); idx++) { registry.get(HIST("correction/hRunNumberPhiEtaVertex"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); + registry.get(HIST("correction/hRunNumberPhiEtaVertexPion"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); + registry.get(HIST("correction/hRunNumberPhiEtaVertexKaon"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); + registry.get(HIST("correction/hRunNumberPhiEtaVertexProton"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); } // end set "correction/hRunNumberPhiEtaVertex" axis0 label } // cfgooutputrunbyrun @@ -957,6 +970,39 @@ struct PidFlowPtCorr { } } + /** + * @brief Get the Pid, combine square cut && circle cut + * + * @tparam TrackObject + * @param track + * @return MyParticleType + */ + template + int getPidConfigurable(TrackObject const& track) + { + int pid = -1; + if (circleCutOpts.cfgUseCircleCutPID.value) { + // Use circular cut (already handles ambiguity rejection) + pid = getPidWithCircleCut(track); + } else { + // Use normal cut (with manual ambiguity rejection) + bool isPi = isPion(track); + bool isKa = isKaon(track); + bool isPr = isProton(track); + int nCandidates = isPi + isKa + isPr; + if (nCandidates == 1) { + if (isPi) + pid = MyParticleType::kPion; + else if (isKa) + pid = MyParticleType::kKaon; + else if (isPr) + pid = MyParticleType::kProton; + } + // else: pid remains -1 (ambiguous or none) + } + return pid; + } + // pid util function // other utils @@ -1294,6 +1340,11 @@ struct PidFlowPtCorr { if (correctionsLoaded) return; int nspecies = 1; + int totalSpecies = 4; + /// @note if put 4 path in cfg then load charged, pi, ka, pr + // else only load charegd + // if path size != 1 or 4, nothing will be loaded + // load NUA if (cfgAcceptance.size() == static_cast(nspecies)) { for (int i = 0; i <= nspecies - 1; i++) { @@ -1304,6 +1355,17 @@ struct PidFlowPtCorr { else LOGF(warning, "Could not load acceptance weights"); } + + if (cfgAcceptance.size() == static_cast(totalSpecies)) { + for (int i = 0; i <= totalSpecies - 1; i++) { + mAcceptance.push_back(ccdb->getForTimeStamp(cfgAcceptance[i], timestamp)); + } + if (mAcceptance.size() == static_cast(totalSpecies)) + LOGF(info, "Loaded acceptance weights * 4"); + else + LOGF(warning, "Could not load acceptance weights * 4"); + } + // end load NUA /// @note dont modify load NUA!, just modify NUE @@ -1420,16 +1482,54 @@ struct PidFlowPtCorr { correctionsLoaded = true; } + /** + * @brief Set the Particle NUA, note that it works only when macceptance size >= 1, + * macceptance size can only be 1 or 4 + * + * @tparam TrackObject + * @param weight_nua + * @param track + * @param vtxz + * @return true + * @return false + */ template bool setParticleNUAWeight(float& weight_nua, TrackObject& track, float vtxz) { - if (mAcceptance.size() == static_cast(1)) + if (mAcceptance.size() == static_cast(1) || mAcceptance.size() == static_cast(4)) weight_nua = mAcceptance[0]->getNUA(track.phi(), track.eta(), vtxz); else weight_nua = 1; return true; } + template + bool setParticleNUAWeight(float& weight_nua, TrackObject& track, float vtxz, int pid) + { + if (mAcceptance.size() == static_cast(4)) { + + switch (pid) { + case MyParticleType::kPion: + weight_nua = mAcceptance[1]->getNUA(track.phi(), track.eta(), vtxz); + break; + case MyParticleType::kKaon: + weight_nua = mAcceptance[2]->getNUA(track.phi(), track.eta(), vtxz); + break; + case MyParticleType::kProton: + weight_nua = mAcceptance[3]->getNUA(track.phi(), track.eta(), vtxz); + break; + + default: + weight_nua = 1; + break; + } + + } else { + weight_nua = 1; + } + return true; + } + /** * @brief Set the Particle Nue Weight, for global track and ITS track, use different eff path * @@ -1932,26 +2032,7 @@ struct PidFlowPtCorr { // ------------------------------ // Unified PID logic (configurable) // ------------------------------ - int pid = -1; - if (circleCutOpts.cfgUseCircleCutPID.value) { - // Use circular cut (already handles ambiguity rejection) - pid = getPidWithCircleCut(track); - } else { - // Use normal cut (with manual ambiguity rejection) - bool isPi = isPion(track); - bool isKa = isKaon(track); - bool isPr = isProton(track); - int nCandidates = isPi + isKa + isPr; - if (nCandidates == 1) { - if (isPi) - pid = MyParticleType::kPion; - else if (isKa) - pid = MyParticleType::kKaon; - else if (isPr) - pid = MyParticleType::kProton; - } - // else: pid remains -1 (ambiguous or none) - } + int pid = getPidConfigurable(track); // Fill PID variables based on unified result if (pid == MyParticleType::kPion) { @@ -2065,39 +2146,31 @@ struct PidFlowPtCorr { // ------------------------------ // Unified PID logic (configurable) // ------------------------------ - int pid = -1; - if (circleCutOpts.cfgUseCircleCutPID.value) { - // Use circular cut (already handles ambiguity rejection) - pid = getPidWithCircleCut(track); - } else { - // Use normal cut (with manual ambiguity rejection) - bool isPi = isPion(track); - bool isKa = isKaon(track); - bool isPr = isProton(track); - int nCandidates = isPi + isKa + isPr; - if (nCandidates == 1) { - if (isPi) - pid = MyParticleType::kPion; - else if (isKa) - pid = MyParticleType::kKaon; - else if (isPr) - pid = MyParticleType::kProton; - } - // else: pid remains -1 (ambiguous or none) - } + int pid = getPidConfigurable(track); + float waccPid = 1; + this->setParticleNUAWeight(waccPid, track, vtxz, pid); // Fill GFW and counters based on unified result if (pid == MyParticleType::kPion) { // bitmask 18: 0010010 - fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 18); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 2); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 16, wacc * weff); + registry.fill(HIST("hPhiPi"), track.phi()); + registry.fill(HIST("hPhicorrPi"), track.phi(), waccPid); numOfPi++; } else if (pid == MyParticleType::kKaon) { // bitmask 36: 0100100 - fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 36); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 4); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 32, wacc * weff); + registry.fill(HIST("hPhiKa"), track.phi()); + registry.fill(HIST("hPhicorrKa"), track.phi(), waccPid); numOfKa++; } else if (pid == MyParticleType::kProton) { // bitmask 72: 1001000 - fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 72); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 8); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 64, wacc * weff); + registry.fill(HIST("hPhiPr"), track.phi()); + registry.fill(HIST("hPhicorrPr"), track.phi(), waccPid); numOfPr++; } // else: do nothing (ambiguous or not identified) @@ -2369,6 +2442,24 @@ struct PidFlowPtCorr { // fill the THn registry.fill(HIST("correction/hRunNumberPhiEtaVertex"), matchedPosition, track.phi(), track.eta(), collision.posZ()); + + int pid = this->getPidConfigurable(track); + switch (pid) { + case MyParticleType::kPion: + registry.fill(HIST("correction/hRunNumberPhiEtaVertexPion"), matchedPosition, track.phi(), track.eta(), collision.posZ()); + break; + + case MyParticleType::kKaon: + registry.fill(HIST("correction/hRunNumberPhiEtaVertexKaon"), matchedPosition, track.phi(), track.eta(), collision.posZ()); + break; + + case MyParticleType::kProton: + registry.fill(HIST("correction/hRunNumberPhiEtaVertexProton"), matchedPosition, track.phi(), track.eta(), collision.posZ()); + break; + + default: + break; + } // end fill the THn } // end loop all the track @@ -2521,26 +2612,7 @@ struct PidFlowPtCorr { // ------------------------------ // Unified PID logic (configurable) // ------------------------------ - int pid = -1; - if (circleCutOpts.cfgUseCircleCutPID.value) { - // Use circular cut (already handles ambiguity rejection) - pid = getPidWithCircleCut(track); - } else { - // Use normal cut (with manual ambiguity rejection) - bool isPi = isPion(track); - bool isKa = isKaon(track); - bool isPr = isProton(track); - int nCandidates = isPi + isKa + isPr; - if (nCandidates == 1) { - if (isPi) - pid = MyParticleType::kPion; - else if (isKa) - pid = MyParticleType::kKaon; - else if (isPr) - pid = MyParticleType::kProton; - } - // else: pid remains -1 (ambiguous or none) - } + int pid = getPidConfigurable(track); // Fill MC reco histograms based on unified result if (pid == MyParticleType::kPion) { From b7c97b0b18d97458898c0f895a0d66de68530ebb Mon Sep 17 00:00:00 2001 From: Antonio Palasciano <52152842+apalasciano@users.noreply.github.com> Date: Sat, 9 May 2026 18:57:08 +0200 Subject: [PATCH 111/449] [PWGHF] Extending derived data for D+-h correl (#16176) --- .../DataModel/DerivedDataCorrelationTables.h | 8 +-- .../TableProducer/correlatorDplusHadrons.cxx | 52 ++++++++++++++++++- .../HFC/TableProducer/correlatorDsHadrons.cxx | 4 +- .../correlatorDsHadronsReduced.cxx | 14 ++--- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h index 8f8dbecf390..fb74da7a260 100644 --- a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h +++ b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h @@ -53,22 +53,22 @@ DECLARE_SOA_COLUMN(Prong2Id, prong2Id, int); //! Prong2 index DECLARE_SOA_COLUMN(PhiCand, phiCand, float); //! Phi of the candidate DECLARE_SOA_COLUMN(EtaCand, etaCand, float); //! Eta of the candidate DECLARE_SOA_COLUMN(PtCand, ptCand, float); //! Pt of the candidate -DECLARE_SOA_COLUMN(InvMassDs, invMassDs, float); //! Invariant mass of Ds candidate +DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass of charm candidate DECLARE_SOA_COLUMN(BdtScorePrompt, bdtScorePrompt, float); //! BDT output score for prompt hypothesis DECLARE_SOA_COLUMN(BdtScoreBkg, bdtScoreBkg, float); //! BDT output score for background hypothesis } // namespace hf_candidate_reduced -DECLARE_SOA_TABLE(DsCandReduceds, "AOD", "DSCANDREDUCED", //! Table with Ds candidate info +DECLARE_SOA_TABLE(HcCandReduceds, "AOD", "HCCANDREDUCED", //! Table with charm hadron candidate info soa::Index<>, aod::hf_candidate_reduced::HfcRedCollisionId, aod::hf_candidate_reduced::PhiCand, aod::hf_candidate_reduced::EtaCand, aod::hf_candidate_reduced::PtCand, - aod::hf_candidate_reduced::InvMassDs, + aod::hf_candidate_reduced::InvMass, aod::hf_candidate_reduced::Prong0Id, aod::hf_candidate_reduced::Prong1Id, aod::hf_candidate_reduced::Prong2Id); -DECLARE_SOA_TABLE(DsCandSelInfos, "AOD", "DSCANDSELINFO", //! Table with Ds candidate selection info +DECLARE_SOA_TABLE(HcCandSelInfos, "AOD", "HCCANDSELINFO", //! Table with charm hadron candidate selection info soa::Index<>, aod::hf_candidate_reduced::HfcRedCollisionId, aod::hf_candidate_reduced::BdtScorePrompt, diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index 3f7f48f84d3..44cd05527b7 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -21,6 +21,7 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.h" #include "Common/CCDB/EventSelectionParams.h" @@ -181,6 +182,12 @@ struct HfCorrelatorDplusHadrons { Produces entryTrackRecoInfo; Produces entryDplus; Produces entryHadron; + Produces collReduced; + Produces candReduced; + Produces candSelInfo; + Produces assocTrackReduced; + Produces assocTrackSelInfo; + static constexpr std::size_t NDaughters{3u}; static constexpr float EtaDaughtersMax = 0.8f; // Eta cut on daughters of D+ meson as Run2 @@ -231,10 +238,13 @@ struct HfCorrelatorDplusHadrons { // filter on selection of Dplus meson and decay channel Dplus->KPiPi Filter dplusFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) != static_cast(0)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + // Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); Preslice presliceMc{aod::mcparticle::mcCollisionId}; Preslice candMcGenPerMcCollision = o2::aod::mcparticle::mcCollisionId; + Preslice candsDplusPerCollision = aod::hf_cand::collisionId; + Preslice trackIndicesPerCollision = aod::track::collisionId; PresliceUnsorted> recoCollisionsPerMcCollision = o2::aod::mccollisionlabel::mcCollisionId; - // Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); + ConfigurableAxis binsMultiplicity{"binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 100000.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; ConfigurableAxis binsMultiplicityMc{"binsMultiplicityMc", {VARIABLE_WIDTH, 0.0f, 20.0f, 50.0f, 500.0f}, "Mixing bins - MC multiplicity"}; // In MCGen multiplicity is defined by counting tracks @@ -528,6 +538,46 @@ struct HfCorrelatorDplusHadrons { } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processData, "Process data", false); + void processDerivedDataDplus(SelCollisionsWithDplus const& collisions, + CandidatesDplusData const& candidates, + TracksData const& tracks) + { + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDplusThisColl = candidates.sliceBy(candsDplusPerCollision, thisCollId); + auto tracksThisColl = tracks.sliceBy(trackIndicesPerCollision, thisCollId); + + int indexHfcReducedCollision = collReduced.lastIndex() + 1; + + // Ds fill histograms and Dplus candidates information stored + for (const auto& candidate : candsDplusThisColl) { + std::vector outputMl = {-1., -1., -1.}; + // candidate selected + if (candidate.isSelDplusToPiKPi() >= selectionFlagDplus) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; + } + candReduced(indexHfcReducedCollision, candidate.phi(), candidate.eta(), candidate.pt(), HfHelper::invMassDplusToPiKPi(candidate), candidate.prong0Id(), candidate.prong1Id(), candidate.prong2Id()); + candSelInfo(indexHfcReducedCollision, outputMl[0], outputMl[2]); + } + } + + // tracks information + for (const auto& track : tracksThisColl) { + if (!track.isGlobalTrackWoDCA()) { + continue; + } + registry.fill(HIST("hDcaXYVsPt"), track.dcaXY(), track.pt()); + assocTrackReduced(indexHfcReducedCollision, track.globalIndex(), track.phi(), track.eta(), track.pt()); + assocTrackSelInfo(indexHfcReducedCollision, track.tpcNClsCrossedRows(), track.itsClusterMap(), track.itsNCls(), track.dcaXY(), track.dcaZ()); + } + + collReduced(collision.multFT0M(), collision.numContrib(), collision.posZ()); + } + } + PROCESS_SWITCH(HfCorrelatorDplusHadrons, processDerivedDataDplus, "Process derived data D+", false); + /// Dplus-Hadron correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) void processMcRec(SelCollisionsWithDplus::iterator const& collision, TracksWithMc const& tracks, diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index e2b85b70fc0..e9461ab0b94 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -173,8 +173,8 @@ struct HfCorrelatorDsHadrons { Produces entryDsCandGenInfo; Produces entryTrackRecoInfo; Produces collReduced; - Produces candReduced; - Produces candSelInfo; + Produces candReduced; + Produces candSelInfo; Produces assocTrackReduced; Produces assocTrackSelInfo; Produces assocTrackPidInfo; diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx index f7aa4fbc31b..4da399567b5 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx @@ -69,7 +69,7 @@ struct HfCorrelatorDsHadronsReduced { // Preslice tracksPerCol = aod::hf_assoc_track_reduced::hfcRedCollisionId; Preslice tracksPerCol = aod::hf_candidate_reduced::hfcRedCollisionId; - Preslice candPerCol = aod::hf_candidate_reduced::hfcRedCollisionId; + Preslice candPerCol = aod::hf_candidate_reduced::hfcRedCollisionId; ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}, "z vertex position pools"}; ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 900., 1800., 6000.}, "event multiplicity pools (FT0M)"}; @@ -106,7 +106,7 @@ struct HfCorrelatorDsHadronsReduced { } void processDerivedData(aod::HfcRedCollisions const& collisions, - soa::Join const& candidates, + soa::Join const& candidates, soa::Join const& tracks) { @@ -126,7 +126,7 @@ struct HfCorrelatorDsHadronsReduced { registry.fill(HIST("hDsPoolBin"), poolBin); registry.fill(HIST("hPhiVsPtCand"), RecoDecay::constrainAngle(candidate.phiCand(), -PIHalf), candidate.ptCand()); registry.fill(HIST("hEtaVsPtCand"), candidate.etaCand(), candidate.ptCand()); - entryDsCandRecoInfo(candidate.invMassDs(), candidate.ptCand(), candidate.bdtScorePrompt(), candidate.bdtScoreBkg(), collision.numPvContrib()); + entryDsCandRecoInfo(candidate.invMass(), candidate.ptCand(), candidate.bdtScorePrompt(), candidate.bdtScoreBkg(), collision.numPvContrib()); for (const auto& track : tracksThisColl) { // Removing Ds daughters by checking track indices if ((candidate.prong0Id() == track.originTrackId()) || (candidate.prong1Id() == track.originTrackId()) || (candidate.prong2Id() == track.originTrackId())) { @@ -142,7 +142,7 @@ struct HfCorrelatorDsHadronsReduced { track.ptAssocTrack(), poolBin, collision.numPvContrib()); - entryDsHadronRecoInfo(candidate.invMassDs(), false, false); + entryDsHadronRecoInfo(candidate.invMass(), false, false); entryDsHadronMlInfo(candidate.bdtScorePrompt(), candidate.bdtScoreBkg()); entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.nTpcCrossedRows()); } @@ -152,7 +152,7 @@ struct HfCorrelatorDsHadronsReduced { PROCESS_SWITCH(HfCorrelatorDsHadronsReduced, processDerivedData, "Process Derived Data", true); void processDerivedDataME(aod::HfcRedCollisions const& collisions, - aod::DsCandReduceds const& candidates, + aod::HcCandReduceds const& candidates, aod::AssocTrackReds const& tracks) { @@ -182,7 +182,7 @@ struct HfCorrelatorDsHadronsReduced { auto tracksTuple = std::make_tuple(candidates, tracks); - Pair const pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair const pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairData) { if (tracks1.size() == 0) { @@ -205,7 +205,7 @@ struct HfCorrelatorDsHadronsReduced { pAssoc.ptAssocTrack(), poolBin, c1.numPvContrib()); - entryDsHadronRecoInfo(cand.invMassDs(), false, false); + entryDsHadronRecoInfo(cand.invMass(), false, false); // entryDsHadronGenInfo(false, false, 0); } } From 87a3d56778172ec682343b74c7d43bdd4a8caf2b Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Sat, 9 May 2026 22:10:28 +0200 Subject: [PATCH 112/449] [PWGCF] FemtoUniverse: Add process functions to check mothers of single tracks and V0s (#16177) --- .../femtoUniversePairTaskTrackV0Extended.cxx | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 57f8f414e16..9bb5265f6be 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -402,6 +402,21 @@ struct FemtoUniversePairTaskTrackV0Extended { registryMCreco.add("mothersReco/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); registryMCreco.add("mothersReco/motherParticlePDGCheck", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); } + + if (doprocessFractionsSingleReco) { + registryMCreco.add("mothersReco/motherParticleTrack", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + registryMCreco.add("mothersReco/motherParticleTrackPDGCheck", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + registryMCreco.add("mothersReco/motherParticleV0", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + registryMCreco.add("mothersReco/motherParticleV0PDGCheck", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + } + + if (doprocessFractionsSingleTruth) { + registryMCtruth.add("mothersTruth/motherParticleTrack", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + registryMCtruth.add("mothersTruth/mcProcessTrack", " ; VMC physics code", {HistType::kTH1F, {{50, 0, 50}}}); + registryMCtruth.add("mothersTruth/motherParticleV0", "; mother PDG", {HistType::kTH1F, {confMotherPDGBins}}); + registryMCtruth.add("mothersTruth/mcProcessV0", " ; VMC physics code", {HistType::kTH1F, {{50, 0, 50}}}); + } + sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventCont.setPDGCodes(ConfTrkSelection.confTrkPDGCodePartOne, ConfV0Selection.confV0PDGCodePartTwo); mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); @@ -1623,6 +1638,80 @@ struct FemtoUniversePairTaskTrackV0Extended { } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processPairFractionsMCTruthV0, "Process MC data to obtain pair fractions for V0V0 MC truth pairs", false); + void processFractionsSingleReco(FilteredFDCollision const& col, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + auto groupPartsOne = partsOneMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + + for (const auto& part : groupPartsTwo) { + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type1)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } + + if (!isParticleTPC(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) + continue; + + if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) + continue; + + registryMCreco.fill(HIST("mothersReco/motherParticleV0"), part.motherPDG()); + auto mcPartId1 = part.fdMCParticleId(); + if (mcPartId1 == -1) + continue; + const auto& mcParticle1 = mcparts.iteratorAt(mcPartId1); + if ((ConfV0Selection.confV0Type1 == 0 && mcParticle1.pdgMCTruth() != kLambda0) || (ConfV0Selection.confV0Type1 == 1 && mcParticle1.pdgMCTruth() != kLambda0Bar)) + continue; + registryMCreco.fill(HIST("mothersReco/motherParticleV0PDGCheck"), part.motherPDG()); + } + + for (const auto& part : groupPartsOne) { + const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; + const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; + + if (!isNSigmaCombined(part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne], tofNSigmas[ConfTrkSelection.confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) + continue; + registryMCreco.fill(HIST("mothersReco/motherParticleTrack"), part.motherPDG()); + auto mcPartId1 = part.fdMCParticleId(); + if (mcPartId1 == -1) + continue; + const auto& mcParticle1 = mcparts.iteratorAt(mcPartId1); + if (mcParticle1.pdgMCTruth() != ConfTrkSelection.confTrkPDGCodePartOne) + continue; + registryMCreco.fill(HIST("mothersReco/motherParticleTrackPDGCheck"), part.motherPDG()); + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processFractionsSingleReco, "Process MC data to obtain fractions for V0 and protons particles", false); + + void processFractionsSingleTruth(FilteredFDCollision const& col, FemtoRecoParticles const&) + { + auto groupPartsOne = partsOneMCFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + // MC truth + for (const auto& part : groupPartsOne) { + int pdgCode1 = static_cast(part.pidCut()); + if (pdgCode1 != ConfTrkSelection.confTrkPDGCodePartOne) + continue; + registryMCtruth.fill(HIST("mothersTruth/motherParticleTrack"), part.tempFitVar()); + registryMCtruth.fill(HIST("mothersTruth/mcProcessTrack"), part.cut()); + } + for (const auto& part : groupPartsTwo) { + int pdgCode2 = static_cast(part.pidCut()); + if (pdgCode2 != ConfV0Selection.confV0PDGCodePartTwo) + continue; + registryMCtruth.fill(HIST("mothersTruth/motherParticleV0"), part.tempFitVar()); + registryMCtruth.fill(HIST("mothersTruth/mcProcessV0"), part.cut()); + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processFractionsSingleTruth, "Process MC data to obtain fractions for V0 and protons particles", false); + template void doMCReco(PartType const& parts, aod::FdMCParticles const& mcparts) { From 42df39dc9c1a8b87bf9dcfec901374d371052566 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 9 May 2026 22:35:39 +0200 Subject: [PATCH 113/449] [PWGEM/Dilepton] implement down sampling in taggingHFE (#16179) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 80 +++++++++++------------------ 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index c722d997add..cc144ec335d 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -99,7 +99,7 @@ struct taggingHFE { Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgPdgLepton{"cfgPdgLepton", 11, "pdg code of desired lepton: 11 or 13"}; - Configurable cfgDownSamplingHc{"cfgDownSamplingHc", 1.1, "down sampling for charm hadrons"}; // there are enough hc, but not jpsi or hb. + Configurable cfgDownSampling{"cfgDownSampling", 1.1, "down sampling for wrongly found SV"}; Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", true, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; struct : ConfigurableGroup { @@ -1028,12 +1028,6 @@ struct taggingHFE { fRegistry.fill(HIST("Electron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Electron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); - auto mcMother = mcParticle.template mothers_as()[0]; - bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); - if (is_e_from_hc && dist01(engine) > cfgDownSamplingHc) { // random sampling hc, if necessary - continue; - } - if (track.sign() > 0) { // positron positronIds.emplace_back(trackId.trackId()); } else { // electron @@ -1160,10 +1154,10 @@ struct taggingHFE { auto mcCollision = mcpos.template mcCollision_as(); bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. - bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; + bool is_e_from_prompt_jpsi = std::abs(mcMother.pdgCode()) == 443 && !isMotherFromB && std::abs(mcMother.pdgCode()) != 100443; bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); - if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { + if (!(is_e_from_dy || is_e_from_prompt_jpsi || is_e_from_hc || is_e_from_hb)) { continue; } @@ -1208,7 +1202,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1216,13 +1210,9 @@ struct taggingHFE { continue; } - // if (std::abs(mckaon.pdgCode()) == 11) { - // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); - // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { - // auto daughter = mcParticles.rawIteratorAt(d); - // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); - // } - // } + if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1276,7 +1266,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1284,13 +1274,9 @@ struct taggingHFE { continue; } - // if (std::abs(mckaon.pdgCode()) == 11) { - // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); - // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { - // auto daughter = mcParticles.rawIteratorAt(d); - // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); - // } - // } + if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1367,7 +1353,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1427,7 +1413,7 @@ struct taggingHFE { foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcLambda) > 0; } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1492,7 +1478,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1557,7 +1543,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1591,10 +1577,10 @@ struct taggingHFE { auto mcCollision = mcele.template mcCollision_as(); bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. - bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; + bool is_e_from_prompt_jpsi = std::abs(mcMother.pdgCode()) == 443 && !isMotherFromB && std::abs(mcMother.pdgCode()) != 100443; bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); - if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { + if (!(is_e_from_dy || is_e_from_prompt_jpsi || is_e_from_hc || is_e_from_hb)) { continue; } @@ -1638,7 +1624,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1646,13 +1632,9 @@ struct taggingHFE { continue; } - // if (std::abs(mckaon.pdgCode()) == 11) { - // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); - // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { - // auto daughter = mcParticles.rawIteratorAt(d); - // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); - // } - // } + if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1707,7 +1689,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1715,13 +1697,9 @@ struct taggingHFE { continue; } - // if (std::abs(mckaon.pdgCode()) == 11) { - // LOGF(info, "mcMother.pdgCode() = %d, mckaon.pdgCode() = %d, foundCommonMother = %d", mcMother.pdgCode(), mckaon.pdgCode(), foundCommonMother); - // for (int d = mcMother.daughtersIds()[0]; d <= mcMother.daughtersIds()[1]; ++d) { - // auto daughter = mcParticles.rawIteratorAt(d); - // LOGF(info, "daughter.pdgCode() = %d", daughter.pdgCode()); - // } - // } + if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1797,7 +1775,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1857,7 +1835,7 @@ struct taggingHFE { foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcLambda) > 0; } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1922,7 +1900,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } @@ -1987,7 +1965,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { continue; } From d61d6b98866a5647e16dd4e340588d4b0667cae6 Mon Sep 17 00:00:00 2001 From: sarjeetagami <162087855+sarjeetagami@users.noreply.github.com> Date: Sun, 10 May 2026 17:09:00 +0530 Subject: [PATCH 114/449] [PWGLF] bug fix in phi analysis (#16145) Co-authored-by: sarjeeta gami --- PWGLF/Tasks/Resonances/CMakeLists.txt | 2 +- ...srun3_PbPb.cxx => phianalysisrun3pbpb.cxx} | 55 ++++++++++--------- 2 files changed, 29 insertions(+), 28 deletions(-) rename PWGLF/Tasks/Resonances/{phianalysisrun3_PbPb.cxx => phianalysisrun3pbpb.cxx} (98%) diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 4d987a4ddf4..1dd8a1015d8 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -135,7 +135,7 @@ o2physics_add_dpl_workflow(phipbpb COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(phianalysisrun3pbpb - SOURCES phianalysisrun3_PbPb.cxx + SOURCES phianalysisrun3pbpb.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx similarity index 98% rename from PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx rename to PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx index 9787970f588..803a534fca0 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx @@ -8,7 +8,8 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file phianalysisrun3_PbPb.cxx + +/// \file phianalysisrun3pbpb.cxx /// \brief Code for phi resonance without resonance initializer /// \author Sarjeeta Gami @@ -55,7 +56,7 @@ using namespace o2::framework::expressions; using std::array; using namespace o2::aod::rctsel; -struct phianalysisrun3_PbPb { +struct Phianalysisrun3pbpb { struct : ConfigurableGroup { Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; @@ -124,7 +125,7 @@ struct phianalysisrun3_PbPb { Configurable centestimator{"centestimator", 0, "Select multiplicity estimator: 0 - FT0C, 1 - FT0A, 2 - FT0M, 3 - FV0A, 4 - PVTracks"}; ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; Configurable isApplyCentFT0C{"isApplyCentFT0C", true, "Centrality based on FT0C"}; - Configurable isApplyCentFT0M{"isApplyCentFV0M", false, "Centrality based on FT0M"}; + Configurable isApplyCentFT0M{"isApplyCentFT0M", false, "Centrality based on FT0M"}; Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; Configurable isApplyTVX{"isApplyTVX", false, "Enable TVX trigger sel"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; @@ -349,11 +350,11 @@ struct phianalysisrun3_PbPb { return false; } else if (pid == 1) { - constexpr double kPtThresholdForTOF = 0.5; - if (candidate.pt() < kPtThresholdForTOF && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmacutTPC) { + constexpr double PtThresholdForTOF = 0.5; + if (candidate.pt() < PtThresholdForTOF && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmacutTPC) { return true; } - if (candidate.pt() >= kPtThresholdForTOF && candidate.hasTOF() && candidate.beta() > cfgCutTOFBeta && + if (candidate.pt() >= PtThresholdForTOF && candidate.hasTOF() && candidate.beta() > cfgCutTOFBeta && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmacutTPC && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmacutTOF) { return true; } @@ -461,10 +462,10 @@ struct phianalysisrun3_PbPb { candidate1.pz() + candidate2.pz()}, mass); - constexpr int kOppositeCharge = 0; + constexpr int OppositeCharge = 0; // default filling - if (rapidity > rapiditycut1 && rapidity < rapiditycut2 && track1Sign * track2Sign < kOppositeCharge) { + if (rapidity > rapiditycut1 && rapidity < rapiditycut2 && track1Sign * track2Sign < OppositeCharge) { if (unlike) { histos.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, pT, mass); histos.fill(HIST("h2PhiRapidity"), pT, rapidity); @@ -664,7 +665,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processSameEvent, "Process Same event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processSameEvent, "Process Same event", false); void processMixedEvent1(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -740,7 +741,7 @@ struct phianalysisrun3_PbPb { } } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent1, "Process Mixed event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMixedEvent1, "Process Mixed event", false); void processMixedEvent2(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -817,7 +818,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent2, "Process Mixed event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMixedEvent2, "Process Mixed event", false); void processMixedEvent3(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -894,7 +895,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent3, "Process Mixed event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMixedEvent3, "Process Mixed event", false); void processMixedEvent4(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -971,7 +972,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent4, "Process Mixed event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMixedEvent4, "Process Mixed event", false); void processRotEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { if (!collision.sel8()) { @@ -1057,7 +1058,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processRotEvent, "Process Rot event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processRotEvent, "Process Rot event", false); void processMC(CollisionMCTrueTable::iterator const& /*TrueCollision*/, CollisionMCRecTableCentFT0C const& RecCollisions, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { histos.fill(HIST("hMC"), 0); @@ -1270,7 +1271,7 @@ struct phianalysisrun3_PbPb { } // rec collision loop } // process MC - PROCESS_SWITCH(phianalysisrun3_PbPb, processMC, "Process Reconstructed", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMC, "Process Reconstructed", false); void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { @@ -1358,7 +1359,7 @@ struct phianalysisrun3_PbPb { } } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processGen, "Process Generated", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processGen, "Process Generated", false); void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) { if (!collision.has_mcCollision()) { @@ -1487,7 +1488,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processRec, "Process Reconstructed", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processRec, "Process Reconstructed", false); void processSameEventMC(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) { if (!collision.sel8()) { @@ -1599,7 +1600,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processSameEventMC, "Process Same event", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processSameEventMC, "Process Same event", false); void processMixedEventMC(EventCandidatesMC const& recCollisions, TrackCandidatesMC const& RecTracks, aod::McParticles const&) { @@ -1684,7 +1685,7 @@ struct phianalysisrun3_PbPb { } } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEventMC, "Process Mixed event MC", true); + PROCESS_SWITCH(Phianalysisrun3pbpb, processMixedEventMC, "Process Mixed event MC", true); void processGen1(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { // all events @@ -1771,7 +1772,7 @@ struct phianalysisrun3_PbPb { multiplicity = collision.centFV0A(); } histos.fill(HIST("Centgen1"), multiplicity); - selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } selectedEvents.resize(nevts); const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); @@ -1815,7 +1816,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processGen1, "Process Generated", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processGen1, "Process Generated", false); void processRec1(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) { if (!collision.has_mcCollision()) { @@ -1964,7 +1965,7 @@ struct phianalysisrun3_PbPb { } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processRec1, "Process Reconstructed", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processRec1, "Process Reconstructed", false); void processEvtLossSigLossMC(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { @@ -2040,7 +2041,7 @@ struct phianalysisrun3_PbPb { } } // end loop on gen particles } - PROCESS_SWITCH(phianalysisrun3_PbPb, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); void processEvtLossSigLossMC1(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) { if (selectionConfig.cutvzgen && @@ -2092,8 +2093,8 @@ struct phianalysisrun3_PbPb { continue; auto daughters = particle.daughters_as(); - static constexpr int kPhiNDaughters = 2; - if (daughters.size() != kPhiNDaughters) + static constexpr int PhiNDaughters = 2; + if (daughters.size() != PhiNDaughters) continue; bool daup = false, daun = false; @@ -2126,10 +2127,10 @@ struct phianalysisrun3_PbPb { } } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processEvtLossSigLossMC1, "Process Signal Loss, Event Loss", false); + PROCESS_SWITCH(Phianalysisrun3pbpb, processEvtLossSigLossMC1, "Process Signal Loss, Event Loss", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"phianalysisrun3_PbPb"})}; + adaptAnalysisTask(cfgc)}; } From 0dcf9c49a66181be80e5c40a90bc4a15b31a495a Mon Sep 17 00:00:00 2001 From: rolavick Date: Sun, 10 May 2026 13:50:17 +0200 Subject: [PATCH 115/449] [PWGUD] First attemp for semifwd UPC analysis (#16183) Co-authored-by: ALICE Action Bot --- PWGUD/TableProducer/CMakeLists.txt | 5 + .../TableProducer/upcCandProducerSemiFwd.cxx | 681 ++++++++++++++++++ PWGUD/Tasks/CMakeLists.txt | 5 + PWGUD/Tasks/upcSemiFwdJpsiRl.cxx | 532 ++++++++++++++ 4 files changed, 1223 insertions(+) create mode 100644 PWGUD/TableProducer/upcCandProducerSemiFwd.cxx create mode 100644 PWGUD/Tasks/upcSemiFwdJpsiRl.cxx diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 284b1af9fdc..a69671ab068 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -75,3 +75,8 @@ o2physics_add_dpl_workflow(upc-cand-producer-global-muon SOURCES upcCandProducerGlobalMuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-cand-producer-semi-fwd + SOURCES upcCandProducerSemiFwd.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking + COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx b/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx new file mode 100644 index 00000000000..958c2e8e796 --- /dev/null +++ b/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx @@ -0,0 +1,681 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file upcCandProducerSemiFwd.cxx +/// \brief UPC candidate producer combining forward MCH-MID muons with central-barrel tracks. +/// Anchor: MCH-MID forward track (precise MID timing). Companions: barrel tracks +/// whose BC falls within fBcWindowBarrel of the anchor BC. One UD candidate per anchor BC. +/// \author Roman Lavička, lavicka.roman@gmail.com +/// \since 10.05.2026 + +#include "PWGUD/Core/UPCCutparHolder.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.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 +#include + +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcCandProducerSemiFwd { + bool fDoMC{false}; + + std::map fNewPartIDs; + + Produces udMCCollisions; + Produces udMCParticles; + Produces udFwdTrackLabels; + Produces udTrackLabels; + + Produces udFwdTracks; + Produces udFwdTracksExtra; + Produces udFwdIndices; + + Produces udTracks; + Produces udTracksExtra; + Produces udTracksDCA; + Produces udTracksFlags; + Produces udTracksPID; + + Produces eventCandidates; + Produces eventCandidatesSelsFwd; + Produces udZdcsReduced; + + Configurable fSignalGenID{"fSignalGenID", 1, "Signal generator ID"}; + + UPCCutparHolder fUpcCuts = UPCCutparHolder(); + MutableConfigurable fUpcCutsConf{"fUpcCutsConf", {}, "UPC event cuts"}; + Configurable fBcWindowFITAmps{"fBcWindowFITAmps", 20, "BC range for T0A/V0A amplitudes array [-range, +(range-1)]"}; + Configurable fBcWindowBarrel{"fBcWindowBarrel", 20, "Time window for barrel-track to MCH-MID anchor matching"}; + Configurable fMaxFV0Amp{"fMaxFV0Amp", 100.f, "Max FV0 amplitude in the same BC"}; + + using ForwardTracks = o2::soa::Join; + + using BarrelTracks = o2::soa::Join; + + HistogramRegistry histRegistry{"HistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + int fRun{0}; + Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; + o2::globaltracking::MatchGlobalFwd fMatching; + + void init(InitContext&) + { + fUpcCuts = (UPCCutparHolder)fUpcCutsConf; + if (fUpcCuts.getUseFwdCuts()) { + fCCDB->setURL("http://alice-ccdb.cern.ch"); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDBApi.init("http://alice-ccdb.cern.ch"); + } + const AxisSpec axisSelFwd{upchelpers::kNFwdSels, 0., static_cast(upchelpers::kNFwdSels), ""}; + histRegistry.add("MuonsSelCounter", "", kTH1F, {axisSelFwd}); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelAll + 1, "All"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelPt + 1, "Pt"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelEta + 1, "Eta"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelRabs + 1, "Rabs"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelpDCA + 1, "pDCA"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelChi2 + 1, "Chi2"); + + const AxisSpec axisSelBar{upchelpers::kNBarrelSels, 0., static_cast(upchelpers::kNBarrelSels), ""}; + histRegistry.add("BarrelsSelCounter", "", kTH1F, {axisSelBar}); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelAll + 1, "All"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelHasTOF + 1, "HasTOF"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelPt + 1, "Pt"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelEta + 1, "Eta"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelITSNCls + 1, "ITSNCls"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelITSChi2 + 1, "ITSChi2"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelTPCNCls + 1, "TPCNCls"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelTPCChi2 + 1, "TPCChi2"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelDCAXY + 1, "DCAXY"); + histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelDCAZ + 1, "DCAZ"); + } + + bool fwdCut(const o2::dataformats::GlobalFwdTrack& pft, const ForwardTracks::iterator& fwdTrack) + { + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelAll, 1); + auto pt = pft.getPt(); + auto eta = pft.getEta(); + auto pdca = fwdTrack.pDca(); + auto rabs = fwdTrack.rAtAbsorberEnd(); + auto chi2 = fwdTrack.chi2(); + bool passPt = pt > fUpcCuts.getFwdPtLow() && pt < fUpcCuts.getFwdPtHigh(); + bool passEta = eta > fUpcCuts.getFwdEtaLow() && eta < fUpcCuts.getFwdEtaHigh(); + bool passRabs = rabs > fUpcCuts.getMuonRAtAbsorberEndLow() && rabs < fUpcCuts.getMuonRAtAbsorberEndHigh(); + bool passPDca = rabs < upchelpers::AbsorberMid ? pdca < fUpcCuts.getMuonPDcaHighFirst() : pdca < fUpcCuts.getMuonPDcaHighSecond(); + bool passChi2 = chi2 > fUpcCuts.getFwdChi2Low() && chi2 < fUpcCuts.getFwdChi2High(); + if (passPt) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelPt, 1); + if (passEta) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelEta, 1); + if (passRabs) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelRabs, 1); + if (passPDca) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelpDCA, 1); + if (passChi2) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelChi2, 1); + return passPt && passEta && passRabs && passPDca && passChi2; + } + + bool barCut(const BarrelTracks::iterator& track) + { + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelAll, 1); + if (!fUpcCuts.getUseBarCuts()) + return true; + if (fUpcCuts.getAmbigSwitch() == 1 && !track.isPVContributor()) + return false; + if (fUpcCuts.getRequireTOF() && !track.hasTOF()) + return false; + bool passHasTOF = !fUpcCuts.getRequireTOF() || track.hasTOF(); + bool passPt = track.pt() > fUpcCuts.getBarPtLow() && track.pt() < fUpcCuts.getBarPtHigh(); + bool passEta = track.eta() > fUpcCuts.getBarEtaLow() && track.eta() < fUpcCuts.getBarEtaHigh(); + bool passITSNCls = track.itsNCls() >= static_cast(fUpcCuts.getITSNClusLow()) && + track.itsNCls() <= static_cast(fUpcCuts.getITSNClusHigh()); + bool passITSChi2 = track.itsChi2NCl() > fUpcCuts.getITSChi2Low() && track.itsChi2NCl() < fUpcCuts.getITSChi2High(); + bool passTPCNCls = track.tpcNClsFound() >= static_cast(fUpcCuts.getTPCNClsLow()) && + track.tpcNClsFound() <= static_cast(fUpcCuts.getTPCNClsHigh()); + bool passTPCChi2 = track.tpcChi2NCl() > fUpcCuts.getTPCChi2Low() && track.tpcChi2NCl() < fUpcCuts.getTPCChi2High(); + bool passDcaZ = track.dcaZ() > fUpcCuts.getDcaZLow() && track.dcaZ() < fUpcCuts.getDcaZHigh(); + bool passDcaXY = true; + if (fUpcCuts.getCheckMaxDcaXY()) { + constexpr float DcaXYConst = 0.0105f; + constexpr float DcaXYSlope = 0.0350f; + constexpr float DcaXYExp = 1.1f; + float maxDCA = DcaXYConst + DcaXYSlope / std::pow(track.pt(), DcaXYExp); + passDcaXY = track.dcaXY() < maxDCA; + } + if (passHasTOF) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelHasTOF, 1); + if (passPt) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelPt, 1); + if (passEta) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelEta, 1); + if (passITSNCls) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelITSNCls, 1); + if (passITSChi2) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelITSChi2, 1); + if (passTPCNCls) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelTPCNCls, 1); + if (passTPCChi2) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelTPCChi2, 1); + if (passDcaXY) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelDCAXY, 1); + if (passDcaZ) + histRegistry.fill(HIST("BarrelsSelCounter"), upchelpers::kBarrelSelDCAZ, 1); + return passPt && passEta && passITSNCls && passITSChi2 && passTPCNCls && passTPCChi2 && passDcaXY && passDcaZ; + } + + void skimMCInfo(o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + { + std::vector newEventIDs(mcCollisions.size(), -1); + + int32_t newPartID = 0; + int32_t newEventID = 0; + int32_t nMCParticles = mcParticles.size(); + for (int32_t mcPartID = 0; mcPartID < nMCParticles; mcPartID++) { + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + if (!mcPart.has_mcCollision()) + continue; + int32_t mcEventID = mcPart.mcCollisionId(); + const auto& mcEvent = mcCollisions.iteratorAt(mcEventID); + bool isSignal = mcEvent.getGeneratorId() == fSignalGenID; + if (!isSignal) { + continue; + } + fNewPartIDs[mcPartID] = newPartID; + newPartID++; + if (newEventIDs[mcEventID] == -1) { + newEventIDs[mcEventID] = newEventID; + newEventID++; + } + } + + std::vector newMotherIDs{}; + + for (const auto& item : fNewPartIDs) { + int32_t mcPartID = item.first; + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + int32_t mcEventID = mcPart.mcCollisionId(); + int32_t mappedEventID = newEventIDs[mcEventID]; + if (mcPart.has_mothers()) { + const auto& motherIDs = mcPart.mothersIds(); + for (const auto& motherID : motherIDs) { + if (motherID >= nMCParticles) { + continue; + } + auto it = fNewPartIDs.find(motherID); + if (it != fNewPartIDs.end()) { + newMotherIDs.push_back(it->second); + } + } + } + int32_t newDaughterIDs[2] = {-1, -1}; + if (mcPart.has_daughters()) { + const auto& daughterIDs = mcPart.daughtersIds(); + int32_t firstDaughter = daughterIDs.front(); + int32_t lastDaughter = daughterIDs.back(); + if (firstDaughter >= nMCParticles || lastDaughter >= nMCParticles) { + continue; + } + auto itFirst = fNewPartIDs.find(firstDaughter); + auto itLast = fNewPartIDs.find(lastDaughter); + if (itFirst != fNewPartIDs.end() && itLast != fNewPartIDs.end()) { + newDaughterIDs[0] = fNewPartIDs.at(daughterIDs.front()); + newDaughterIDs[1] = fNewPartIDs.at(daughterIDs.back()); + } + } + udMCParticles(mappedEventID, mcPart.pdgCode(), mcPart.getHepMCStatusCode(), mcPart.flags(), newMotherIDs, newDaughterIDs, + mcPart.weight(), mcPart.px(), mcPart.py(), mcPart.pz(), mcPart.e()); + newMotherIDs.clear(); + } + + for (int32_t i = 0; i < mcCollisions.size(); i++) { + if (newEventIDs[i] == -1) { + continue; + } + const auto& mcEvent = mcCollisions.iteratorAt(i); + const auto& bc = mcEvent.bc(); + udMCCollisions(bc.globalBC(), mcEvent.generatorsID(), mcEvent.posX(), mcEvent.posY(), mcEvent.posZ(), + mcEvent.t(), mcEvent.weight(), mcEvent.impactParameter()); + } + + newEventIDs.clear(); + } + + int64_t bcDiff(uint64_t bc1, uint64_t bc2) + { + return bc1 > bc2 ? bc1 - bc2 : bc2 - bc1; + } + + template + T::iterator getStartForScroll(uint64_t inGbc, T& gbcMap) + { + auto it1 = gbcMap.lower_bound(inGbc); + typename T::iterator it; + if (it1 != gbcMap.end()) { + auto it2 = it1; + uint64_t bc1 = it1->first; + if (it2 != gbcMap.begin()) + --it2; + uint64_t bc2 = it2->first; + uint64_t dbc1 = bcDiff(bc1, inGbc); + uint64_t dbc2 = bcDiff(bc2, inGbc); + it = (dbc1 <= dbc2) ? it1 : it2; + } else { + it = it1; + --it; + } + return it; + } + + template + void scrollBackForth(uint64_t inGbc, uint64_t maxDbc, T& gbcMap, F&& func) + { + auto it = getStartForScroll(inGbc, gbcMap); + uint64_t gbc = it->first; + uint64_t dbc = bcDiff(inGbc, gbc); + + int count = 0; + while (dbc <= maxDbc) { + func(it, gbc); + count++; + if (it == gbcMap.begin()) + break; + --it; + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + } + + std::advance(it, count + 1); + + if (it == gbcMap.end()) + return; + + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + + while (dbc <= maxDbc) { + func(it, gbc); + ++it; + if (it == gbcMap.end()) + break; + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + } + } + + void getBarrelTrackIds(uint64_t inGbc, std::map>& tracksPerBC, + uint64_t maxDbc, std::map& outTrkIds) + { + auto fillIds = [&outTrkIds](std::map>::iterator& inIt, uint64_t gbc) { + std::vector& ids = inIt->second; + for (const auto& id : ids) + outTrkIds[id] = gbc; + }; + scrollBackForth(inGbc, maxDbc, tracksPerBC, fillIds); + } + + void getFV0Amplitudes(uint64_t inGbc, o2::aod::FV0As const& fv0s, uint64_t maxDbc, + std::map& mapBcs, std::vector& amps, std::vector& relBcs) + { + auto fillAmps = [this, &fv0s, &s, &relBcs, inGbc](std::map::iterator& inIt, uint64_t gbc) { + int64_t fv0Id = inIt->second; + const auto& fv0 = fv0s.iteratorAt(fv0Id); + const auto& amplitudes = fv0.amplitude(); + float totalAmp = std::accumulate(amplitudes.begin(), amplitudes.end(), 0.f); + if (totalAmp > 0.f) { + amps.push_back(totalAmp); + auto relBc = static_cast(bcDiff(gbc, inGbc)); + if (gbc < inGbc) + relBc *= -1; + relBcs.push_back(relBc); + } + }; + scrollBackForth(inGbc, maxDbc, mapBcs, fillAmps); + } + + auto propagateToZero(ForwardTracks::iterator const& muon) + { + using SMatrix55 = ROOT::Math::SMatrix>; + using SMatrix5 = ROOT::Math::SVector; + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::dataformats::GlobalFwdTrack propmuon; + o2::dataformats::GlobalFwdTrack track; + track.setParameters(tpars); + track.setZ(muon.z()); + track.setCovariances(tcovs); + auto mchTrack = fMatching.FwdtoMCH(track); + o2::mch::TrackExtrap::extrapToVertex(mchTrack, 0., 0., 0., 0., 0.); + auto proptrack = fMatching.MCHtoFwd(mchTrack); + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + return propmuon; + } + + bool addToFwdTable(int64_t candId, int64_t trackId, uint64_t gbc, float trackTime, ForwardTracks const& fwdTracks, + const o2::aod::McFwdTrackLabels* mcFwdTrackLabels) + { + constexpr float NoMchMftMatch = -1.f; + const auto& track = fwdTracks.iteratorAt(trackId); + float px; + float py; + float pz; + int sign; + if (fUpcCuts.getUseFwdCuts()) { + auto pft = propagateToZero(track); + bool pass = fwdCut(pft, track); + if (!pass) + return false; + px = pft.getPx(); + py = pft.getPy(); + pz = pft.getPz(); + sign = (pft.getInvQPt() > 0) ? 1 : -1; + } else { + px = track.px(); + py = track.py(); + pz = track.pz(); + sign = track.sign(); + } + udFwdTracks(candId, px, py, pz, sign, gbc, trackTime, track.trackTimeRes()); + udFwdTracksExtra(track.trackType(), track.nClusters(), track.pDca(), track.rAtAbsorberEnd(), track.chi2(), + track.chi2MatchMCHMID(), NoMchMftMatch, track.mchBitMap(), track.midBitMap(), track.midBoards()); + udFwdIndices(candId, trackId, track.matchMCHTrackId(), -1); + if (fDoMC) { + const auto& label = mcFwdTrackLabels->iteratorAt(trackId); + uint16_t mcMask = label.mcMask(); + auto it = fNewPartIDs.find(label.mcParticleId()); + int32_t newPartID = it != fNewPartIDs.end() ? it->second : -1; + udFwdTrackLabels(newPartID, mcMask); + } + return true; + } + + bool addToBarrelTable(int64_t candId, int64_t trackId, uint64_t gbc, float trackTime, BarrelTracks const& barrelTracks, + const o2::aod::McTrackLabels* mcTrackLabels) + { + const auto& track = barrelTracks.iteratorAt(trackId); + if (!barCut(track)) + return false; + int32_t colId = track.collisionId() >= 0 ? track.collisionId() : -1; + udTracks(candId, track.px(), track.py(), track.pz(), track.sign(), gbc, trackTime, track.trackTimeRes()); + udTracksExtra(track.tpcInnerParam(), track.itsClusterSizes(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), + track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.trdPattern(), track.itsChi2NCl(), + track.tpcChi2NCl(), track.trdChi2(), track.tofChi2(), track.tpcSignal(), track.tofSignal(), track.trdSignal(), + track.length(), track.tofExpMom(), track.detectorMap()); + udTracksDCA(track.dcaZ(), track.dcaXY()); + udTracksFlags(colId, track.isPVContributor()); + udTracksPID(track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.betaerror(), + track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()); + if (fDoMC) { + const auto& label = mcTrackLabels->iteratorAt(trackId); + uint16_t mcMask = label.mcMask(); + auto it = fNewPartIDs.find(label.mcParticleId()); + int32_t newPartID = it != fNewPartIDs.end() ? it->second : -1; + udTrackLabels(newPartID, mcMask); + } + return true; + } + + void createCandidates(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BarrelTracks const& barrelTracks, + o2::aod::AmbiguousTracks const& ambBarrelTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs, + const o2::aod::McFwdTrackLabels* mcFwdTrackLabels, + const o2::aod::McTrackLabels* mcBarrelTrackLabels) + { + using o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack; + + int32_t runNumber = bcs.iteratorAt(0).runNumber(); + if (fUpcCuts.getUseFwdCuts()) { + if (runNumber != fRun) { + fRun = runNumber; + std::map metadata; + auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(fCCDBApi, fRun); + auto ts = soreor.second; + auto grpmag = fCCDBApi.retrieveFromTFileAny("GLO/Config/GRPMagField", metadata, ts); + o2::base::Propagator::initFieldFromGRP(grpmag); + if (!o2::base::GeometryManager::isGeometryLoaded()) + fCCDB->get("GLO/Config/GeometryAligned"); + o2::mch::TrackExtrap::setField(); + } + } + + auto nBcs = bcs.size(); + std::vector vGlobalBCs(nBcs, 0); + for (const auto& bc : bcs) { + vGlobalBCs[bc.globalIndex()] = bc.globalBC(); + } + + auto nCols = collisions.size(); + std::vector vColIndexBCs(nCols, -1); + for (const auto& col : collisions) { + vColIndexBCs[col.globalIndex()] = col.bcId(); + } + + std::map mapGlobalBcWithV0A{}; + constexpr float FV0ValidTime = 15.f; + for (const auto& fv0 : fv0s) { + if (std::abs(fv0.time()) > FV0ValidTime) + continue; + uint64_t globalBC = vGlobalBCs[fv0.bcId()]; + mapGlobalBcWithV0A[globalBC] = fv0.globalIndex(); + } + auto nFV0s = mapGlobalBcWithV0A.size(); + + std::map mapGlobalBcWithZdc{}; + constexpr float ZDCValidTime = 2.f; + for (const auto& zdc : zdcs) { + if (std::abs(zdc.timeZNA()) > ZDCValidTime && std::abs(zdc.timeZNC()) > ZDCValidTime) + continue; + uint64_t globalBC = vGlobalBCs[zdc.bcId()]; + mapGlobalBcWithZdc[globalBC] = zdc.globalIndex(); + } + auto nZdcs = mapGlobalBcWithZdc.size(); + + auto nFwdTracks = fwdTracks.size(); + auto nAmbFwdTracks = ambFwdTracks.size(); + std::vector vAmbFwdTrackIndex(nFwdTracks, -1); + std::vector vAmbFwdTrackIndexBCs(nAmbFwdTracks, -1); + for (const auto& ambTr : ambFwdTracks) { + vAmbFwdTrackIndex[ambTr.fwdtrackId()] = ambTr.globalIndex(); + vAmbFwdTrackIndexBCs[ambTr.globalIndex()] = ambTr.bcIds()[0]; + } + + auto nBarrelTracks = barrelTracks.size(); + auto nAmbBarrelTracks = ambBarrelTracks.size(); + std::vector vAmbBarTrackIndex(nBarrelTracks, -1); + std::vector vAmbBarTrackIndexBCs(nAmbBarrelTracks, -1); + for (const auto& ambTr : ambBarrelTracks) { + vAmbBarTrackIndex[ambTr.trackId()] = ambTr.globalIndex(); + vAmbBarTrackIndexBCs[ambTr.globalIndex()] = ambTr.bcIds()[0]; + } + + // anchor map: MCH-MID forward muons keyed by their global BC + std::map> mapGlobalBcsWithMCHMIDTrackIds; + for (const auto& fwdTrack : fwdTracks) { + if (fwdTrack.trackType() != MuonStandaloneTrack) + continue; + auto trackId = fwdTrack.globalIndex(); + int64_t indexBC = vAmbFwdTrackIndex[trackId] < 0 ? vColIndexBCs[fwdTrack.collisionId()] : vAmbFwdTrackIndexBCs[vAmbFwdTrackIndex[trackId]]; + auto globalBC = vGlobalBCs[indexBC] + TMath::FloorNint(fwdTrack.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + 1.); + mapGlobalBcsWithMCHMIDTrackIds[globalBC].push_back(trackId); + } + + // companion map: barrel tracks keyed by their global BC + std::map> mapGlobalBcsWithBarrelTrackIds; + for (const auto& barTrack : barrelTracks) { + auto trackId = barTrack.globalIndex(); + int64_t bcId = vAmbBarTrackIndex[trackId] < 0 + ? (barTrack.has_collision() ? vColIndexBCs[barTrack.collisionId()] : -1) + : vAmbBarTrackIndexBCs[vAmbBarTrackIndex[trackId]]; + if (bcId < 0) + continue; + auto globalBC = vGlobalBCs[bcId] + TMath::FloorNint(barTrack.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + 1.); + mapGlobalBcsWithBarrelTrackIds[globalBC].push_back(trackId); + } + + int32_t candId = 0; + for (const auto& gbcMuids : mapGlobalBcsWithMCHMIDTrackIds) { + uint64_t globalBcMid = gbcMuids.first; + + // veto on FV0 in the same BC as the anchor + auto itFv0Id = mapGlobalBcWithV0A.find(globalBcMid); + if (itFv0Id != mapGlobalBcWithV0A.end()) { + auto fv0Id = itFv0Id->second; + const auto& fv0 = fv0s.iteratorAt(fv0Id); + float fv0Amp = 0.f; + for (const auto& amp : fv0.amplitude()) + fv0Amp += amp; + if (fv0Amp > fMaxFV0Amp) + continue; + } + + uint16_t numContrib = 0; + auto& vMuonIds = gbcMuids.second; + for (const auto& imuon : vMuonIds) { + if (!addToFwdTable(candId, imuon, globalBcMid, 0., fwdTracks, mcFwdTrackLabels)) + continue; + numContrib++; + } + if (numContrib < 1) // anchor produced no surviving fwd tracks + continue; + + // gather barrel tracks within ±fBcWindowBarrel of the anchor + std::map mapBarIdBc{}; + getBarrelTrackIds(globalBcMid, mapGlobalBcsWithBarrelTrackIds, fBcWindowBarrel, mapBarIdBc); + for (const auto& [ibar, gbc] : mapBarIdBc) { + float trackTime = (static_cast(gbc) - static_cast(globalBcMid)) * o2::constants::lhc::LHCBunchSpacingNS; + if (!addToBarrelTable(candId, ibar, gbc, trackTime, barrelTracks, mcBarrelTrackLabels)) + continue; + numContrib++; + } + + eventCandidates(globalBcMid, runNumber, 0., 0., 0., 0, numContrib, 0, 0); + std::vector amplitudesV0A{}; + std::vector relBCsV0A{}; + std::vector amplitudesT0A{}; + std::vector relBCsT0A{}; + if (nFV0s > 0) { + getFV0Amplitudes(globalBcMid, fv0s, fBcWindowFITAmps, mapGlobalBcWithV0A, amplitudesV0A, relBCsV0A); + } + eventCandidatesSelsFwd(0., 0., amplitudesT0A, relBCsT0A, amplitudesV0A, relBCsV0A); + if (nZdcs > 0) { + auto itZDC = mapGlobalBcWithZdc.find(globalBcMid); + if (itZDC != mapGlobalBcWithZdc.end()) { + const auto& zdc = zdcs.iteratorAt(itZDC->second); + float timeZNA = zdc.timeZNA(); + float timeZNC = zdc.timeZNC(); + float eComZNA = zdc.energyCommonZNA(); + float eComZNC = zdc.energyCommonZNC(); + udZdcsReduced(candId, timeZNA, timeZNC, eComZNA, eComZNC); + } + } + candId++; + } + + vGlobalBCs.clear(); + vColIndexBCs.clear(); + mapGlobalBcWithV0A.clear(); + mapGlobalBcWithZdc.clear(); + vAmbFwdTrackIndex.clear(); + vAmbFwdTrackIndexBCs.clear(); + vAmbBarTrackIndex.clear(); + vAmbBarTrackIndexBCs.clear(); + mapGlobalBcsWithMCHMIDTrackIds.clear(); + mapGlobalBcsWithBarrelTrackIds.clear(); + } + + void processSemiFwd(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BarrelTracks const& barrelTracks, + o2::aod::AmbiguousTracks const& ambBarrelTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs) + { + fDoMC = false; + createCandidates(fwdTracks, ambFwdTracks, barrelTracks, ambBarrelTracks, bcs, collisions, fv0s, zdcs, + (o2::aod::McFwdTrackLabels*)nullptr, (o2::aod::McTrackLabels*)nullptr); + } + + void processSemiFwdMC(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BarrelTracks const& barrelTracks, + o2::aod::AmbiguousTracks const& ambBarrelTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs, + o2::aod::McCollisions const& mcCollisions, + o2::aod::McParticles const& mcParticles, + o2::aod::McFwdTrackLabels const& mcFwdTrackLabels, + o2::aod::McTrackLabels const& mcBarrelTrackLabels) + { + fDoMC = true; + skimMCInfo(mcCollisions, mcParticles); + createCandidates(fwdTracks, ambFwdTracks, barrelTracks, ambBarrelTracks, bcs, collisions, fv0s, zdcs, + &mcFwdTrackLabels, &mcBarrelTrackLabels); + fNewPartIDs.clear(); + } + + PROCESS_SWITCH(UpcCandProducerSemiFwd, processSemiFwd, "Produce candidates combining forward MCH-MID and central-barrel tracks", true); + PROCESS_SWITCH(UpcCandProducerSemiFwd, processSemiFwdMC, "Produce semi-forward candidates with MC information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 5fe01ad5980..b30af171280 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -209,6 +209,11 @@ o2physics_add_dpl_workflow(upc-fwd-jpsi-rl PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(upc-semi-fwd-jpsi-rl + SOURCES upcSemiFwdJpsiRl.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(upc-event-itsrof-counter SOURCES upcEventITSROFcounter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB diff --git a/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx b/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx new file mode 100644 index 00000000000..eb77adce860 --- /dev/null +++ b/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx @@ -0,0 +1,532 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file upcSemiFwdJpsiRl.cxx +/// \brief UPC semi-forward J/psi -> mu+mu- analysis pairing one forward MCH-MID muon +/// with one central-barrel track. Consumes UD tables produced by +/// upcCandProducerSemiFwd. +/// \author Roman Lavicka, roman.lavicka@cern.ch +/// \since 10.05.2026 +/// +/// executable name o2-analysis-ud-upc-semi-fwd-jpsi-rl + +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +// table for saving tree with semi-forward dimuon info +namespace jpsisfw +{ +// dimuon +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Px, px, float); +DECLARE_SOA_COLUMN(Py, py, float); +DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(PhiAv, phiAv, float); +DECLARE_SOA_COLUMN(PhiCh, phiCh, float); +// positive (p) and negative (n) tracks +DECLARE_SOA_COLUMN(EnergyP, energyP, float); +DECLARE_SOA_COLUMN(Pxp, pxp, float); +DECLARE_SOA_COLUMN(Pyp, pyp, float); +DECLARE_SOA_COLUMN(Pzp, pzp, float); +DECLARE_SOA_COLUMN(Ptp, ptp, float); +DECLARE_SOA_COLUMN(Etap, etap, float); +DECLARE_SOA_COLUMN(Phip, phip, float); +DECLARE_SOA_COLUMN(IsFwdP, isFwdP, int); // 1 if the positive track is forward, 0 if barrel +DECLARE_SOA_COLUMN(EnergyN, energyN, float); +DECLARE_SOA_COLUMN(Pxn, pxn, float); +DECLARE_SOA_COLUMN(Pyn, pyn, float); +DECLARE_SOA_COLUMN(Pzn, pzn, float); +DECLARE_SOA_COLUMN(Ptn, ptn, float); +DECLARE_SOA_COLUMN(Etan, etan, float); +DECLARE_SOA_COLUMN(Phin, phin, float); +DECLARE_SOA_COLUMN(IsFwdN, isFwdN, int); +// zn +DECLARE_SOA_COLUMN(Tzna, tzna, float); +DECLARE_SOA_COLUMN(Ezna, ezna, float); +DECLARE_SOA_COLUMN(Tznc, tznc, float); +DECLARE_SOA_COLUMN(Eznc, eznc, float); +DECLARE_SOA_COLUMN(Nclass, nclass, int); +} // namespace jpsisfw + +namespace o2::aod +{ +DECLARE_SOA_TABLE(JpsiSemiFwdRL, "AOD", "JPSISFW", + jpsisfw::RunNumber, + jpsisfw::M, jpsisfw::Energy, jpsisfw::Px, jpsisfw::Py, jpsisfw::Pz, jpsisfw::Pt, jpsisfw::Rap, jpsisfw::Phi, + jpsisfw::PhiAv, jpsisfw::PhiCh, + jpsisfw::EnergyP, jpsisfw::Pxp, jpsisfw::Pyp, jpsisfw::Pzp, jpsisfw::Ptp, jpsisfw::Etap, jpsisfw::Phip, jpsisfw::IsFwdP, + jpsisfw::EnergyN, jpsisfw::Pxn, jpsisfw::Pyn, jpsisfw::Pzn, jpsisfw::Ptn, jpsisfw::Etan, jpsisfw::Phin, jpsisfw::IsFwdN, + jpsisfw::Tzna, jpsisfw::Ezna, jpsisfw::Tznc, jpsisfw::Eznc, jpsisfw::Nclass); +} // namespace o2::aod + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// constants used in the forward-muon selection (mirror upcFwdJpsiRl) +const float kRAbsMin = 17.6; +const float kRAbsMid = 26.5; +const float kRAbsMax = 89.5; +const float kPDca1 = 200.; +const float kPDca2 = 200.; +const float kFwdEtaMin = -4.0; +const float kFwdEtaMax = -2.5; +const float kFwdPtMin = 0.; + +const float kMaxAmpV0A = 100.; +const float kMaxZDCTime = 2.; +const float kMaxZDCTimeHisto = 10.; +const float kInvalidFloat = -999.; +const int kMaxRelBCsV0A = 1; + +struct UpcSemiFwdJpsiRl { + + using CandidatesSemiFwd = soa::Join; + using ForwardTracks = soa::Join; + using BarrelTracks = soa::Join; + + Produces dimuSel; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry reg0n0n{"reg0n0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXn0n{"regXn0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry regXnXn{"regXnXn", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // CONFIGURABLES + static constexpr double Pi = o2::constants::math::PI; + // pair kinematics + Configurable nBinsPt{"nBinsPt", 250, "N bins in pT histo"}; + Configurable lowPt{"lowPt", 0., "lower limit in pT histo"}; + Configurable highPt{"highPt", 2., "upper limit in pT histo"}; + Configurable nBinsMass{"nBinsMass", 500, "N bins in mass histo"}; + Configurable lowMass{"lowMass", 0., "lower limit in mass histo"}; + Configurable highMass{"highMass", 10., "upper limit in mass histo"}; + Configurable nBinsEta{"nBinsEta", 600, "N bins in eta histo"}; + Configurable lowEta{"lowEta", -10., "lower limit in eta histo"}; + Configurable highEta{"highEta", 5., "upper limit in eta histo"}; + Configurable nBinsRapidity{"nBinsRapidity", 500, "N bins in rapidity histo"}; + Configurable lowRapidity{"lowRapidity", -4.5, "lower limit in rapidity histo"}; + Configurable highRapidity{"highRapidity", 0., "upper limit in rapidity histo"}; + Configurable nBinsPhi{"nBinsPhi", 600, "N bins in phi histo"}; + Configurable lowPhi{"lowPhi", -Pi, "lower limit in phi histo"}; + Configurable highPhi{"highPhi", Pi, "upper limit in phi histo"}; + // single-track histos + Configurable nBinsPtSingle{"nBinsPtSingle", 500, "N bins in pT histo single track"}; + Configurable lowPtSingle{"lowPtSingle", 0., "lower limit in pT histo single track"}; + Configurable highPtSingle{"highPtSingle", 5., "upper limit in pT histo single track"}; + Configurable nBinsEtaSingle{"nBinsEtaSingle", 250, "N bins in eta histo single track"}; + Configurable lowEtaSingle{"lowEtaSingle", -4.5, "lower limit in eta histo single track"}; + Configurable highEtaSingle{"highEtaSingle", 1.5, "upper limit in eta histo single track"}; + Configurable nBinsPhiSingle{"nBinsPhiSingle", 600, "N bins in phi histo single track"}; + Configurable lowPhiSingle{"lowPhiSingle", -Pi, "lower limit in phi histo single track"}; + Configurable highPhiSingle{"highPhiSingle", Pi, "upper limit in phi histo single track"}; + // ZDC + Configurable nBinsZDCen{"nBinsZDCen", 200, "N bins in ZN energy"}; + Configurable lowEnZN{"lowEnZN", -50., "lower limit in ZN energy histo"}; + Configurable highEnZN{"highEnZN", 250., "upper limit in ZN energy histo"}; + + // central-barrel-muon selection + Configurable barEtaMin{"barEtaMin", -0.9, "barrel min eta"}; + Configurable barEtaMax{"barEtaMax", 0.9, "barrel max eta"}; + Configurable barPtMin{"barPtMin", 0.7, "barrel min pT (GeV/c)"}; + Configurable barMinITSNCls{"barMinITSNCls", 4, "barrel min number of ITS clusters"}; + Configurable barMinTPCNClsCR{"barMinTPCNClsCR", 70, "barrel min number of TPC crossed rows"}; + Configurable barMaxTpcNSigmaMu{"barMaxTpcNSigmaMu", 4., "barrel max |TPC nSigma muon|"}; + Configurable barRequireTOF{"barRequireTOF", false, "require TOF on the barrel track"}; + Configurable barMaxTofNSigmaMu{"barMaxTofNSigmaMu", 3., "barrel max |TOF nSigma muon| when TOF is present"}; + + void init(InitContext&) + { + std::vector ptFitBinning = { + 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, + 0.11, 0.12, 0.13, 0.14, 0.15, 0.175, 0.20, 0.25, 0.30, 0.40, 0.50, + 0.60, 0.70, 0.80, 0.90, 1.00, 1.20, 1.40, 1.60, 1.80, 2.00, 2.50, + 3.00, 3.50}; + + const AxisSpec axisPt{nBinsPt, lowPt, highPt, "#it{p}_{T} GeV/#it{c}"}; + const AxisSpec axisPtFit = {ptFitBinning, "#it{p}_{T} (GeV/c)"}; + const AxisSpec axisMass{nBinsMass, lowMass, highMass, "m_{#mu#mu} GeV/#it{c}^{2}"}; + const AxisSpec axisEta{nBinsEta, lowEta, highEta, "#eta"}; + const AxisSpec axisRapidity{nBinsRapidity, lowRapidity, highRapidity, "Rapidity"}; + const AxisSpec axisPhi{nBinsPhi, lowPhi, highPhi, "#varphi"}; + const AxisSpec axisPtSingle{nBinsPtSingle, lowPtSingle, highPtSingle, "#it{p}_{T}_{ trk} GeV/#it{c}"}; + const AxisSpec axisTimeZN{200, -10, 10, "ZDC time (ns)"}; + const AxisSpec axisEnergyZNA{nBinsZDCen, lowEnZN, highEnZN, "ZNA energy (TeV)"}; + const AxisSpec axisEnergyZNC{nBinsZDCen, lowEnZN, highEnZN, "ZNC energy (TeV)"}; + const AxisSpec axisEtaSingle{nBinsEtaSingle, lowEtaSingle, highEtaSingle, "#eta_{trk}"}; + const AxisSpec axisPhiSingle{nBinsPhiSingle, lowPhiSingle, highPhiSingle, "#varphi_{trk}"}; + + // pair histos + registry.add("hMass", "Invariant mass of mu pairs;;#counts", kTH1D, {axisMass}); + registry.add("hPt", "Transverse momentum of mu pairs;;#counts", kTH1D, {axisPt}); + registry.add("hPtFit", "Transverse momentum of mu pairs;;#counts", kTH1D, {axisPtFit}); + registry.add("hEta", "Pseudorapidity of mu pairs;;#counts", kTH1D, {axisEta}); + registry.add("hRapidity", "Rapidity of mu pairs;;#counts", kTH1D, {axisRapidity}); + registry.add("hPhi", "#varphi of mu pairs;;#counts", kTH1D, {axisPhi}); + registry.add("hCharge", "Charge;;;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hContrib", "hContrib;;#counts", kTH1D, {{20, -0.5, 19.5}}); + registry.add("hEvSign", "Sum of the charges of all the tracks in each event;;#counts", kTH1D, {{5, -2.5, 2.5}}); + registry.add("hSameSign", "hSameSign;;#counts", kTH1D, {{20, -0.5, 19.5}}); + registry.add("hPhiCharge", "#phi #it{charge}", kTH1D, {axisPhi}); + registry.add("hPhiAverage", "#phi #it{average}", kTH1D, {axisPhi}); + + // forward / barrel single-track histos + registry.add("hPtTrkFwd", "Pt of forward muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hPtTrkBar", "Pt of barrel muons;;#counts", kTH1D, {axisPtSingle}); + registry.add("hEtaTrkFwd", "#eta of forward muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hEtaTrkBar", "#eta of barrel muons;;#counts", kTH1D, {axisEtaSingle}); + registry.add("hPhiTrkFwd", "#varphi of forward muons;;#counts", kTH1D, {axisPhiSingle}); + registry.add("hPhiTrkBar", "#varphi of barrel muons;;#counts", kTH1D, {axisPhiSingle}); + + // ZDC + registry.add("hTimeZNA", "ZNA Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hTimeZNC", "ZNC Times;;#counts", kTH1D, {axisTimeZN}); + registry.add("hEnergyZN", "ZNA vs ZNC energy", kTH2D, {axisEnergyZNA, axisEnergyZNC}); + + // neutron classes + reg0n0n.add("hMass", "Invariant mass of mu pairs - 0n0n;;#counts", kTH1D, {axisMass}); + reg0n0n.add("hPt", "Transverse momentum of mu pairs - 0n0n;;#counts", kTH1D, {axisPt}); + reg0n0n.add("hEta", "Pseudorapidity of mu pairs - 0n0n;;#counts", kTH1D, {axisEta}); + reg0n0n.add("hRapidity", "Rapidity of mu pairs - 0n0n;;#counts", kTH1D, {axisRapidity}); + reg0n0n.add("hPtFit", "Transverse momentum of mu pairs - 0n0n;;#counts", kTH1D, {axisPtFit}); + + regXn0n.add("hMass", "Invariant mass of mu pairs - Xn0n;;#counts", kTH1D, {axisMass}); + regXn0n.add("hPt", "Transverse momentum of mu pairs - Xn0n;;#counts", kTH1D, {axisPt}); + regXn0n.add("hEta", "Pseudorapidity of mu pairs - Xn0n;;#counts", kTH1D, {axisEta}); + regXn0n.add("hRapidity", "Rapidity of mu pairs - Xn0n;;#counts", kTH1D, {axisRapidity}); + regXn0n.add("hPtFit", "Transverse momentum of mu pairs - Xn0n;;#counts", kTH1D, {axisPtFit}); + + regXnXn.add("hMass", "Invariant mass of mu pairs - XnXn;;#counts", kTH1D, {axisMass}); + regXnXn.add("hPt", "Transverse momentum of mu pairs - XnXn;;#counts", kTH1D, {axisPt}); + regXnXn.add("hEta", "Pseudorapidity of mu pairs - XnXn;;#counts", kTH1D, {axisEta}); + regXnXn.add("hRapidity", "Rapidity of mu pairs - XnXn;;#counts", kTH1D, {axisRapidity}); + regXnXn.add("hPtFit", "Transverse momentum of mu pairs - XnXn;;#counts", kTH1D, {axisPtFit}); + } + + // FUNCTIONS + using LorentzVec = ROOT::Math::PxPyPzMVector; + + // collect tracks per candidate into a map + template + void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + { + for (const auto& tr : tracks) { + int32_t candId = tr.udCollisionId(); + if (candId < 0) { + continue; + } + tracksPerCand[candId].push_back(tr.globalIndex()); + } + } + + struct ZDCinfo { + float timeA; + float timeC; + float enA; + float enC; + }; + + void collectCandZDCInfo(std::unordered_map& zdcPerCand, o2::aod::UDZdcsReduced const& ZDCs) + { + for (const auto& zdc : ZDCs) { + int32_t candId = zdc.udCollisionId(); + if (candId < 0) { + continue; + } + zdcPerCand[candId].timeA = zdc.timeZNA(); + zdcPerCand[candId].timeC = zdc.timeZNC(); + zdcPerCand[candId].enA = zdc.energyCommonZNA(); + zdcPerCand[candId].enC = zdc.energyCommonZNC(); + + if (std::isinf(zdcPerCand[candId].timeA)) + zdcPerCand[candId].timeA = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].timeC)) + zdcPerCand[candId].timeC = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].enA)) + zdcPerCand[candId].enA = kInvalidFloat; + if (std::isinf(zdcPerCand[candId].enC)) + zdcPerCand[candId].enC = kInvalidFloat; + } + } + + // forward-muon selection (MCH-MID muon, like upcFwdJpsiRl) + template + bool isFwdMuonSelected(const TTrack& fwdTrack) + { + float rAbs = fwdTrack.rAtAbsorberEnd(); + float pDca = fwdTrack.pDca(); + auto mMu = o2::constants::physics::MassMuon; + LorentzVec p(fwdTrack.px(), fwdTrack.py(), fwdTrack.pz(), mMu); + float eta = p.Eta(); + float pt = p.Pt(); + float pDcaMax = rAbs < kRAbsMid ? kPDca1 : kPDca2; + + if (eta < kFwdEtaMin || eta > kFwdEtaMax) + return false; + if (pt < kFwdPtMin) + return false; + if (rAbs < kRAbsMin || rAbs > kRAbsMax) + return false; + if (pDca > pDcaMax) + return false; + if (fwdTrack.chi2MatchMCHMID() <= 0) // require MID match + return false; + return true; + } + + // barrel-muon selection + template + bool isBarrelMuonSelected(const TTrack& barTrack) + { + auto mMu = o2::constants::physics::MassMuon; + LorentzVec p(barTrack.px(), barTrack.py(), barTrack.pz(), mMu); + float eta = p.Eta(); + float pt = p.Pt(); + + if (pt < barPtMin) + return false; + if (eta < barEtaMin || eta > barEtaMax) + return false; + if (barTrack.itsNCls() < static_cast(barMinITSNCls)) + return false; + if (barTrack.tpcNClsCrossedRows() < static_cast(barMinTPCNClsCR)) + return false; + if (std::abs(barTrack.tpcNSigmaMu()) > barMaxTpcNSigmaMu) + return false; + if (barRequireTOF && !barTrack.hasTOF()) + return false; + if (barTrack.hasTOF() && std::abs(barTrack.tofNSigmaMu()) > barMaxTofNSigmaMu) + return false; + return true; + } + + // azimuth anisotropy phi + void computePhiAnis(LorentzVec p1, LorentzVec p2, int sign1, float& phiAverage, float& phiCharge) + { + auto tSum = p1 + p2; + float halfUnity = 0.5; + decltype(tSum) tDiffCh, tDiffAv; + if (sign1 > 0) { + tDiffCh = p1 - p2; + if (gRandom->Rndm() > halfUnity) + tDiffAv = p1 - p2; + else + tDiffAv = p2 - p1; + } else { + tDiffCh = p2 - p1; + if (gRandom->Rndm() > halfUnity) + tDiffAv = p2 - p1; + else + tDiffAv = p1 - p2; + } + phiAverage = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffAv); + phiCharge = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffCh); + } + + // process a single (forward, barrel) pair + void processPair(CandidatesSemiFwd::iterator const& cand, + ForwardTracks::iterator const& fwd, BarrelTracks::iterator const& bar, + ZDCinfo const& zdc) + { + // V0 selection + const auto& ampsV0A = cand.amplitudesV0A(); + const auto& ampsRelBCsV0A = cand.ampRelBCsV0A(); + for (unsigned int i = 0; i < ampsV0A.size(); ++i) { + if (std::abs(ampsRelBCsV0A[i]) <= kMaxRelBCsV0A) { + if (ampsV0A[i] > kMaxAmpV0A) + return; + } + } + + // opposite charge only + int pairCharge = fwd.sign() + bar.sign(); + if (pairCharge != 0) { + registry.fill(HIST("hSameSign"), cand.numContrib()); + return; + } + + // track selection + if (!isFwdMuonSelected(fwd)) + return; + if (!isBarrelMuonSelected(bar)) + return; + + // form Lorentz vectors + auto mMu = o2::constants::physics::MassMuon; + LorentzVec pFwd(fwd.px(), fwd.py(), fwd.pz(), mMu); + LorentzVec pBar(bar.px(), bar.py(), bar.pz(), mMu); + auto p = pFwd + pBar; + + // pair-level cuts + if (p.M() < lowMass || p.M() > highMass) + return; + if (p.Pt() < lowPt || p.Pt() > highPt) + return; + if (p.Rapidity() < lowRapidity || p.Rapidity() > highRapidity) + return; + + // azimuth anisotropy + float phiAverage = 0; + float phiCharge = 0; + computePhiAnis(pFwd, pBar, fwd.sign(), phiAverage, phiCharge); + + // ZDC info histograms + if (std::abs(zdc.timeA) < kMaxZDCTimeHisto) + registry.fill(HIST("hTimeZNA"), zdc.timeA); + if (std::abs(zdc.timeC) < kMaxZDCTimeHisto) + registry.fill(HIST("hTimeZNC"), zdc.timeC); + registry.fill(HIST("hEnergyZN"), zdc.enA, zdc.enC); + + // neutron classes + bool neutronA = std::abs(zdc.timeA) < kMaxZDCTime && !std::isinf(zdc.timeA); + bool neutronC = std::abs(zdc.timeC) < kMaxZDCTime && !std::isinf(zdc.timeC); + int znClass = -1; + + if (!neutronC && !neutronA) { + znClass = 1; + reg0n0n.fill(HIST("hMass"), p.M()); + reg0n0n.fill(HIST("hPt"), p.Pt()); + reg0n0n.fill(HIST("hPtFit"), p.Pt()); + reg0n0n.fill(HIST("hEta"), p.Eta()); + reg0n0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutronA ^ neutronC) { + znClass = neutronA ? 2 : 3; + regXn0n.fill(HIST("hMass"), p.M()); + regXn0n.fill(HIST("hPt"), p.Pt()); + regXn0n.fill(HIST("hPtFit"), p.Pt()); + regXn0n.fill(HIST("hEta"), p.Eta()); + regXn0n.fill(HIST("hRapidity"), p.Rapidity()); + } else if (neutronA && neutronC) { + znClass = 4; + regXnXn.fill(HIST("hMass"), p.M()); + regXnXn.fill(HIST("hPt"), p.Pt()); + regXnXn.fill(HIST("hPtFit"), p.Pt()); + regXnXn.fill(HIST("hEta"), p.Eta()); + regXnXn.fill(HIST("hRapidity"), p.Rapidity()); + } + + // single-track histos by side + registry.fill(HIST("hPtTrkFwd"), pFwd.Pt()); + registry.fill(HIST("hPtTrkBar"), pBar.Pt()); + registry.fill(HIST("hEtaTrkFwd"), pFwd.Eta()); + registry.fill(HIST("hEtaTrkBar"), pBar.Eta()); + registry.fill(HIST("hPhiTrkFwd"), pFwd.Phi()); + registry.fill(HIST("hPhiTrkBar"), pBar.Phi()); + + // pair histos + registry.fill(HIST("hContrib"), cand.numContrib()); + registry.fill(HIST("hEvSign"), cand.netCharge()); + registry.fill(HIST("hMass"), p.M()); + registry.fill(HIST("hPt"), p.Pt()); + registry.fill(HIST("hPtFit"), p.Pt()); + registry.fill(HIST("hEta"), p.Eta()); + registry.fill(HIST("hRapidity"), p.Rapidity()); + registry.fill(HIST("hPhi"), p.Phi()); + registry.fill(HIST("hCharge"), fwd.sign()); + registry.fill(HIST("hCharge"), bar.sign()); + registry.fill(HIST("hPhiAverage"), phiAverage); + registry.fill(HIST("hPhiCharge"), phiCharge); + + // assign positive/negative leg + bool fwdIsPos = fwd.sign() > 0; + const LorentzVec& pPos = fwdIsPos ? pFwd : pBar; + const LorentzVec& pNeg = fwdIsPos ? pBar : pFwd; + int isFwdPos = fwdIsPos ? 1 : 0; + int isFwdNeg = fwdIsPos ? 0 : 1; + + dimuSel(cand.runNumber(), + p.M(), p.E(), p.Px(), p.Py(), p.Pz(), p.Pt(), p.Rapidity(), p.Phi(), + phiAverage, phiCharge, + pPos.E(), pPos.Px(), pPos.Py(), pPos.Pz(), pPos.Pt(), pPos.Eta(), pPos.Phi(), isFwdPos, + pNeg.E(), pNeg.Px(), pNeg.Py(), pNeg.Pz(), pNeg.Pt(), pNeg.Eta(), pNeg.Phi(), isFwdNeg, + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + } + + // PROCESS FUNCTION + void processData(CandidatesSemiFwd const& eventCandidates, + o2::aod::UDZdcsReduced const& ZDCs, + ForwardTracks const& fwdTracks, + BarrelTracks const& barrelTracks) + { + std::unordered_map> fwdTracksPerCand; + collectCandIDs(fwdTracksPerCand, fwdTracks); + + std::unordered_map> barTracksPerCand; + collectCandIDs(barTracksPerCand, barrelTracks); + + std::unordered_map zdcPerCand; + collectCandZDCInfo(zdcPerCand, ZDCs); + + // loop over candidates that have at least one forward track + for (const auto& [candID, fwdIds] : fwdTracksPerCand) { + auto itBar = barTracksPerCand.find(candID); + if (itBar == barTracksPerCand.end()) + continue; // need at least one barrel companion + const auto& barIds = itBar->second; + auto cand = eventCandidates.iteratorAt(candID); + + ZDCinfo zdc; + auto itZdc = zdcPerCand.find(candID); + if (itZdc != zdcPerCand.end()) { + zdc = itZdc->second; + } else { + zdc.timeA = kInvalidFloat; + zdc.timeC = kInvalidFloat; + zdc.enA = kInvalidFloat; + zdc.enC = kInvalidFloat; + } + + for (const auto& fwdIdx : fwdIds) { + for (const auto& barIdx : barIds) { + auto fwd = fwdTracks.iteratorAt(fwdIdx); + auto bar = barrelTracks.iteratorAt(barIdx); + processPair(cand, fwd, bar, zdc); + } + } + } + } + + PROCESS_SWITCH(UpcSemiFwdJpsiRl, processData, "Process semi-forward J/psi candidates", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 7d1e7c86fff94dfea6ba26530e8f047869cc421e Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Sun, 10 May 2026 20:01:10 +0800 Subject: [PATCH 116/449] [PWGUD] flow UPC analyses hot fixes (#16175) --- PWGUD/Tasks/flowCumulantsUpc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/Tasks/flowCumulantsUpc.cxx b/PWGUD/Tasks/flowCumulantsUpc.cxx index 0a85386e44c..eff14256879 100644 --- a/PWGUD/Tasks/flowCumulantsUpc.cxx +++ b/PWGUD/Tasks/flowCumulantsUpc.cxx @@ -78,7 +78,7 @@ struct FlowCumulantsUpc { O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum number of crossed TPC Rows") O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum number of found TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum number of ITS clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCChi2NCl, int, 4, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCChi2NCl, float, 4.0f, "max chi2 per TPC clusters") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 30, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRefPt, bool, false, "NUA weights are filled in ref pt bins") From 3f269bdeeacbeead7a75f9c90e0fcd628a79aae3 Mon Sep 17 00:00:00 2001 From: Antonio Palasciano <52152842+apalasciano@users.noreply.github.com> Date: Sun, 10 May 2026 16:03:45 +0200 Subject: [PATCH 117/449] [PWGHF] Hist missing declaration in DpH correlator (#16182) --- PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index 44cd05527b7..e5c3c8d57e0 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -254,6 +254,7 @@ struct HfCorrelatorDplusHadrons { ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 6000.}, "Multiplicity as FT0M signal amplitude"}; ConfigurableAxis binsMassD{"binsMassD", {200, 1.7, 2.10}, "inv. mass (#pi^{+}K^{-}#pi^{+}) (GeV/#it{c}^{2})"}; + ConfigurableAxis binsDcaXY{"binsDcaXY", {128, -0.2, 0.2}, "DCA xy"}; BinningType corrBinning{{binsZVtx, binsMultiplicity}, true}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -271,6 +272,7 @@ struct HfCorrelatorDplusHadrons { AxisSpec const axisPoolBin = {binsPoolBin, "PoolBin"}; AxisSpec const axisStatus = {15, 0.5, 15.5, "Selection status"}; AxisSpec const axisRapidity = {100, -2, 2, "Rapidity"}; + AxisSpec const axisDcaXY = {binsDcaXY, "DCA xy"}; registry.add("hPtCand", "Dplus,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); registry.add("hPtProng0", "Dplus,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtD}}); @@ -291,6 +293,7 @@ struct HfCorrelatorDplusHadrons { registry.add("hMassDplusData", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisMassD}}}); registry.add("hDplusPoolBin", "D+ candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); + registry.add("hDcaXYVsPt", "DCA xy vs pt", {HistType::kTH2F, {{axisDcaXY}, {axisPtHadron}}}); // Histograms for MC Reco analysis registry.add("hSelectionStatusMCRec", "Dplus,Hadron candidates - MC reco;selection status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}); registry.add("hMCEvtCount", "Event counter - MC gen;;entries", {HistType::kTH1F, {{1, -0.5, 0.5}}}); From a31b4bbb1a01995d53f2100e2a5b07bcbe73bcb5 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 10 May 2026 17:07:33 +0200 Subject: [PATCH 118/449] [PWGEM/Dilepton] improve V0 selection in taggingHFE (#16184) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 15 +- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 678 +++++++++++++++++++++--- 2 files changed, 600 insertions(+), 93 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 149333eb33a..e8eb1a58458 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -220,7 +220,10 @@ DECLARE_SOA_COLUMN(RapidityV0, rapidityV0, float); //! rapidity of associated V0 DECLARE_SOA_COLUMN(RapidityC, rapidityC, float); //! rapidity of associated Cascade DECLARE_SOA_COLUMN(ImpParXY, impParXY, float); //! impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParXYErr, impParXYErr, float); //! sigma of impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParZ, impParZ, float); //! impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParCYY, impParCYY, float); //! sigma of impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParCZY, impParCZY, float); //! sigma of impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParCZZ, impParCZZ, float); //! sigma of impact parameter for V0/Cascade in XY plane DECLARE_SOA_COLUMN(V0CosPA, v0copa, float); //! cosPA of V0 DECLARE_SOA_COLUMN(V0CosPAXY, v0copaXY, float); //! cosPA of V0 in XY plane @@ -263,24 +266,26 @@ using EMMLLHPair = EMMLLHPairs::iterator; DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::EMMLLeptonId, track::Pt, emmllhpair::RapidityV0, - emmllhpair::V0CosPA, emmllhpair::V0CosPAXY, emmllhpair::ImpParXY, emmllhpair::ImpParXYErr, + emmllhpair::V0CosPA, emmllhpair::V0CosPAXY, + emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, emmllhpair::Lxyz, emmllhpair::LxyzSigma, emmllhpair::Lxy, emmllhpair::LxySigma, emmllhpair::Lz, emmllhpair::LzSigma, - emmllhpair::PdgCodeH, emmllhpair::FoundCommonMother); + emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLV0Pair = EMMLLV0Pairs::iterator; DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCAPAIR", //! emmllhpair::EMMLLeptonId, track::Pt, emmllhpair::RapidityC, - emmllhpair::CascCosPA, emmllhpair::CascCosPAXY, emmllhpair::ImpParXY, emmllhpair::ImpParXYErr, + emmllhpair::CascCosPA, emmllhpair::CascCosPAXY, + emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, emmllhpair::Lxyz, emmllhpair::LxyzSigma, emmllhpair::Lxy, emmllhpair::LxySigma, emmllhpair::Lz, emmllhpair::LzSigma, - emmllhpair::PdgCodeH, emmllhpair::FoundCommonMother); + emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLCascPair = EMMLLCascPairs::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index cc144ec335d..4306fcf48b3 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -72,6 +72,9 @@ using namespace o2::constants::physics; using namespace o2::aod::pwgem::dilepton::utils::mcutil; struct taggingHFE { + using MyBCs = soa::Join; + using MyBC = MyBCs::iterator; + using MyCollisions = soa::Join; using MyCollisionsWithMCLabel = soa::Join; @@ -101,6 +104,7 @@ struct taggingHFE { Configurable cfgPdgLepton{"cfgPdgLepton", 11, "pdg code of desired lepton: 11 or 13"}; Configurable cfgDownSampling{"cfgDownSampling", 1.1, "down sampling for wrongly found SV"}; Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", true, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; + Configurable cfgApplyBCShiftTOF{"cfgApplyBCShiftTOF", true, "apply bc shift for TOF n sigma of track from v0 or cascade"}; struct : ConfigurableGroup { std::string prefix = "dcaFitterGroup_eK"; @@ -176,12 +180,14 @@ struct taggingHFE { struct : ConfigurableGroup { std::string prefix = "v0Cut"; - Configurable cfg_min_mass_k0s{"cfg_min_mass_k0s", 0.49, "min mass for K0S"}; + Configurable cfg_min_mass_k0s{"cfg_min_mass_k0s", 0.48, "min mass for K0S"}; Configurable cfg_max_mass_k0s{"cfg_max_mass_k0s", 0.51, "max mass for K0S"}; - Configurable cfg_min_mass_k0s_veto{"cfg_min_mass_k0s_veto", 0.47, "min mass for K0S veto for Lambda"}; - Configurable cfg_max_mass_k0s_veto{"cfg_max_mass_k0s_veto", 0.52, "max mass for K0S veto for Lambda"}; - Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.113, "min mass for Lambda"}; - Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.118, "max mass for Lambda"}; + Configurable cfg_min_mass_k0s_veto{"cfg_min_mass_k0s_veto", 0.48, "min mass for K0S veto for Lambda"}; + Configurable cfg_max_mass_k0s_veto{"cfg_max_mass_k0s_veto", 0.51, "max mass for K0S veto for Lambda"}; + Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for Lambda"}; + Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for Lambda"}; + Configurable cfg_min_mass_lambda_veto{"cfg_min_mass_lambda_veto", 1.11, "min mass for Lambda veto for K0S"}; + Configurable cfg_max_mass_lambda_veto{"cfg_max_mass_lambda_veto", 1.12, "max mass for Lambda veto for K0S"}; Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "min cospa for v0"}; Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 0.1, "max distance between 2 legs for v0"}; // Configurable cfg_min_radius{"cfg_min_radius", 0.1, "min rxy for v"}; @@ -195,14 +201,23 @@ struct taggingHFE { Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; Configurable cfg_min_dcaxy{"cfg_min_dcaxy", 0.1, "min dca XY for v0 legs in cm"}; + Configurable cfg_max_alpha_veto{"cfg_max_alpha_veto", 0.95, "max alpha for photon conversion rejection"}; + Configurable cfg_max_qt_veto{"cfg_max_qt_veto", 0.01, "max qT for photon conversion rejection"}; + + // for both v0 and cascade Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3, "min n sigma pi in TPC"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3, "max n sigma pi in TPC"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3, "min n sigma ka in TPC"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; + Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; + Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + Configurable applyTOFif{"applyTOFif", false, "apply TOFif for hadron identification"}; } v0Cut; struct : ConfigurableGroup { @@ -352,7 +367,8 @@ struct taggingHFE { o2::dataformats::DCA mDcaInfoCov; o2::dataformats::VertexBase mVtx; - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + template + void initCCDB(TBC const& bc) { if (mRunNumber == bc.runNumber()) { return; @@ -447,6 +463,10 @@ struct taggingHFE { fRegistry.add("V0/hMassK0S", "K0S mass;m_{#pi#pi} (GeV/c^{2})", kTH1F, {{100, 0.45, 0.55}}, false); fRegistry.add("V0/hMassLambda", "Lambda mass;m_{p#pi^{#minus}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); fRegistry.add("V0/hMassAntiLambda", "Anti-Lambda mass;m_{#bar{p}#pi^{+}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); + fRegistry.add("V0/hMassGamma_misid", "#gamma mass;m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); + fRegistry.add("V0/hMassK0S_misid", "K0S mass;m_{#pi#pi} (GeV/c^{2})", kTH1F, {{100, 0.45, 0.55}}, false); + fRegistry.add("V0/hMassLambda_misid", "Lambda mass;m_{p#pi^{#minus}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); + fRegistry.add("V0/hMassAntiLambda_misid", "Anti-Lambda mass;m_{#bar{p}#pi^{+}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); // for cascade fRegistry.add("Cascade/hPt", "pT of V0;p_{T} (GeV/c)", kTH1F, {{100, 0, 10}}, false); @@ -458,6 +478,8 @@ struct taggingHFE { fRegistry.add("Cascade/hMassLambda", "Lambda mass;m_{p#pi^{-}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); fRegistry.add("Cascade/hMassXi", "#Xi mass;m_{#Lambda#pi} (GeV/c^{2})", kTH1F, {{100, 1.27, 1.37}}, false); fRegistry.add("Cascade/hMassOmega", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", kTH1F, {{100, 1.62, 1.72}}, false); + fRegistry.add("Cascade/hMassXi_misid", "#Xi mass;m_{#Lambda#pi} (GeV/c^{2})", kTH1F, {{100, 1.27, 1.37}}, false); + fRegistry.add("Cascade/hMassOmega_misid", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", kTH1F, {{100, 1.62, 1.72}}, false); } template @@ -480,32 +502,114 @@ struct taggingHFE { return (is_pi_included_TPC && is_pi_included_TOF) || (is_ka_included_TPC && is_ka_included_TOF) || (is_pr_included_TPC && is_pr_included_TOF); } - template - bool isPion(TTrack const& track) + template + bool isPionFromK0S(TCollision const& collision, TTrack const& track) { - // TOFif + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)]; bool is_pi_included_TPC = v0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0Cut.cfg_max_TPCNsigmaPi; - bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < v0Cut.cfg_max_TOFNsigmaPi) : true; + bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0Cut.cfg_max_TOFNsigmaPi) : true; + if (!v0Cut.applyTOFif) { + is_pi_included_TOF = true; + } return is_pi_included_TPC && is_pi_included_TOF; } - template - bool isKaon(TTrack const& track) + template + bool isPionFromLambda(TCollision const& collision, TTrack const& track) { - bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; - bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < hadronCut.cfg_max_TOFNsigmaKa) : true; - return is_ka_included_TPC && is_ka_included_TOF; + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)]; + bool is_pi_included_TPC = v0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0Cut.cfg_max_TPCNsigmaPi; + bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0Cut.cfg_max_TOFNsigmaPi) : true; + if (!v0Cut.applyTOFif) { + is_pi_included_TOF = true; + } + return is_pi_included_TPC && is_pi_included_TOF; + } + + template + bool isProtonFromLambda(TCollision const& collision, TTrack const& track) + { + float tofNSigmaPr = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)]; + bool is_pr_included_TPC = v0Cut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < v0Cut.cfg_max_TPCNsigmaPr; + bool is_pr_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < v0Cut.cfg_max_TOFNsigmaPr) : true; + if (!v0Cut.applyTOFif) { + is_pr_included_TOF = true; + } + return is_pr_included_TPC && is_pr_included_TOF; + } + + template + bool isPionFromLambdaFromXi(TCollision const& collision, TTrack const& track) + { + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)]; + bool is_pi_included_TPC = v0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0Cut.cfg_max_TPCNsigmaPi; + bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0Cut.cfg_max_TOFNsigmaPi) : true; + if (!v0Cut.applyTOFif) { + is_pi_included_TOF = true; + } + return is_pi_included_TPC && is_pi_included_TOF; + } + + template + bool isPionFromLambdaFromOmega(TCollision const& collision, TTrack const& track) + { + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)]; + bool is_pi_included_TPC = v0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0Cut.cfg_max_TPCNsigmaPi; + bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0Cut.cfg_max_TOFNsigmaPi) : true; + if (!v0Cut.applyTOFif) { + is_pi_included_TOF = true; + } + return is_pi_included_TPC && is_pi_included_TOF; + } + + template + bool isProtonFromLambdaFromXi(TCollision const& collision, TTrack const& track) + { + float tofNSigmaPr = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)]; + bool is_pr_included_TPC = v0Cut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < v0Cut.cfg_max_TPCNsigmaPr; + bool is_pr_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < v0Cut.cfg_max_TOFNsigmaPr) : true; + if (!v0Cut.applyTOFif) { + is_pr_included_TOF = true; + } + return is_pr_included_TPC && is_pr_included_TOF; } - template - bool isProton(TTrack const& track) + template + bool isProtonFromLambdaFromOmega(TCollision const& collision, TTrack const& track) { - // TOFif + float tofNSigmaPr = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)]; bool is_pr_included_TPC = v0Cut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < v0Cut.cfg_max_TPCNsigmaPr; - bool is_pr_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPr < track.tofNSigmaPr() && track.tofNSigmaPr() < v0Cut.cfg_max_TOFNsigmaPr) : true; + bool is_pr_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < v0Cut.cfg_max_TOFNsigmaPr) : true; + if (!v0Cut.applyTOFif) { + is_pr_included_TOF = true; + } return is_pr_included_TPC && is_pr_included_TOF; } + template + bool isPionFromXi(TCollision const& collision, TTrack const& track) + { + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)]; + bool is_pi_included_TPC = v0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0Cut.cfg_max_TPCNsigmaPi; + bool is_pi_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0Cut.cfg_max_TOFNsigmaPi) : true; + if (!v0Cut.applyTOFif) { + is_pi_included_TOF = true; + } + return is_pi_included_TPC && is_pi_included_TOF; + } + + template + bool isKaonFromOmega(TCollision const& collision, TTrack const& track) + { + float tofNSigmaKa = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)]; + bool is_ka_included_TPC = v0Cut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < v0Cut.cfg_max_TPCNsigmaKa; + bool is_ka_included_TOF = track.hasTOF() ? (v0Cut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < v0Cut.cfg_max_TOFNsigmaKa) : true; + if (!v0Cut.applyTOFif) { + is_ka_included_TOF = true; + } + return is_ka_included_TPC && is_ka_included_TOF; + } + // template // bool isElectron(TTrack const& track) // { @@ -642,7 +746,7 @@ struct taggingHFE { template bool isK0S(TV0 const& v0) { - return (v0Cut.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0Cut.cfg_max_mass_k0s); + return (v0Cut.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0Cut.cfg_max_mass_k0s) && (v0.mLambda() < v0Cut.cfg_min_mass_lambda_veto || v0Cut.cfg_max_mass_lambda_veto < v0.mLambda()) && (v0.mAntiLambda() < v0Cut.cfg_min_mass_lambda_veto || v0Cut.cfg_max_mass_lambda_veto < v0.mAntiLambda()); } template @@ -669,7 +773,7 @@ struct taggingHFE { return (cascadeCut.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < cascadeCut.cfg_max_mass_Omega) && (cascade.mXi() < cascadeCut.cfg_min_mass_Xi_veto || cascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()); } - template + template bool isSelectedV0Leg(TTrack const& track) { if constexpr (isMC) { @@ -731,8 +835,8 @@ struct taggingHFE { fRegistry.fill(HIST("Event/hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); } - template - void fillV0Histograms(TV0 const& v0) + template + void fillV0Histograms(TCollision const& collision, TV0 const& v0) { auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); @@ -743,21 +847,39 @@ struct taggingHFE { fRegistry.fill(HIST("V0/hLxy"), v0.v0radius()); fRegistry.fill(HIST("V0/hDCA2Legs"), v0.dcaV0daughters()); - if (isPion(pos) && isPion(neg)) { - fRegistry.fill(HIST("V0/hMassK0S"), v0.mK0Short()); + if (isPionFromK0S(collision, pos) && isPionFromK0S(collision, neg)) { + if ((v0.mLambda() < v0Cut.cfg_min_mass_lambda_veto || v0Cut.cfg_max_mass_lambda_veto < v0.mLambda()) && (v0.mAntiLambda() < v0Cut.cfg_min_mass_lambda_veto || v0Cut.cfg_max_mass_lambda_veto < v0.mAntiLambda())) { + fRegistry.fill(HIST("V0/hMassK0S"), v0.mK0Short()); + } + fRegistry.fill(HIST("V0/hMassGamma_misid"), v0.mGamma()); + fRegistry.fill(HIST("V0/hMassLambda_misid"), v0.mLambda()); + fRegistry.fill(HIST("V0/hMassAntiLambda_misid"), v0.mAntiLambda()); } - if (isProton(pos) && isPion(neg)) { - fRegistry.fill(HIST("V0/hMassLambda"), v0.mLambda()); + + if (isProtonFromLambda(collision, pos) && isPionFromLambda(collision, neg)) { + if (v0.mK0Short() < v0Cut.cfg_min_mass_k0s_veto || v0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()) { + fRegistry.fill(HIST("V0/hMassLambda"), v0.mLambda()); + } + fRegistry.fill(HIST("V0/hMassGamma_misid"), v0.mGamma()); + fRegistry.fill(HIST("V0/hMassK0S_misid"), v0.mK0Short()); } - if (isProton(neg) && isPion(pos)) { - fRegistry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); + + if (isProtonFromLambda(collision, neg) && isPionFromLambda(collision, pos)) { + if (v0.mK0Short() < v0Cut.cfg_min_mass_k0s_veto || v0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()) { + fRegistry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); + } + fRegistry.fill(HIST("V0/hMassGamma_misid"), v0.mGamma()); + fRegistry.fill(HIST("V0/hMassK0S_misid"), v0.mK0Short()); } } template void fillCascadeHistograms(TCollision const& collision, TCascade const& cascade) { + auto pos = cascade.template posTrack_as(); + auto neg = cascade.template negTrack_as(); auto bachelor = cascade.template bachelor_as(); + fRegistry.fill(HIST("Cascade/hPt"), cascade.pt()); fRegistry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); fRegistry.fill(HIST("Cascade/hCosPA"), cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ())); @@ -765,11 +887,32 @@ struct taggingHFE { fRegistry.fill(HIST("Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); fRegistry.fill(HIST("Cascade/hV0DCA2Legs"), cascade.dcaV0daughters()); - if (isPion(bachelor)) { - fRegistry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); - } - if (isKaon(bachelor)) { - fRegistry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); + if (cascade.sign() < 0) { // Xi- or Omega- + if (isPionFromXi(collision, bachelor) && isProtonFromLambdaFromXi(collision, pos) && isPionFromLambdaFromXi(collision, neg)) { + if (cascade.mOmega() < cascadeCut.cfg_min_mass_Omega_veto || cascadeCut.cfg_max_mass_Omega_veto < cascade.mOmega()) { + fRegistry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); + } + fRegistry.fill(HIST("Cascade/hMassOmega_misid"), cascade.mOmega()); + } + if (isKaonFromOmega(collision, bachelor) && isProtonFromLambdaFromOmega(collision, pos) && isPionFromLambdaFromOmega(collision, neg)) { + if (cascade.mXi() < cascadeCut.cfg_min_mass_Xi_veto || cascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()) { + fRegistry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); + } + fRegistry.fill(HIST("Cascade/hMassXi_misid"), cascade.mXi()); + } + } else { // Xi+ or Omega+ + if (isPionFromXi(collision, bachelor) && isProtonFromLambdaFromXi(collision, neg) && isPionFromLambdaFromXi(collision, pos)) { + if (cascade.mOmega() < cascadeCut.cfg_min_mass_Omega_veto || cascadeCut.cfg_max_mass_Omega_veto < cascade.mOmega()) { + fRegistry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); + } + fRegistry.fill(HIST("Cascade/hMassOmega_misid"), cascade.mOmega()); + } + if (isKaonFromOmega(collision, bachelor) && isProtonFromLambdaFromOmega(collision, neg) && isPionFromLambdaFromOmega(collision, pos)) { + if (cascade.mXi() < cascadeCut.cfg_min_mass_Xi_veto || cascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()) { + fRegistry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); + } + fRegistry.fill(HIST("Cascade/hMassXi_misid"), cascade.mXi()); + } } } @@ -871,6 +1014,354 @@ struct taggingHFE { return true; } + std::map, float> mapTOFNSigma; // map -> tof n sigma + std::map, float> mapTOFBeta; // map -> tof beta + + template + float recalculateTOFNSigmaTrackFromV0FromCascade(TCollision const& collision, TCascade const& cascade, const float massCascade, float& beta) + { + if (mapCollisionTime.find(cascade.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto track = sign > 0 ? cascade.template posTrack_as() : cascade.template negTrack_as(); + auto arrMomTrack = sign > 0 ? std::array{cascade.pxpos(), cascade.pypos(), cascade.pzpos()} : std::array{cascade.pxneg(), cascade.pyneg(), cascade.pzneg()}; + + if (!track.hasTOF() || !track.has_collision()) { + beta = -1.f; + return -999.f; + } + auto bcCascade = collision.template bc_as(); // collision in this function is the collision where this cascade belong. + + o2::track::TrackPar trackPar = o2::track::TrackPar({cascade.xlambda(), cascade.ylambda(), cascade.zlambda()}, arrMomTrack, sign, false); + auto collisionTrack = track.template collision_as(); + auto bcTrack = collisionTrack.template bc_as(); + double deltaTime = track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCascade.globalBC()) - timeCascade(collision, cascade, massCascade) - timeV0inCascade(cascade); // in ps + + const o2::math_utils::Point3D trackVertex{collisionTrack.posX(), collisionTrack.posY(), collisionTrack.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, trackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = track.length() - ltIntegral.getL(); + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + + beta = length / (deltaTime - mapCollisionTime[cascade.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, track.tofExpMom(), length, trackPar.getP(), trackPar.getEta(), mapCollisionTime[cascade.collisionId()], mapCollisionTimeError[cascade.collisionId()]); + } + + template + float recalculateTOFNSigmaBachelorFromCascade(TCollision const& collision, TCascade const& cascade, const float massCascade, float& beta) + { + if (mapCollisionTime.find(cascade.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto bachelor = cascade.template bachelor_as(); + if (!bachelor.hasTOF() || !bachelor.has_collision()) { + beta = -1.f; + return -999.f; + } + + auto bcCascade = collision.template bc_as(); // collision in this function is the collision where this cascade belong. + auto collisionBachelor = bachelor.template collision_as(); + auto bcBachelor = collisionBachelor.template bc_as(); + double deltaTime = bachelor.tofSignalInAnotherBC(bcBachelor.globalBC(), bcCascade.globalBC()) - timeCascade(collision, cascade, massCascade); // in ps + + o2::track::TrackPar bTrackPar = o2::track::TrackPar({cascade.x(), cascade.y(), cascade.z()}, {cascade.pxbach(), cascade.pybach(), cascade.pzbach()}, cascade.sign(), false); // at SV + const o2::math_utils::Point3D trackVertex{collisionBachelor.posX(), collisionBachelor.posY(), collisionBachelor.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, bTrackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = bachelor.length() - ltIntegral.getL(); + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + + beta = length / (deltaTime - mapCollisionTime[cascade.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, bachelor.tofExpMom(), length, bTrackPar.getP(), bTrackPar.getEta(), mapCollisionTime[cascade.collisionId()], mapCollisionTimeError[cascade.collisionId()]); + } + + template + float recalculateTOFNSigmaLegFromV0(TCollision const& collision, TV0 const& v0, const float massV0, float& beta) + { + if (mapCollisionTime.find(v0.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto track = sign > 0 ? v0.template posTrack_as() : v0.template negTrack_as(); + if (!track.hasTOF() || !track.has_collision()) { + beta = -1.f; + return -999.f; + } + + auto bcV0 = collision.template bc_as(); // collision in this function is the collision where this v0 belong. + auto arrMomTrack = sign > 0 ? std::array{v0.pxpos(), v0.pypos(), v0.pzpos()} : std::array{v0.pxneg(), v0.pyneg(), v0.pzneg()}; + + auto collisionTrack = track.template collision_as(); + auto bcTrack = collisionTrack.template bc_as(); + double deltaTime = track.tofSignalInAnotherBC(bcTrack.globalBC(), bcV0.globalBC()) - timeV0(collision, v0, massV0); // in ps + + o2::track::TrackPar trackPar = o2::track::TrackPar({v0.x(), v0.y(), v0.z()}, arrMomTrack, track.sign(), false); // at SV + const o2::math_utils::Point3D trackVertex{collisionTrack.posX(), collisionTrack.posY(), collisionTrack.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, trackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = track.length() - ltIntegral.getL(); // in cm + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + beta = length / (deltaTime - mapCollisionTime[v0.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, track.tofExpMom(), length, trackPar.getP(), trackPar.getEta(), mapCollisionTime[v0.collisionId()], mapCollisionTimeError[v0.collisionId()]); + } + + template + float timeV0inCascade(TCascade const& cascade) + { + float p = RecoDecay::sqrtSumOfSquares(cascade.pxlambda(), cascade.pylambda(), cascade.pzlambda()); + float length = std::hypot(cascade.xlambda() - cascade.x(), cascade.ylambda() - cascade.y(), cascade.zlambda() - cascade.z()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((p * p) / (p * p + o2::constants::physics::MassLambda * o2::constants::physics::MassLambda)); // cm/ps + return length / velocity; // ps + } + + template + float timeCascade(TCollision const& collision, TCascade const& cascade, const float massCascade) + { + float length = std::hypot(cascade.x() - collision.posX(), cascade.y() - collision.posY(), cascade.z() - collision.posZ()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((cascade.p() * cascade.p()) / (cascade.p() * cascade.p() + massCascade * massCascade)); // cm/ps + return length / velocity; // ps + } + + template + float timeV0(TCollision const& collision, TV0 const& v0, const float massV0) + { + float length = std::hypot(v0.x() - collision.posX(), v0.y() - collision.posY(), v0.z() - collision.posZ()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((v0.p() * v0.p()) / (v0.p() * v0.p() + massV0 * massV0)); // cm/ps + return length / velocity; // ps + } + + template + void calculateTOFNSigmasForV0sAndCascades(TCollisions const& collisions, TBCs const&, TV0s const& v0s, TCascades const& cascades, TTracks const& tracks) + { + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } // end of track loop + + for (const auto& collision : collisions) { + if (!isSelectedCollision(collision)) { + continue; + } + if (eventCut.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + + auto v0s_coll = v0s.sliceBy(perCol_v0, collision.globalIndex()); + for (const auto& v0 : v0s_coll) { + auto pos = v0.template posTrack_as(); + auto neg = v0.template negTrack_as(); + + if (v0.dcaV0daughters() > v0Cut.cfg_max_dca2legs) { + continue; + } + if (v0.v0cosPA() < v0Cut.cfg_min_cospa) { + continue; + } + if (pos.sign() * neg.sign() > 0) { + continue; + } + if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { + continue; + } + + float beta = -1.f; + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + } // end of v0 loop + + auto cascades_coll = cascades.sliceBy(perCol_casc, collision.globalIndex()); + for (const auto& cascade : cascades_coll) { + // Track casting + auto bachelor = cascade.template bachelor_as(); + auto pos = cascade.template posTrack_as(); + auto neg = cascade.template negTrack_as(); + if (pos.sign() * neg.sign() > 0) { + continue; + } + + if (!(cascadeCut.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < cascadeCut.cfg_max_mass_lambda)) { + continue; + } + + if (cascade.cascradius() > cascade.v0radius()) { + continue; + } + + if (cascade.dcaV0daughters() > cascadeCut.cfg_max_dcadau_v0) { + continue; + } + if (cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_cospa_v0) { + continue; + } + if (cascade.v0radius() < cascadeCut.cfg_min_rxy_v0) { + continue; + } + + if (cascade.cascradius() < cascadeCut.cfg_min_rxy) { + continue; + } + + if (cascade.dcacascdaughters() > cascadeCut.cfg_max_dcadau) { + continue; + } + if (cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_cospa) { + continue; + } + + if (cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_dcaxy_v0) { + continue; + } + + if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg) || !isSelectedV0Leg(bachelor)) { + continue; + } + + // for bachelor tracks + float beta = -1.f; + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + + // for tracks from lambda from cascade + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + } // end of cascade loop + } // end of collision loop + } + std::map, float> mapTOFNsigmaPiReassociated; // map pair(collisionId, trackId) -> tof n sigma pi std::map, float> mapTOFNsigmaKaReassociated; // map pair(collisionId, trackId) -> tof n sigma ka std::map, float> mapTOFNsigmaPrReassociated; // map pair(collisionId, trackId) -> tof n sigma pr @@ -1067,15 +1558,20 @@ struct taggingHFE { if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { continue; } - fillV0Histograms<>(v0); - if (isK0S(v0) && isPion(pos) && isPion(neg)) { + fillV0Histograms(collision, v0); + + if (std::sqrt(std::pow(v0.alpha() / v0Cut.cfg_max_alpha_veto, 2) + std::pow(v0.qtarm() / v0Cut.cfg_max_qt_veto, 2)) < 1.f) { // photon conversion rejection at small qT + continue; + } + + if (isK0S(v0) && isPionFromK0S(collision, pos) && isPionFromK0S(collision, neg)) { k0Ids.emplace_back(v0.globalIndex()); } - if (isLambda(v0) && isProton(pos) && isPion(neg)) { + if (isLambda(v0) && isProtonFromLambda(collision, pos) && isPionFromLambda(collision, neg)) { lambdaIds.emplace_back(v0.globalIndex()); - } else if (isAntiLambda(v0) && isProton(neg) && isPion(pos)) { + } else if (isAntiLambda(v0) && isProtonFromLambda(collision, neg) && isPionFromLambda(collision, pos)) { antilambdaIds.emplace_back(v0.globalIndex()); } } // end of V0 loop @@ -1104,16 +1600,6 @@ struct taggingHFE { continue; } - if (cascade.sign() < 0) { // L-> p pi- - if (!isProton(pos) || !isPion(neg)) { - continue; - } - } else { // Lbar-> pbar pi+ - if (!isProton(neg) || !isPion(pos)) { - continue; - } - } - if (cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_cospa) { continue; } @@ -1122,18 +1608,19 @@ struct taggingHFE { } fillCascadeHistograms(collision, cascade); + if (cascade.sign() < 0) { // Xi- or Omega- - if (isXi(cascade) && isPion(bachelor)) { + if (isXi(cascade) && isPionFromXi(collision, bachelor) && isProtonFromLambdaFromXi(collision, pos) && isPionFromLambdaFromXi(collision, neg)) { xiMinusIds.emplace_back(cascade.globalIndex()); } - if (isOmega(cascade) && isKaon(bachelor)) { + if (isOmega(cascade) && isKaonFromOmega(collision, bachelor) && isProtonFromLambdaFromOmega(collision, pos) && isPionFromLambdaFromOmega(collision, neg)) { omegaMinusIds.emplace_back(cascade.globalIndex()); } } else { // Xi+ or Omega+ - if (isXi(cascade) && isPion(bachelor)) { + if (isXi(cascade) && isPionFromXi(collision, bachelor) && isProtonFromLambdaFromXi(collision, neg) && isPionFromLambdaFromXi(collision, pos)) { xiPlusIds.emplace_back(cascade.globalIndex()); } - if (isOmega(cascade) && isKaon(bachelor)) { + if (isOmega(cascade) && isKaonFromOmega(collision, bachelor) && isProtonFromLambdaFromOmega(collision, neg) && isPionFromLambdaFromOmega(collision, pos)) { omegaPlusIds.emplace_back(cascade.globalIndex()); } } @@ -1153,11 +1640,11 @@ struct taggingHFE { bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; auto mcCollision = mcpos.template mcCollision_as(); - bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. - bool is_e_from_prompt_jpsi = std::abs(mcMother.pdgCode()) == 443 && !isMotherFromB && std::abs(mcMother.pdgCode()) != 100443; + bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. + bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; // e from prompt J/psi is treated as the same as Z. // e from nonprompt J/psi is treated as the same as B. bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, -cfgPdgLepton, cfgPdgLepton + 1); - if (!(is_e_from_dy || is_e_from_prompt_jpsi || is_e_from_hc || is_e_from_hb)) { + if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { continue; } @@ -1202,7 +1689,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1266,7 +1753,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1332,6 +1819,7 @@ struct taggingHFE { int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcK0SId > 0) { // true K0S pdgCodeV0 = 310; auto mcK0S = mcParticles.rawIteratorAt(mcK0SId); @@ -1348,12 +1836,13 @@ struct taggingHFE { int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcMother_of_k0s); if (commonMotherId > 0) { foundCommonMother = true; + pdgCodeIM = mcMother_of_k0s.pdgCode(); } } } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1361,12 +1850,12 @@ struct taggingHFE { v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), - impactParameterV0.getY(), std::sqrt(impactParameterV0.getSigmaY2()), + impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.lxyz, eV0pair.lxyzErr, eV0pair.lxy, eV0pair.lxyErr, eV0pair.lz, eV0pair.lzErr, - pdgCodeV0, foundCommonMother); + pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -1407,13 +1896,14 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true v0 auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); pdgCodeV0 = mcLambda.pdgCode(); foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcpos, mcLambda) > 0; } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1421,12 +1911,12 @@ struct taggingHFE { v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), - impactParameterV0.getY(), std::sqrt(impactParameterV0.getSigmaY2()), + impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.lxyz, eV0pair.lxyzErr, eV0pair.lxy, eV0pair.lxyErr, eV0pair.lz, eV0pair.lzErr, - pdgCodeV0, foundCommonMother); + pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Lambda loop @@ -1468,6 +1958,7 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcXiId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, 3122, -211, 3312, mcParticles); @@ -1478,7 +1969,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1486,12 +1977,12 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), - impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.lxyz, eCpair.lxyzErr, eCpair.lxy, eCpair.lxyErr, eCpair.lz, eCpair.lzErr, - pdgCodeCascade, foundCommonMother); + pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi- loop @@ -1533,6 +2024,7 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 2212, -211, 3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcOmegaId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, 3122, -321, 3334, mcParticles); @@ -1543,7 +2035,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1551,12 +2043,12 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), - impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.lxyz, eCpair.lxyzErr, eCpair.lxy, eCpair.lxyErr, eCpair.lz, eCpair.lzErr, - pdgCodeCascade, foundCommonMother); + pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega- loop @@ -1576,11 +2068,11 @@ struct taggingHFE { bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; auto mcCollision = mcele.template mcCollision_as(); - bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. - bool is_e_from_prompt_jpsi = std::abs(mcMother.pdgCode()) == 443 && !isMotherFromB && std::abs(mcMother.pdgCode()) != 100443; + bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. + bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; // e from prompt J/psi is treated as the same as Z. // e from nonprompt J/psi is treated as the same as B. // B+ -> J/psi K+ -> e+ e- K+ bool is_e_from_hc = (std::abs(mcMother.pdgCode()) == 411 || std::abs(mcMother.pdgCode()) == 421 || std::abs(mcMother.pdgCode()) == 431 || std::abs(mcMother.pdgCode()) == 4122 || std::abs(mcMother.pdgCode()) == 4132 || std::abs(mcMother.pdgCode()) == 4232 || std::abs(mcMother.pdgCode()) == 4332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); bool is_e_from_hb = (std::abs(mcMother.pdgCode()) == 511 || std::abs(mcMother.pdgCode()) == 521 || std::abs(mcMother.pdgCode()) == 531 || std::abs(mcMother.pdgCode()) == 541 || std::abs(mcMother.pdgCode()) == 5122 || std::abs(mcMother.pdgCode()) == 5132 || std::abs(mcMother.pdgCode()) == 5232 || std::abs(mcMother.pdgCode()) == 5332) && isSemiLeptonic(mcMother, mcParticles, cfgPdgLepton, -cfgPdgLepton - 1); - if (!(is_e_from_dy || is_e_from_prompt_jpsi || is_e_from_hc || is_e_from_hb)) { + if (!(is_e_from_dy || is_e_from_jpsi || is_e_from_hc || is_e_from_hb)) { continue; } @@ -1624,7 +2116,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1689,7 +2181,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && foundCommonMother && std::abs(mckaon.pdgCode()) == cfgPdgLepton))) { // I want 3 types. // 1. truely found HF->eh (SV should found by eh, and truely found.) For signal sample in ML. // 2. mistakenly found DY->eh (SV should not be found by eh, but found.) For bkg sample in ML. @@ -1755,6 +2247,7 @@ struct taggingHFE { int mcK0SId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -211, 310, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcK0SId > 0) { // true K0S pdgCodeV0 = 310; auto mcK0S = mcParticles.rawIteratorAt(mcK0SId); @@ -1770,12 +2263,13 @@ struct taggingHFE { int commonMotherId = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcMother_of_k0s); if (commonMotherId > 0) { foundCommonMother = true; + pdgCodeIM = mcMother_of_k0s.pdgCode(); } } } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1783,12 +2277,12 @@ struct taggingHFE { v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), - impactParameterV0.getY(), std::sqrt(impactParameterV0.getSigmaY2()), + impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.lxyz, eV0pair.lxyzErr, eV0pair.lxy, eV0pair.lxyErr, eV0pair.lz, eV0pair.lzErr, - pdgCodeV0, foundCommonMother); + pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -1829,13 +2323,14 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeV0 = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true v0 auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); pdgCodeV0 = mcLambda.pdgCode(); foundCommonMother = FindCommonMotherFrom2ProngsWithoutPDG(mcele, mcLambda) > 0; } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1843,12 +2338,12 @@ struct taggingHFE { v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), - impactParameterV0.getY(), std::sqrt(impactParameterV0.getSigmaY2()), + impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.lxyz, eV0pair.lxyzErr, eV0pair.lxy, eV0pair.lxyErr, eV0pair.lz, eV0pair.lzErr, - pdgCodeV0, foundCommonMother); + pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Anti-Lambda loop @@ -1890,6 +2385,7 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcXiId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, -3122, 211, -3312, mcParticles); @@ -1900,7 +2396,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1908,12 +2404,12 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), - impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.lxyz, eCpair.lxyzErr, eCpair.lxy, eCpair.lxyErr, eCpair.lz, eCpair.lzErr, - pdgCodeCascade, foundCommonMother); + pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi+ loop @@ -1955,6 +2451,7 @@ struct taggingHFE { int mcLambdaId = FindCommonMotherFrom2Prongs(mcposLeg, mcnegLeg, 211, -2212, -3122, mcParticles); int pdgCodeCascade = 0; bool foundCommonMother = false; + int pdgCodeIM = 0; if (mcLambdaId > 0) { // true Lambda auto mcLambda = mcParticles.rawIteratorAt(mcLambdaId); int mcOmegaId = FindCommonMotherFrom2Prongs(mcLambda, mcbachelor, -3122, 321, -3334, mcParticles); @@ -1965,7 +2462,7 @@ struct taggingHFE { } } - if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_prompt_jpsi) && !foundCommonMother))) { + if (!(((is_e_from_hc || is_e_from_hb) && foundCommonMother) || ((is_e_from_dy || is_e_from_jpsi) && !foundCommonMother))) { continue; } @@ -1973,12 +2470,12 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), - impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.lxyz, eCpair.lxyzErr, eCpair.lxy, eCpair.lxyErr, eCpair.lz, eCpair.lzErr, - pdgCodeCascade, foundCommonMother); + pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega+ loop @@ -2158,7 +2655,8 @@ struct taggingHFE { std::vector> used_electronIds; // pair of hTypeId and electronId - void processMC(FilteredMyCollisionsWithMCLabel const& collisions, aod::BCsWithTimestamps const& bcs, MyTracksWithMCLabel const& tracks, aod::TrackAssoc const& trackIndices, filteredV0s const& v0s, filteredMyCascades const& cascades, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + // void processMC(FilteredMyCollisionsWithMCLabel const& collisions, MyBCs const& bcs, MyTracksWithMCLabel const& tracks, aod::TrackAssoc const& trackIndices, filteredV0s const& v0s, filteredMyCascades const& cascades, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + void processMC(MyCollisionsWithMCLabel const& collisions, MyBCs const& bcs, MyTracksWithMCLabel const& tracks, aod::TrackAssoc const& trackIndices, filteredV0s const& v0s, filteredMyCascades const& cascades, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { initCCDB(bcs.iteratorAt(0)); mTOFResponse->processSetup(bcs.iteratorAt(0)); @@ -2170,7 +2668,8 @@ struct taggingHFE { mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); } } - calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); // for primary tracks + calculateTOFNSigmasForV0sAndCascades(collisions, bcs, v0s, cascades, tracks); // for secondary tracks runPairing(bcs, collisions, tracks, trackIndices, v0s, cascades, mcCollisions, mcParticles); runGen(mcCollisions, mcParticles); @@ -2181,6 +2680,9 @@ struct taggingHFE { mapTOFNsigmaKaReassociated.clear(); mapTOFNsigmaPrReassociated.clear(); mapTOFBetaReassociated.clear(); + + mapTOFNSigma.clear(); + mapTOFBeta.clear(); } PROCESS_SWITCH(taggingHFE, processMC, "process with TTCA", true); From 0001a5fcf6d95ca559b21ea81ae0c94d6c72c36e Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 10 May 2026 18:38:22 +0200 Subject: [PATCH 119/449] [PWGEM/Dilepton] fix after #16184 (#16185) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 91 ++++++++++++++--------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 4306fcf48b3..0e9e92ffe4b 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -190,7 +190,7 @@ struct taggingHFE { Configurable cfg_max_mass_lambda_veto{"cfg_max_mass_lambda_veto", 1.12, "max mass for Lambda veto for K0S"}; Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "min cospa for v0"}; Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 0.1, "max distance between 2 legs for v0"}; - // Configurable cfg_min_radius{"cfg_min_radius", 0.1, "min rxy for v"}; + Configurable cfg_min_radius{"cfg_min_radius", 0.1, "min rxy for v"}; Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.f, "min. TPC Ncr/Nf ratio"}; Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; @@ -224,20 +224,20 @@ struct taggingHFE { std::string prefix = "cascadeCut"; Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for lambda in cascade"}; Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for lambda in cascade"}; - Configurable cfg_min_mass_Xi{"cfg_min_mass_Xi", 1.316, "min mass for Xi"}; - Configurable cfg_max_mass_Xi{"cfg_max_mass_Xi", 1.326, "max mass for Xi"}; + Configurable cfg_min_mass_Xi{"cfg_min_mass_Xi", 1.314, "min mass for Xi"}; + Configurable cfg_max_mass_Xi{"cfg_max_mass_Xi", 1.328, "max mass for Xi"}; Configurable cfg_min_mass_Xi_veto{"cfg_min_mass_Xi_veto", 1.31, "min mass for Xi veto"}; Configurable cfg_max_mass_Xi_veto{"cfg_max_mass_Xi_veto", 1.33, "max mass for Xi veto"}; - Configurable cfg_min_mass_Omega{"cfg_min_mass_Omega", 1.669, "min mass for Omega"}; - Configurable cfg_max_mass_Omega{"cfg_max_mass_Omega", 1.675, "max mass for Omega"}; - Configurable cfg_min_mass_Omega_veto{"cfg_min_mass_Omega_veto", 1.66, "min mass for Omega veto"}; - Configurable cfg_max_mass_Omega_veto{"cfg_max_mass_Omega_veto", 1.68, "max mass for Omega veto"}; - Configurable cfg_min_cospa_v0{"cfg_min_cospa_v0", 0.9, "minimum V0 CosPA in cascade"}; + Configurable cfg_min_mass_Omega{"cfg_min_mass_Omega", 1.668, "min mass for Omega"}; + Configurable cfg_max_mass_Omega{"cfg_max_mass_Omega", 1.678, "max mass for Omega"}; + Configurable cfg_min_mass_Omega_veto{"cfg_min_mass_Omega_veto", 1.665, "min mass for Omega veto"}; + Configurable cfg_max_mass_Omega_veto{"cfg_max_mass_Omega_veto", 1.680, "max mass for Omega veto"}; + Configurable cfg_min_cospa_v0{"cfg_min_cospa_v0", 0.95, "minimum V0 CosPA in cascade"}; Configurable cfg_max_dcadau_v0{"cfg_max_dcadau_v0", 0.1, "max distance between V0 Daughters in cascade"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.9, "minimum cascade CosPA"}; + Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "minimum cascade CosPA"}; Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.1, "max distance between bachelor and V0"}; - Configurable cfg_min_rxy_v0{"cfg_min_rxy_v0", 1.2, "minimum V0 rxy in cascade"}; - Configurable cfg_min_rxy{"cfg_min_rxy", 0.5, "minimum V0 rxy in cascade"}; + Configurable cfg_min_rxy_v0{"cfg_min_rxy_v0", 0.1, "minimum V0 rxy in cascade"}; + Configurable cfg_min_rxy{"cfg_min_rxy", 0.1, "minimum V0 rxy in cascade"}; Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; Configurable cfg_min_dcaxy_bachelor{"cfg_min_dcaxy_bachelor", 0.05, "min dca XY for bachelor in cm"}; Configurable cfg_min_dcaxy_v0{"cfg_min_dcaxy_v0", 0.05, "min dca XY for V0 in cm"}; @@ -1182,12 +1182,6 @@ struct taggingHFE { auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); - if (v0.dcaV0daughters() > v0Cut.cfg_max_dca2legs) { - continue; - } - if (v0.v0cosPA() < v0Cut.cfg_min_cospa) { - continue; - } if (pos.sign() * neg.sign() > 0) { continue; } @@ -1268,35 +1262,6 @@ struct taggingHFE { continue; } - if (cascade.cascradius() > cascade.v0radius()) { - continue; - } - - if (cascade.dcaV0daughters() > cascadeCut.cfg_max_dcadau_v0) { - continue; - } - if (cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_cospa_v0) { - continue; - } - if (cascade.v0radius() < cascadeCut.cfg_min_rxy_v0) { - continue; - } - - if (cascade.cascradius() < cascadeCut.cfg_min_rxy) { - continue; - } - - if (cascade.dcacascdaughters() > cascadeCut.cfg_max_dcadau) { - continue; - } - if (cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_cospa) { - continue; - } - - if (cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_dcaxy_v0) { - continue; - } - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg) || !isSelectedV0Leg(bachelor)) { continue; } @@ -1559,6 +1524,18 @@ struct taggingHFE { continue; } + if (v0.dcaV0daughters() > v0Cut.cfg_max_dca2legs) { + continue; + } + + if (v0.v0radius() < v0Cut.cfg_min_radius) { + continue; + } + + if (v0.v0cosPA() < v0Cut.cfg_min_cospa) { + continue; + } + fillV0Histograms(collision, v0); if (std::sqrt(std::pow(v0.alpha() / v0Cut.cfg_max_alpha_veto, 2) + std::pow(v0.qtarm() / v0Cut.cfg_max_qt_veto, 2)) < 1.f) { // photon conversion rejection at small qT @@ -1607,6 +1584,28 @@ struct taggingHFE { continue; } + if (cascade.cascradius() > cascade.v0radius()) { + continue; + } + + if (cascade.dcaV0daughters() > cascadeCut.cfg_max_dcadau_v0) { + continue; + } + if (cascade.v0radius() < cascadeCut.cfg_min_rxy_v0) { + continue; + } + if (cascade.cascradius() < cascadeCut.cfg_min_rxy) { + continue; + } + + if (cascade.dcacascdaughters() > cascadeCut.cfg_max_dcadau) { + continue; + } + + // if (cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_dcaxy_v0) { + // continue; + // } + fillCascadeHistograms(collision, cascade); if (cascade.sign() < 0) { // Xi- or Omega- From 1d11aee3406f1df67e35ac81b89a55a5add82014 Mon Sep 17 00:00:00 2001 From: Joachim Carlo Kristian Bjerg Hansen <50103987+joachimckh@users.noreply.github.com> Date: Mon, 11 May 2026 00:44:54 +0200 Subject: [PATCH 120/449] [PWGJE] Dev bugf (#16186) --- PWGJE/Tasks/jetSpectraEseTask.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index 04ac8b3c1e7..de4299d79d2 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -413,7 +413,7 @@ struct JetSpectraEseTask { registry.add("hTrackEta", "track #eta;#eta_{track};entries", {HistType::kTH3F, {{centAxis}, {etaAxis}, {occAxis}}}); registry.add("hTrackPhi", "track #phi;#phi_{track};entries", {HistType::kTH3F, {{centAxis}, {phiAxis}, {occAxis}}}); registry.add("hOccupancy", "Occupancy;Occupancy;entries", {HistType::kTH2F, {{centAxis}, {occAxis}}}); - registry.add("hOccupancyEv", "Occupancy;Occupancy;entries", {HistType::kTH1F, {{centAxis}, {occAxis}}}); + registry.add("hOccupancyEv", "Occupancy;Occupancy;entries", {HistType::kTH2F, {{centAxis}, {occAxis}}}); registry.add("hPsiOccupancy", "Occupancy;#Psi_{2};entries", {HistType::kTH3F, {{centAxis}, {150, -2.5, 2.5}, {occAxis}}}); registry.add("hSTrackPtPhiEtaOcc", ";cent;jpt;phi;eta;occ", {HistType::kTHnSparseF, {{centAxis}, {100, 0, 100}, {phiAxis}, {etaAxis}, {occAxis}}}); registry.add("hSJetPtPhiEtaOcc", ";cent;jpt;phi;eta;occ", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {phiAxis}, {etaAxis}, {occAxis}}}); From cdf8de6775e257f69f00bf4e28939c0702e27c57 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Mon, 11 May 2026 11:32:19 +0530 Subject: [PATCH 121/449] [PWGLF] Added Lambda1520 for MC prediction (#16181) --- PWGLF/Tasks/QC/mcParticlePrediction.cxx | 14 ++++++++------ PWGLF/Utils/mcParticle.h | 6 +++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/QC/mcParticlePrediction.cxx b/PWGLF/Tasks/QC/mcParticlePrediction.cxx index 2f506ba14e5..c190fe5a525 100644 --- a/PWGLF/Tasks/QC/mcParticlePrediction.cxx +++ b/PWGLF/Tasks/QC/mcParticlePrediction.cxx @@ -57,7 +57,7 @@ using namespace o2::pwglf; // Particles static const std::vector parameterNames{"Enable"}; static constexpr int nParameters = 1; -static const int defaultParticles[PIDExtended::NIDsTot][nParameters]{{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; +static const int defaultParticles[PIDExtended::NIDsTot][nParameters]{{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; bool enabledParticlesArray[PIDExtended::NIDsTot]; // Estimators @@ -158,7 +158,7 @@ std::array, Estimators::nEstimators> hvertexPosZ; std::array, PIDExtended::NIDsTot>, Estimators::nEstimators> hpt; std::array, PIDExtended::NIDsTot>, Estimators::nEstimators> hyield; -struct mcParticlePrediction { +struct McParticlePrediction { // Histograms HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -195,6 +195,8 @@ struct mcParticlePrediction { Configurable enableVsEta05Histograms{"enableVsEta05Histograms", true, "Enables the correlation between ETA05 and other estimators"}; Configurable enableVsEta08Histograms{"enableVsEta08Histograms", true, "Enables the correlation between ETA08 and other estimators"}; Configurable enableVsImpactParameterHistograms{"enableVsImpactParameterHistograms", true, "Enables the correlation between impact parameter and other estimators"}; + Configurable cfgEvtZvtxCut{"cfgEvtZvtxCut", 10.0f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable chargetolerance{"chargetolerance", 1e-3, "Tolerance to consider a particle as charged based on its charge"}; Service pdgDB; o2::pwglf::ParticleCounter mCounter; @@ -456,7 +458,7 @@ struct mcParticlePrediction { } histos.fill(HIST("collisions/generated"), 1); - if (std::abs(mcCollision.posZ()) > 10.f) { + if (std::abs(mcCollision.posZ()) > cfgEvtZvtxCut) { return; } histos.fill(HIST("collisions/generated"), 2); @@ -500,7 +502,7 @@ struct mcParticlePrediction { TParticlePDG* p = pdgDB->GetParticle(particle.pdgCode()); if (p) { - if (std::abs(p->Charge()) > 1e-3) { + if (std::abs(p->Charge()) > chargetolerance) { histos.fill(HIST("particles/eta/charged"), particle.eta()); } else { histos.fill(HIST("particles/eta/neutral"), particle.eta()); @@ -721,7 +723,7 @@ struct mcParticlePrediction { hestimatorsRecoEvVsBCId[i]->Fill(foundBCid, nMultReco[i]); } } - PROCESS_SWITCH(mcParticlePrediction, processReco, "Process the reco info", true); + PROCESS_SWITCH(McParticlePrediction, processReco, "Process the reco info", true); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Utils/mcParticle.h b/PWGLF/Utils/mcParticle.h index 657e696ec9a..745fcd94fbf 100644 --- a/PWGLF/Utils/mcParticle.h +++ b/PWGLF/Utils/mcParticle.h @@ -134,7 +134,8 @@ class PIDExtended static constexpr ID KstarPM = PIDCounts + 40; static constexpr ID Kshort = PIDCounts + 41; static constexpr ID Xi1530 = PIDCounts + 42; - static constexpr ID NIDsTot = PIDCounts + 43; + static constexpr ID Lambda1520 = PIDCounts + 43; + static constexpr ID NIDsTot = PIDCounts + 44; static constexpr const char* sNames[NIDsTot + 1] = { o2::track::pid_constants::sNames[Electron], // Electron @@ -199,6 +200,7 @@ class PIDExtended "KstarPM", // KstarPM "Kshort", // Kshort "Xi1530", // Xi1530 + "Lambda1520", // Lambda1520 nullptr}; static std::vector arrayNames() @@ -341,6 +343,8 @@ class PIDExtended return Kshort; case 3324: return Xi1530; + case 3124: + return Lambda1520; default: LOG(debug) << "Cannot identify particle with PDG code " << particle.pdgCode(); break; From 1791cf2521fb74d2cf5520d1d4282d5754c3e21f Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 11 May 2026 11:55:26 +0200 Subject: [PATCH 122/449] [PWGLF] Fix in hStrangeCorrelation.cxx (#16190) Co-authored-by: Lucia Anna Tarasovicova --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index c5d120deb0e..bd03393379a 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -1775,10 +1775,10 @@ struct HStrangeCorrelation { histos.add("hNumberOfRejectedPairsPion", "hNumberOfRejectedPairsPion", kTH1F, {{1, 0, 1}}); } if (doprocessSameEventHHadrons) { - histos.add("hDCAzTriggerHadron", "hDCAzTriggerHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); - histos.add("hDCAxyTriggerHadron", "hDCAxyTriggerHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); - histos.add("hDCAzAssociatedHadron", "hDCAzAssociatedHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); - histos.add("hDCAxyAssociatedHadron", "hDCAxyAssociatedHadron", kTH2F, {{200, -10, 10}, axesConfigurations.axisPtQA}); + histos.add("hDCAzTriggerHadron", "hDCAzTriggerHadron", kTH2F, {{200, -0.5, 0.5}, axesConfigurations.axisPtQA}); + histos.add("hDCAxyTriggerHadron", "hDCAxyTriggerHadron", kTH2F, {{200, -0.5, 0.5}, axesConfigurations.axisPtQA}); + histos.add("hDCAzAssociatedHadron", "hDCAzAssociatedHadron", kTH2F, {{200, -0.5, 0.5}, axesConfigurations.axisPtQA}); + histos.add("hDCAxyAssociatedHadron", "hDCAxyAssociatedHadron", kTH2F, {{200, -0.5, 0.5}, axesConfigurations.axisPtQA}); } if (doprocessSameEventHV0s || doprocessMixedEventHV0s) { histos.add("hNumberOfRejectedPairsV0", "hNumberOfRejectedPairsV0", kTH1F, {{1, 0, 1}}); From 75ce5a3c45ef5b25132d1a3397d0d804a9695310 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Mon, 11 May 2026 18:06:06 +0530 Subject: [PATCH 123/449] [PWGLF] Update Kstar and Phi tasks with correction factors (#16178) --- PWGLF/Tasks/Resonances/kstar0analysis.cxx | 1906 ++++++++++++-------- PWGLF/Tasks/Resonances/phi1020analysis.cxx | 1517 ++++++++++------ 2 files changed, 2164 insertions(+), 1259 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar0analysis.cxx b/PWGLF/Tasks/Resonances/kstar0analysis.cxx index 4c3a32afcae..ba0e75d4e1a 100644 --- a/PWGLF/Tasks/Resonances/kstar0analysis.cxx +++ b/PWGLF/Tasks/Resonances/kstar0analysis.cxx @@ -8,11 +8,16 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. + /// \file kstar0analysis.cxx /// \brief the reconstruction of k*0(892) resonance analysis using K\pi decay channel /// \author Hirak Kumar Koley +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" + #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -20,6 +25,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include #include #include #include @@ -28,918 +34,1312 @@ #include #include #include +#include #include #include #include #include +#include #include +#include #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include -#include +#include +#include #include #include -#include -#include -#include #include -#include #include -#include - using namespace o2; +using namespace o2::soa; +using namespace o2::aod; +using namespace o2::aod::rctsel; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; -struct kstar0analysis { +using LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; + +enum TrackSelectionType { + AllTracks = 0, + GlobalTracks, + GlobalTracksWoPtEta, + GlobalTracksWoDCA, + QualityTracks, + InAcceptanceTracks, +}; + +enum PIDCutType { + SquareType = 1, + CircularType, +}; + +struct Kstar0analysis { + // Define slice per collision + Preslice perCollision = o2::aod::track::collisionId; SliceCache cache; - Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + SliceCache cacheMC; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - //================================== - //|| - //|| Selection - //|| - //================================== - - // Event Selection - Configurable cfgEventSelections{"cfgEventSelections", "sel8", "Set event selection"}; - Configurable cfgEventVtxCut{"cfgEventVtxCut", 10.0, "V_z cut selection"}; - ConfigurableAxis cfgCentAxis{"cfgCentAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0}, "Binning of the centrality axis"}; - Configurable cfgOccupancySel{"cfgOccupancySel", false, "Occupancy selection"}; - Configurable cfgOccupancyMax{"cfgOccupancyMax", 999999., "maximum occupancy of tracks in neighbouring collisions in a given time range"}; - Configurable cfgOccupancyMin{"cfgOccupancyMin", -100., "minimum occupancy of tracks in neighbouring collisions in a given time range"}; - - // Track Selection - // General - Configurable cfgTrackMinPt{"cfgTrackMinPt", 0.15, "set track min pT"}; - Configurable cfgTrackMaxEta{"cfgTrackMaxEta", 0.8, "set track max Eta"}; - Configurable cfgTrackMaxDCArToPVcut{"cfgTrackMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; - Configurable cfgTrackMaxDCAzToPVcut{"cfgTrackMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; - Configurable cfgTrackGlobalSel{"cfgTrackGlobalSel", true, "Global track selection"}; - Configurable cfgTrackPrimaryTrack{"cfgTrackPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgTrackConnectedToPV{"cfgTrackConnectedToPV", true, "PV contributor track selection"}; // PV Contriuibutor - Configurable cfgTrackGlobalWoDCATrack{"cfgTrackGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - - // TPC - Configurable cfgTrackFindableTPCClusters{"cfgTrackFindableTPCClusters", 50, "nFindable TPC Clusters"}; - Configurable cfgTrackTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; - Configurable cfgTrackRowsOverFindable{"cfgTrackRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; - Configurable cfgTrackTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; - - // ITS - Configurable cfgTrackITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; - - // PID - Configurable cfgTrackTPCPID{"cfgTrackTPCPID", true, "Enables TPC PID"}; - Configurable cfgTrackTOFPID{"cfgTrackTOFPID", true, "Enables TOF PID"}; - Configurable cfgTrackSquarePIDCut{"cfgTrackSqurePIDCut", true, "Enables PID cut shape square switch"}; - Configurable cfgTrackCirclePIDCut{"cfgTrackCirclePIDCut", true, "Enables PID cut shape circle switch"}; - Configurable cfgTrackCircleValue{"cfgTrackCircleValue", 2, "Enables TOF TPC PID circle cut value"}; - Configurable cfgTrackTOFHard{"cfgTrackTOFHard", false, "Enables TOF Hard"}; - - Configurable cfgTrackTPCPIDnSig{"cfgTrackTPCPIDnSig", 4.0, "nTPC PID sigma"}; - Configurable cfgTrackTOFPIDnSig{"cfgTrackTOFPIDnSig", 4.0, "nTOF PID sigma"}; - Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; - - // Mixing - ConfigurableAxis cfgBinsMixMult{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0}, "Binning of the centrality axis"}; - ConfigurableAxis cfgBinsMixVtx{"cfgBinsMixVtx", {VARIABLE_WIDTH, -10.0f, -5.f, 0.f, 5.f, 10.f}, "Mixing bins - z-vertex"}; - Configurable cfgMixNMixedEvents{"cfgMixNMixedEvents", 10, "Number of mixed events per event"}; - Configurable cfgVtxMixCut{"cfgVtxMixCut", 10, "Vertex Mix Cut"}; - - // MCGen - Configurable cfgForceGenReco{"cfgForceGenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; - Configurable cfgReqMcEffPID{"cfgReqMcEffPID", false, "Request McEfficiency PID"}; - - // Pair - Configurable cfgMinvNBins{"cfgMinvNBins", 300, "Number of bins for Minv axis"}; - Configurable cfgMinvMin{"cfgMinvMin", 0.60, "Minimum Minv value"}; - Configurable cfgMinvMax{"cfgMinvMax", 1.20, "Maximum Minv value"}; - - // Histogram - ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; - ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; - Configurable cfgEventCutQA{"cfgEventCutsQA", false, "Enable Event QA Hists"}; - Configurable cfgTrackCutQA{"cfgTrackCutQA", false, "Enable Track QA Hists"}; - - Configurable cfgMCHistos{"cfgMCHistos", false, "Enable MC Hists"}; - Configurable cfgMixedHistos{"cfgMixedHistos", false, "Enable Mixed Histos"}; - Configurable cfgManualEvSel{"cfgManualEvSel", false, "Enable Manual EvSel"}; - - // Main + + Service pdg; + RCTFlagsChecker rctChecker; + + struct : ConfigurableGroup { + Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.0f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtNoTFBorderCut{"cfgEvtNoTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtNoITSROFrameBorderCut{"cfgEvtNoITSROFrameBorderCut", false, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgEvtIsRCTFlagpassed{"cfgEvtIsRCTFlagpassed", false, "Evt sel: apply RCT flag selection"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable cfgEvtSel8{"cfgEvtSel8", false, "Evt Sel 8 check for offline selection"}; + Configurable cfgEvtIsINELgt0{"cfgEvtIsINELgt0", false, "Evt sel: apply INEL>0 selection"}; + } configEvents; + + struct : ConfigurableGroup { + // Pre-selection Track cuts + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; + Configurable cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"}; + Configurable cMinTPCNClsFound{"cMinTPCNClsFound", 120, "minimum TPCNClsFound value for good track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgCutRapidity{"cfgCutRapidity", 0.5f, "rapidity range for particles"}; + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"}; + + // DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1f, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1f, "Track DCAz cut to PV Maximum"}; + + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cTPCNClsFound{"cTPCNClsFound", false, "Switch to turn on/off TPCNClsFound cut"}; + Configurable cDCAr7SigCut{"cDCAr7SigCut", false, "Track DCAr 7 Sigma cut to PV Maximum"}; + } configTracks; + + struct : ConfigurableGroup { + /// PID Selections + Configurable pidnSigmaPreSelectionCut{"pidnSigmaPreSelectionCut", 4.0f, "pidnSigma Cut for pre-selection of tracks"}; + Configurable cByPassTOF{"cByPassTOF", false, "By pass TOF PID selection"}; // By pass TOF PID selection + Configurable cPIDcutType{"cPIDcutType", 2, "cPIDcutType = 1 for square cut, 2 for circular cut"}; // By pass TOF PID selection + + // Kaon + Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {0.5f}, "pT intervals for Kaon TPC PID cuts"}; + Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; + Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.0f}, "pT intervals for Kaon TOF PID cuts"}; + Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedpTintv{"kaonTPCTOFCombinedpTintv", {999.0f}, "pT intervals for Kaon TPC-TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedPIDcuts{"kaonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Kaon TPC-TOF PID cuts"}; + + // Pion + Configurable> pionTPCPIDpTintv{"pionTPCPIDpTintv", {0.9f}, "pT intervals for Pion TPC PID cuts"}; + Configurable> pionTPCPIDcuts{"pionTPCPIDcuts", {2}, "nSigma list for Pion TPC PID cuts"}; + Configurable> pionTOFPIDpTintv{"pionTOFPIDpTintv", {999.0f}, "pT intervals for Pion TOF PID cuts"}; + Configurable> pionTOFPIDcuts{"pionTOFPIDcuts", {2}, "nSigma list for Pion TOF PID cuts"}; + Configurable> pionTPCTOFCombinedpTintv{"pionTPCTOFCombinedpTintv", {999.0f}, "pT intervals for Pion TPC-TOF PID cuts"}; + Configurable> pionTPCTOFCombinedPIDcuts{"pionTPCTOFCombinedPIDcuts", {2}, "nSigma list for Pion TPC-TOF PID cuts"}; + } configPID; + + struct : ConfigurableGroup { + /// Event Mixing + Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; + ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}, "Mixing bins - z-vertex"}; + ConfigurableAxis cfgMultPercentileBins{"cfgMultPercentileBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - multiplicity"}; + + // Rotational background + Configurable rotationalcut{"rotationalcut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable cNofRotations{"cNofRotations", 3, "Number of random rotations in the rotational background"}; + Configurable cfgRotPi{"cfgRotPi", true, "rotate Pion"}; + } configBkg; + + // Additional purity check + Configurable crejectProton{"crejectProton", false, "Switch to turn on/off proton contamination"}; + Configurable cUseOpeningAngleCut{"cUseOpeningAngleCut", false, "Kinematic Cuts for p-K pair opening angle"}; + Configurable cMinOpeningAngle{"cMinOpeningAngle", 1.4f, "Minimum opening angle between daughters"}; + Configurable cMaxOpeningAngle{"cMaxOpeningAngle", 2.4f, "Maximum opening angle between daughters"}; + Configurable cfgUseDeltaEtaPhiCuts{"cfgUseDeltaEtaPhiCuts", false, "Switch to turn on/off delta eta and delta phi cuts"}; + Configurable cfgUseDaughterEtaCutMC{"cfgUseDaughterEtaCutMC", false, "Switch to turn on/off eta cuts for daughters in MC"}; + + // MC selection cut + Configurable cUseRapcutMC{"cUseRapcutMC", true, "Use rapidity cut for MC"}; + + // cuts on mother + Configurable cfgUseCutsOnMother{"cfgUseCutsOnMother", false, "Enable additional cuts on mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 10.0f, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 3.0f, "Maximum Minv of mother cut"}; + Configurable cMaxDeltaEtaCut{"cMaxDeltaEtaCut", 0.7f, "Maximum deltaEta between daughters"}; + Configurable cMaxDeltaPhiCut{"cMaxDeltaPhiCut", 1.5f, "Maximum deltaPhi between daughters"}; + + // switches + Configurable cFillMultQA{"cFillMultQA", false, "Turn on/off additional QA plots"}; + Configurable cFillTrackQA{"cFillTrackQA", false, "Turn on/off additional QA plots"}; + Configurable cFilladditionalQAeventPlots{"cFilladditionalQAeventPlots", false, "Additional QA event plots"}; + Configurable cFilladditionalMEPlots{"cFilladditionalMEPlots", false, "Additional Mixed event plots"}; + Configurable cFilldeltaEtaPhiPlots{"cFilldeltaEtaPhiPlots", false, "Enable additional cuts on daughters"}; + Configurable cFill1DQAs{"cFill1DQAs", false, "Invariant mass 1D"}; + Configurable centEstimator{"centEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; + + TRandom* rn = new TRandom(); + + // Pre-filters for efficient process + Filter zVtxFilter = (nabs(o2::aod::collision::posZ) <= configEvents.cfgEvtZvtx); + Filter collisionFilterMC = nabs(aod::mccollision::posZ) <= configEvents.cfgEvtZvtx; + + Filter acceptanceFilter = (nabs(aod::track::eta) < configTracks.cfgCutEta && nabs(aod::track::pt) > configTracks.cMinPtcut) && + (nabs(aod::track::dcaXY) < configTracks.cMaxDCArToPVcut) && (nabs(aod::track::dcaZ) < configTracks.cMaxDCAzToPVcut); + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Filtered>; + + // for MC reco + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Filtered>; + + /// Figures + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.12f, 0.14f, 0.16f, 0.18f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.5f, 0.55f, 0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.75f, 1.8f, 1.9f, 2.0f, 2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f, 3.0f, 3.1f, 3.2f, 3.3f, 3.4f, 3.6f, 3.7f, 3.8f, 3.9f, 4.0f, 4.1f, 4.2f, 4.5f, 4.6f, 4.8f, 4.9f, 5.0f, 5.5f, 5.6f, 6.0f, 6.4f, 6.5f, 7.0f, 7.2f, 8.0f, 9.0f, 9.5f, 9.6f, 10.0f, 11.0f, 11.5f, 12.0f, 13.0f, 14.0f, 14.4f, 15.0f, 16.0f, 18.0f, 19.2f, 20.0f}, "Binning of the pT axis"}; + ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.2f, 1.4f, 1.6f, 1.8f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.2f, 4.4f, 4.6f, 4.8f, 5.0f, 5.2f, 5.4f, 5.6f, 5.8f, 6.0f, 6.2f, 6.4f, 6.6f, 6.8f, 7.0f, 7.2f, 7.4f, 7.6f, 7.8f, 8.0f, 8.2f, 8.4f, 8.6f, 8.8f, 9.0f, 9.2f, 9.4f, 9.6f, 9.8f, 10.0f, 10.2f, 10.4f, 10.6f, 10.8f, 11.0f, 11.2f, 11.4f, 11.6f, 11.8f, 12.0f, 12.2f, 12.4f, 12.6f, 12.8f, 13.0f, 13.2f, 13.4f, 13.6f, 13.8f, 14.0f, 14.2f, 14.4f, 14.6f, 14.8f, 15.0f, 15.2f, 15.4f, 15.6f, 15.8f, 16.0f, 16.2f, 16.4f, 16.6f, 16.8f, 17.0f, 17.2f, 17.4f, 17.6f, 17.8f, 18.0f, 18.2f, 18.4f, 18.6f, 18.8f, 19.0f, 19.2f, 19.4f, 19.6f, 19.8f, 20.0f}, "Binning of the pT axis"}; + ConfigurableAxis binsEta{"binsEta", {150, -1.5f, 1.5f}, ""}; + ConfigurableAxis binsMass{"binsMass", {300, 0.6f, 1.2f}, "Invariant Mass (GeV/#it{c}^2)"}; + ConfigurableAxis binsMult{"binsMult", {105, 0.0f, 105.0f}, "mult_{FT0M}"}; + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsTPCXrows{"binsTPCXrows", {100, 60, 160}, ""}; + ConfigurableAxis binsnSigma{"binsnSigma", {130, -6.5f, 6.5f}, ""}; + ConfigurableAxis binsnTPCSignal{"binsnTPCSignal", {1000, 0, 1000}, ""}; + ConfigurableAxis binsEtaPhi{"binsEtaPhi", {350, -3.5f, 3.5f}, ""}; + void init(o2::framework::InitContext&) { - // HISTOGRAMS - const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; - const AxisSpec axisPhi{200, -1, +7, "#phi"}; - const AxisSpec ptAxis = {200, 0, 20.0}; - const AxisSpec pidAxis = {120, -6, 6}; - const AxisSpec minvAxis = {cfgMinvNBins, cfgMinvMin, cfgMinvMax}; - const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; - const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; - - if (cfgEventCutQA) { - histos.add("hEvent_Cut", "Number of event after cuts", kTH1D, {{13, -0.5, 12.5}}); - histos.add("hPosZ_BC", "hPosZ_BC", kTH1F, {{300, -15.0, 15.0}}); - histos.add("hPosZ_AC", "hPosZ_AC", kTH1F, {{300, -15.0, 15.0}}); - histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); - histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); - } - if (cfgTrackCutQA) { - histos.add("hDCArToPv_BC", "DCArToPv_BC", kTH1F, {axisDCAxy}); - histos.add("hDCAzToPv_BC", "DCAzToPv_BC", kTH1F, {axisDCAz}); - histos.add("hIsPrim_BC", "hIsPrim_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsGood_BC", "hIsGood_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsPrimCont_BC", "hIsPrimCont_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hFindableTPCClusters_BC", "hFindableTPCClusters_BC", kTH1F, {{200, 0, 200}}); - histos.add("hFindableTPCRows_BC", "hFindableTPCRows_BC", kTH1F, {{200, 0, 200}}); - histos.add("hClustersVsRows_BC", "hClustersVsRows_BC", kTH1F, {{200, 0, 2}}); - histos.add("hTPCChi2_BC", "hTPCChi2_BC", kTH1F, {{200, 0, 100}}); - histos.add("hITSChi2_BC", "hITSChi2_BC", kTH1F, {{200, 0, 100}}); - histos.add("QA_nSigma_pion_TPC_BC", "QA_nSigma_pion_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_nSigma_pion_TOF_BC", "QA_nSigma_pion_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_pion_TPC_TOF_BC", "QA_pion_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); - histos.add("QA_nSigma_kaon_TPC_BC", "QA_nSigma_kaon_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_nSigma_kaon_TOF_BC", "QA_nSigma_kaon_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_kaon_TPC_TOF_BC", "QA_kaon_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); - histos.add("QA_track_pT_BC", "QA_track_pT_BC", kTH1F, {{13, 0.0, 13.0}}); - - histos.add("hDCArToPv_AC", "DCArToPv_AC", kTH1F, {axisDCAxy}); - histos.add("hDCAzToPv_AC", "DCAzToPv_AC", kTH1F, {axisDCAz}); - histos.add("hIsPrim_AC", "hIsPrim_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsGood_AC", "hIsGood_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsPrimCont_AC", "hIsPrimCont_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hFindableTPCClusters_AC", "hFindableTPCClusters_AC", kTH1F, {{200, 0, 200}}); - histos.add("hFindableTPCRows_AC", "hFindableTPCRows_AC", kTH1F, {{200, 0, 200}}); - histos.add("hClustersVsRows_AC", "hClustersVsRows_AC", kTH1F, {{200, 0, 2}}); - histos.add("hTPCChi2_AC", "hTPCChi2_AC", kTH1F, {{200, 0, 100}}); - histos.add("hITSChi2_AC", "hITSChi2_AC", kTH1F, {{200, 0, 100}}); - histos.add("QA_nSigma_pion_TPC_AC", "QA_nSigma_pion_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_nSigma_pion_TOF_AC", "QA_nSigma_pion_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_pion_TPC_TOF_AC", "QA_pion_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); - histos.add("QA_nSigma_kaon_TPC_AC", "QA_nSigma_kaon_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_nSigma_kaon_TOF_AC", "QA_nSigma_kaon_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); - histos.add("QA_kaon_TPC_TOF_AC", "QA_kaon_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); - histos.add("QA_track_pT_AC", "QA_track_pT_AC", kTH1F, {{13, 0.0, 13.0}}); + rctChecker.init(configEvents.cfgEvtRCTFlagCheckerLabel, configEvents.cfgEvtRCTFlagCheckerZDCCheck, configEvents.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + // axes + AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPtQA{binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{binsEta, "#eta"}; + AxisSpec axisRap{binsEta, "#it{y}"}; + AxisSpec axisMassk892{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec axisMult{binsMult, "mult_{FT0M}"}; + AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; + AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; + AxisSpec axisPIDQA{binsnSigma, "#sigma"}; + AxisSpec axisTPCSignal{binsnTPCSignal, ""}; + AxisSpec axisEtaPhi{binsEtaPhi, ""}; + AxisSpec axisPhi{350, 0, 7, "#Phi"}; + AxisSpec axisMultMix{configBkg.cfgMultPercentileBins, "Multiplicity Percentile"}; + AxisSpec axisVtxMix{configBkg.cfgVtxBins, "Vertex Z (cm)"}; + + histos.add("CollCutCounts", "No. of event after cuts", kTH1I, {{10, 0, 10}}); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(1, "All Events"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(2, "|Vz| < cut"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(6, "rctChecker"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(7, "sel8"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(8, "IsINELgt0"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(9, "All Passed Events"); + + histos.add("Event/posZ", "; vtx_{z} (cm); Entries", HistType::kTH1F, {{250, -12.5, 12.5}}); + histos.add("Event/centFT0M", "; FT0M Percentile; Entries", HistType::kTH1F, {{110, 0, 110}}); + + if (cFilladditionalQAeventPlots) { + // event histograms + if (doprocessData) { + histos.add("QAevent/hPairsCounterSameE", "total valid no. of pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0, 1000.0}}); + } + // Gen on Mixed event + if (doprocessME) { + + // Histograms for Mixed Event Pool characteristics + histos.add("QAevent/hMixPool_VtxZ", "Mixed Event Pool: Vertex Z;Vtx Z (cm);Counts", HistType::kTH1F, {axisVtxMix}); + histos.add("QAevent/hMixPool_Multiplicity", "Mixed Event Pool: Multiplicity;Multiplicity;Counts", HistType::kTH1F, {axisMultMix}); + histos.add("QAevent/hMixPool_VtxZ_vs_Multiplicity", "Mixed Event Pool: Vertex Z vs Multiplicity;Counts", HistType::kTH2F, {axisVtxMix, axisMultMix}); + + histos.add("QAevent/hPairsCounterMixedE", "total valid no. of pairs mixedE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("QAevent/hVertexZMixedE", "Collision Vertex Z position", HistType::kTH1F, {{100, -15.0f, 15.0f}}); + histos.add("QAevent/hMultiplicityPercentMixedE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); + histos.add("QAevent/hnTrksMixedE", "n tracks per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + } } - //////////////////////////////////// - histos.add("nEvents", "nEvents", kTH1F, {{7, 0.0, 7.0}}); - histos.add("hUSS_KPi", "hUSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hUSS_PiK", "hUSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hLSS_KPi", "hLSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hLSS_PiK", "hLSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + if (doprocessData) { + // Track QA before cuts + // --- Track + if (cFillTrackQA) { + histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for all Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_ka_all", "TOF NSigma for all Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for all Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka_all", "TPC NSigma for all Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + + histos.add("QA/QAbefore/Track/TOF_TPC_Map_pi_all", "TOF + TPC Combined PID for all Pion;{#sigma_{TOF}^{Pion}};{#sigma_{TPC}^{Pion}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_pi_all", "TOF NSigma for all Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pi_all", "TPC NSigma for all Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_pi_all", "TPC NSigma for all Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Pion}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + + histos.add("QA/QAbefore/Track/dcaZ_all", "DCA_{Z} distribution of all Tracks; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY_all", "DCA_{XY} momentum distribution of all Tracks; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR_all", "# TPC Xrows distribution of all Tracks; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/pT_all", "pT distribution of all Tracks; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAbefore/Track/eta_all", "#eta distribution of all Tracks; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + } + if (cFillMultQA) { + // Multiplicity correlation calibrations + histos.add("MultCalib/centGloPVpi", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + histos.add("MultCalib/centGloPVka", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + } - if (cfgMixedHistos) { - histos.add("hUSS_KPi_Mix", "hUSS_KPi_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hUSS_PiK_Mix", "hUSS_PiK_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - } - if (cfgMCHistos) { - histos.add("nEvents_Gen", "nEvents_Gen", kTH1F, {{4, 0.0, 4.0}}); - histos.add("hUSS_TrueRec", "hUSS_TrueRec", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hGen_pT_Raw", "Gen_pT_Raw (GeV/c)", kTH1F, {{800, 0., 40.}}); - histos.add("hGen_pT_GoodEv", "hGen_pT_GoodEv", kTHnSparseF, {cfgCentAxis, ptAxis}); - } + // PID QA after cuts + // --- Kaon + histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_selected", "TOF + TPC Combined PID for selected Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_selected", "TOF NSigma for selected Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_selected", "TPC NSigma for selected Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly_selected", "TPC NSigma for selected Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/dcaZ_selected", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Kaon/dcaXY_selected", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Kaon/TPC_CR_selected", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Kaon/pT_selected", "pT distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Kaon/eta_selected", "#eta distribution of selected Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Kaon/TPC_Signal_ka_selected", "TPC Signal for selected Kaon;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Kaon/TPCnclusterPhika_selected", "TPC ncluster vs phi for selected Kaon", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // --- Pion + histos.add("QA/QAafter/Pion/TOF_TPC_Map_pi_selected", "TOF + TPC Combined PID for selected Pion;{#sigma_{TOF}^{Pion}};{#sigma_{TPC}^{Pion}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Pion/TOF_Nsigma_pi_selected", "TOF NSigma for selected Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Pion/TPC_Nsigma_pi_selected", "TPC NSigma for selected Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Pion/TPC_Nsigma_pi_TPConly_selected", "TPC NSigma for selected Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Pion}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Pion/dcaZ_selected", "DCA_{Z} distribution of selected Pions; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Pion/dcaXY_selected", "DCA_{XY} momentum distribution of selected Pions; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Pion/TPC_CR_selected", "# TPC Xrows distribution of selected Pions; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Pion/pT_selected", "pT distribution of selected Pions; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Pion/eta_selected", "#eta distribution of selected Pions; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Pion/TPC_Signal_pi_selected", "TPC Signal for selected Pion;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Pion/TPCnclusterPhipi_selected", "TPC ncluster vs phi for selected Pion", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // Mass QA 1D for quick check + if (cFill1DQAs) { + histos.add("Result/Data/k892invmass", "Invariant mass of K(892) K^{#pm}#pi^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); + histos.add("Result/Data/antik892invmass", "Invariant mass of K(892) K^{#mp}#pi^{#pm}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); + histos.add("Result/Data/k892invmassLSPP", "Invariant mass of K(892) Like Sign Method K^{#plus}#pi^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K+ + Pi + histos.add("Result/Data/k892invmassLSMM", "Invariant mass of K(892) Like Sign Method K^{#minus}#pi^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K- + anti-Pi + } + // eta phi QA + if (cFilldeltaEtaPhiPlots) { + histos.add("QAbefore/deltaEta", "deltaEta of kaon and Pion candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAbefore/deltaPhi", "deltaPhi of kaon and Pion candidates", HistType::kTH1F, {axisEtaPhi}); + + histos.add("QAafter/deltaEta", "deltaEta of kaon and Pion candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAafter/deltaPhi", "deltaPhi of kaon and Pion candidates", HistType::kTH1F, {axisEtaPhi}); - if (cfgEventCutQA) { - std::shared_ptr hCutFlow = histos.get(HIST("hEvent_Cut")); - std::vector eventCutLabels = { - "All Events", - "sel8", - Form("|Vz| < %.1f", cfgEventVtxCut.value), - "kIsGoodZvtxFT0vsPV", - "kNoSameBunchPileup", - "kNoTimeFrameBorder", - "kNoITSROFrameBorder", - "kNoCollInTimeRangeStandard", - "kIsGoodITSLayersAll", - Form("Occupancy < %.0f", cfgOccupancyMax.value), - "All passed events"}; - - for (size_t i = 0; i < eventCutLabels.size(); ++i) { - hCutFlow->GetXaxis()->SetBinLabel(i + 1, eventCutLabels[i].c_str()); + histos.add("QAafter/PhiPiafter", "Phi of Pion candidates", HistType::kTH1F, {axisPhi}); + histos.add("QAafter/PhiKaafter", "Phi of kaon candidates", HistType::kTH1F, {axisPhi}); } + + // 3d histogram + histos.add("Result/Data/h3k892invmass", "Invariant mass of K(892) K^{#pm}#pi^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); + histos.add("Result/Data/h3antik892invmass", "Invariant mass of K(892) K^{#mp}#pi^{#pm}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); + histos.add("Result/Data/h3k892invmassLSPP", "Invariant mass of K(892) Like Sign Method K^{#plus}#pi^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); // K+ + Pi + histos.add("Result/Data/h3k892invmassLSMM", "Invariant mass of K(892) Like Sign Method K^{#minus}#pi^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); // K- + anti-Pi } - } // end of init - //====================== - //|| For LF Analysis - //====================== - using EventCandidates = soa::Join; //, aod::CentFT0Ms, aod::CentFT0As - using EventCandidatesTrue = aod::McCollisions; - using TrackCandidates = soa::Join; - using TrackCandidatesMC = soa::Join; - - // For Mixed Event - using BinningType = ColumnBinningPolicy; - - Partition kaon = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); - Partition pion = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); - Partition kaonMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); - Partition pionMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); - - double massKa = o2::constants::physics::MassKPlus; - double massPi = o2::constants::physics::MassPiMinus; - - //================================== - //|| - //|| Helper Templates - //|| - //================================== - template - void fillQA(const bool pass, const objType& obj, const int objecttype = 0) - { - if (objecttype == 1) { - if constexpr (requires { obj.posZ(); }) { - if (!pass) { - histos.fill(HIST("hPosZ_BC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); - } else { - histos.fill(HIST("hPosZ_AC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); - } - } - } // eventSelection histogram - - if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { - if (objecttype == 3) { - if (!pass) { - histos.fill(HIST("hDCArToPv_BC"), obj.dcaXY()); - histos.fill(HIST("hDCAzToPv_BC"), obj.dcaZ()); - histos.fill(HIST("hIsPrim_BC"), obj.isPrimaryTrack()); - histos.fill(HIST("hIsGood_BC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_BC"), obj.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_BC"), obj.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_BC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_BC"), obj.tpcChi2NCl()); - histos.fill(HIST("hITSChi2_BC"), obj.itsChi2NCl()); - histos.fill(HIST("QA_track_pT_BC"), obj.pt()); - } else { - histos.fill(HIST("hDCArToPv_AC"), obj.dcaXY()); - histos.fill(HIST("hDCAzToPv_AC"), obj.dcaZ()); - histos.fill(HIST("hIsPrim_AC"), obj.isPrimaryTrack()); - histos.fill(HIST("hIsGood_AC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_AC"), obj.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_AC"), obj.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_AC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_AC"), obj.tpcChi2NCl()); - histos.fill(HIST("hITSChi2_AC"), obj.itsChi2NCl()); - histos.fill(HIST("QA_track_pT_AC"), obj.pt()); - } + if (doprocessRotational) { + if (cFill1DQAs) { + histos.add("Result/Data/k892InvMassRotation", "Invariant mass of K(892) Like Sign Method K^{#plus}#pi^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K+ + Pi + histos.add("Result/Data/antik892InvMassRotation", "Invariant mass of K(892) Like Sign Method K^{#minus}#pi^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K- + anti-Pi } - } // trackSelection - if (objecttype == 4) { - if constexpr (requires { obj.pt(); }) { - if (!pass) { - histos.fill(HIST("QA_nSigma_kaon_TPC_BC"), obj.pt(), obj.tpcNSigmaKa()); - histos.fill(HIST("QA_nSigma_kaon_TOF_BC"), obj.pt(), obj.tofNSigmaKa()); - histos.fill(HIST("QA_kaon_TPC_TOF_BC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); - } else { - histos.fill(HIST("QA_nSigma_kaon_TPC_AC"), obj.pt(), obj.tpcNSigmaKa()); - histos.fill(HIST("QA_nSigma_kaon_TOF_AC"), obj.pt(), obj.tofNSigmaKa()); - histos.fill(HIST("QA_kaon_TPC_TOF_AC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); - } + histos.add("Result/Data/h3k892InvMassRotation", "Invariant mass of K(892) rotation", kTHnSparseF, {axisMult, axisPt, axisMassk892}); + histos.add("Result/Data/h3antik892InvMassRotation", "Invariant mass of K(892) rotation", kTHnSparseF, {axisMult, axisPt, axisMassk892}); + } + // Mixed event histograms + if (doprocessME) { + if (cFill1DQAs) { + histos.add("Result/Data/k892invmassME_UnlikeSign", "Invariant mass of K(892) mixed event K^{#pm}#pi^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); + histos.add("Result/Data/antik892invmassME_UnlikeSign", "Invariant mass of K(892) mixed event K^{#pm}#pi^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); } - } // kaon pid Selection - if (objecttype == 5) { - if constexpr (requires { obj.pt(); }) { - if (!pass) { - histos.fill(HIST("QA_nSigma_pion_TPC_BC"), obj.pt(), obj.tpcNSigmaPi()); - histos.fill(HIST("QA_nSigma_pion_TOF_BC"), obj.pt(), obj.tofNSigmaPi()); - histos.fill(HIST("QA_pion_TPC_TOF_BC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); - } else { - histos.fill(HIST("QA_nSigma_pion_TPC_AC"), obj.pt(), obj.tpcNSigmaPi()); - histos.fill(HIST("QA_nSigma_pion_TOF_AC"), obj.pt(), obj.tofNSigmaPi()); - histos.fill(HIST("QA_pion_TPC_TOF_AC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + histos.add("Result/Data/h3k892invmassME_UnlikeSign", "Invariant mass of K(892) mixed event K^{#pm}#pi^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); + histos.add("Result/Data/h3antik892invmassME_UnlikeSign", "Invariant mass of K(892) mixed event K^{#pm}#pi^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); + + if (cFilladditionalMEPlots) { + if (cFill1DQAs) { + histos.add("Result/Data/k892invmassME_LSPP", "Invariant mass of K(892) Like Sign Method K^{#plus}#pi^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K+ + Pi + histos.add("Result/Data/k892invmassME_LSMM", "Invariant mass of K(892) Like Sign Method K^{#minus}#pi^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassk892}}); // K- + anti-Pi } + histos.add("Result/Data/h3k892invmassME_LSPP", "Invariant mass of K(892) mixed event Like Sign Method K^{#plus}#pi^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); // K+ + Pi + histos.add("Result/Data/h3k892invmassME_LSMM", "Invariant mass of K(892) mixed event Like Sign Method K^{#minus}#pi^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassk892}); // K- + anti-Pi } - } // pion pid Selection - } // fill QA - - enum class objectType { MB, - MBRecParticle }; + } - template - void fillMinv(objectType type, const TrackType& trk1, const TrackType& trk2, const ROOT::Math::PxPyPzMVector& lReso, double centrality, bool IsMix, bool flip) - { - double conjugate = trk1.sign() * trk2.sign(); - switch (type) { - case objectType::MB: - if (IsMix && cfgMixedHistos) { - if (conjugate < 0) { - if (!flip) - histos.fill(HIST("hUSS_KPi_Mix"), centrality, lReso.Pt(), lReso.M()); - else - histos.fill(HIST("hUSS_PiK_Mix"), centrality, lReso.Pt(), lReso.M()); - } - } else { - if (conjugate < 0) { - if (!flip) - histos.fill(HIST("hUSS_KPi"), centrality, lReso.Pt(), lReso.M()); - else - histos.fill(HIST("hUSS_PiK"), centrality, lReso.Pt(), lReso.M()); - } else if (conjugate > 0) { - if (!flip) - histos.fill(HIST("hLSS_KPi"), centrality, lReso.Pt(), lReso.M()); - else - histos.fill(HIST("hLSS_PiK"), centrality, lReso.Pt(), lReso.M()); - } - } - break; + // MC QA + if (doprocessEventFactor) { + histos.add("Event/MultiplicityGenEv", "hMCEventIndices", kTH1D, {axisMult}); + histos.add("Event/MultiplicityRecoEv", "Multiplicity of Reconstructed Events", kTH1D, {axisMult}); + } - case objectType::MBRecParticle: - if (cfgMCHistos) { - if (conjugate < 0) { - histos.fill(HIST("hUSS_TrueRec"), centrality, lReso.Pt(), lReso.M()); - } - } - break; - } // switch - } // fillMinv - //====================================================================== + if (doprocessMCGen) { + histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated K(892); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated K(892); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterRapcut", " #phi-#it{p}_{T} distribution of Generated K(892); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_afterRapcut", " #phi-y distribution of Generated K(892); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); - template - std::pair eventSelection(const EventType event, const bool QA) - { - if (cfgEventCutQA && QA) { - fillQA(false, event, 1); - histos.fill(HIST("hEvent_Cut"), 0); + histos.add("Result/MC/Genk892pt", "pT distribution of True MC K(892)0", kTH2F, {axisPt, axisMult}); + histos.add("Result/MC/Genantik892pt", "pT distribution of True MC Anti-K(892)0", kTH2F, {axisPt, axisMult}); } - if (!event.sel8()) - return {false, 1}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 1); - } - if (std::abs(event.posZ()) > cfgEventVtxCut) - return {false, 2}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 2); - } - if (!event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) - return {false, 3}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 3); - } - if (!event.selection_bit(aod::evsel::kNoSameBunchPileup)) - return {false, 4}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 4); - } - if (!event.selection_bit(aod::evsel::kNoTimeFrameBorder)) - return {false, 5}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 5); - } - if (!event.selection_bit(aod::evsel::kNoITSROFrameBorder)) - return {false, 6}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 6); - } - if (!event.selection_bit(aod::evsel::kNoCollInTimeRangeStandard)) - return {false, 7}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 7); - } - if (!event.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) - return {false, 8}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 8); - } - if (cfgOccupancySel && (event.trackOccupancyInTimeRange() > cfgOccupancyMax || event.trackOccupancyInTimeRange() < cfgOccupancyMin)) - return {false, 9}; - if (cfgEventCutQA && QA) { - histos.fill(HIST("hEvent_Cut"), 9); + if (doprocessMCRec) { + histos.add("QA/MC/h2RecoEtaPt_after", " #eta-#it{p}_{T} distribution of Reconstructed K(892); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); + histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed K(892); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + + histos.add("QA/MC/trkDCAxy_pi", "DCAxy distribution of Pion track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAz_pi", "DCAz distribution of Pion track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/TOF_Nsigma_pi_all", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_pi_all", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Pion}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + + histos.add("Result/MC/h3k892Recoinvmass", "Invariant mass of Reconstructed MC K(892)0", kTHnSparseF, {axisMult, axisPt, axisMassk892}); + histos.add("Result/MC/h3antik892Recoinvmass", "Invariant mass of Reconstructed MC Anti-K(892)0", kTHnSparseF, {axisMult, axisPt, axisMassk892}); } - if (cfgEventCutQA && QA) { - fillQA(true, event, 1); - histos.fill(HIST("hEvent_Cut"), 10); + if (doprocessSignalLoss) { + histos.add("Result/SignalLoss/GenTruek892pt_den", "True k892 (den)", kTH2F, {axisPt, axisMult}); + histos.add("Result/SignalLoss/GenTrueantik892pt_den", "True anti-k892 (den)", kTH2F, {axisPt, axisMult}); + + histos.add("Result/SignalLoss/GenTruek892pt_num", "True k892 (num)", kTH2F, {axisPt, axisMult}); + histos.add("Result/SignalLoss/GenTrueantik892pt_num", "True anti-k892 (num)", kTH2F, {axisPt, axisMult}); } - return {true, 11}; - }; - template - bool trackSelection(const TracksType track, const bool QA) + // Print output histograms statistics + LOG(info) << "Size of the histograms in Kstar0analysis:"; + histos.print(); + } // end of init + + float massKa = MassKaonCharged; + float massPi = MassPionCharged; + + // Centralicity estimator selection + template + float centEst(Coll collisions) { - if (cfgTrackCutQA && QA) { - fillQA(false, track, 3); + float returnValue = -999.0f; + switch (centEstimator) { + case 0: + returnValue = collisions.centFT0M(); + break; + case 1: + returnValue = collisions.centFT0A(); + break; + case 2: + returnValue = collisions.centFT0C(); + break; + default: + returnValue = collisions.centFT0M(); + break; } + return returnValue; + } + + template + bool isSelected(const Coll& collision, bool fillHist = true) + { + auto applyCut = [&](bool enabled, bool condition, int bin) { + if (!enabled) + return true; + if (!condition) + return false; + if (fillHist) + histos.fill(HIST("CollCutCounts"), bin); + return true; + }; + + if (fillHist) + histos.fill(HIST("CollCutCounts"), 0); - if (cfgTrackGlobalSel && !track.isGlobalTrack()) + if (!applyCut(true, std::abs(collision.posZ()) <= configEvents.cfgEvtZvtx, 1)) return false; - if (track.pt() < cfgTrackMinPt) + + if (!applyCut(configEvents.cfgEvtTriggerTVXSel, + collision.selection_bit(aod::evsel::kIsTriggerTVX), 2)) return false; - if (std::abs(track.eta()) > cfgTrackMaxEta) + + if (!applyCut(configEvents.cfgEvtNoTFBorderCut, + collision.selection_bit(aod::evsel::kNoTimeFrameBorder), 3)) return false; - if (std::abs(track.dcaXY()) > cfgTrackMaxDCArToPVcut) + + if (!applyCut(configEvents.cfgEvtNoITSROFrameBorderCut, + collision.selection_bit(aod::evsel::kNoITSROFrameBorder), 4)) return false; - if (std::abs(track.dcaZ()) > cfgTrackMaxDCAzToPVcut) + + if (!applyCut(configEvents.cfgEvtIsRCTFlagpassed, rctChecker(collision), 5)) return false; - if (cfgTrackPrimaryTrack && !track.isPrimaryTrack()) + + if (!applyCut(configEvents.cfgEvtSel8, collision.sel8(), 6)) return false; - if (cfgTrackGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + + if (!applyCut(configEvents.cfgEvtIsINELgt0, collision.isInelGt0(), 7)) return false; - if (cfgTrackFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTrackFindableTPCClusters) + + if (fillHist) + histos.fill(HIST("CollCutCounts"), 8); + + return true; + } + + template + bool trackCut(const TrackType track) + { + // basic track cuts + if (configTracks.cDCAr7SigCut && std::abs(track.dcaXY()) > (0.004f + 0.013f / (track.pt()))) // 7 - Sigma cut + return false; + if (configTracks.cTPCNClsFound && (track.tpcNClsFound() < configTracks.cMinTPCNClsFound)) return false; - if (track.tpcNClsCrossedRows() < cfgTrackTPCCrossedRows) + if (track.tpcNClsCrossedRows() < configTracks.cfgMinCrossedRows) return false; - if (cfgTrackRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTrackRowsOverFindable) + if (configTracks.cfgHasTOF && !track.hasTOF()) return false; - if (track.tpcChi2NCl() > cfgTrackTPCChi2) + if (configTracks.cfgPrimaryTrack && !track.isPrimaryTrack()) return false; - if (track.itsChi2NCl() > cfgTrackITSChi2) + if (configTracks.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgTrackConnectedToPV && !track.isPVContributor()) + if (configTracks.cfgPVContributor && !track.isPVContributor()) + return false; + if (configTracks.cfgGlobalTrack && !track.isGlobalTrack()) return false; - if (cfgTrackCutQA && QA) { - fillQA(true, track, 3); - } return true; - }; + } + + // LOGF(info, "AFTER: pt: %f, hasTOF: %d, TPCSigma: %f, TOFSigma: %f, boolTPC: %d, boolTOF: %d, bool: %d", pt, candidate.hasTOF(), + // candidate.tpcNSigmaPr(), candidate.tofNSigmaPr(), tpcPIDPassed, tofPIDPassed, tpcPIDPassed || tofPIDPassed); - template - bool trackPIDKaon(const TrackPID& candidate, const bool QA) + template + bool ptDependentPidPion(const T& candidate) { - double tpcpid = 0; - double tofpid = 0; - bool tpcPIDPassed{false}, tofPIDPassed{false}; + auto vPionTPCPIDpTintv = configPID.pionTPCPIDpTintv.value; + vPionTPCPIDpTintv.insert(vPionTPCPIDpTintv.begin(), configTracks.cMinPtcut); + auto vPionTPCPIDcuts = configPID.pionTPCPIDcuts.value; + auto vPionTOFPIDpTintv = configPID.pionTOFPIDpTintv.value; + auto vPionTPCTOFCombinedpTintv = configPID.pionTPCTOFCombinedpTintv.value; + auto vPionTPCTOFCombinedPIDcuts = configPID.pionTPCTOFCombinedPIDcuts.value; + auto vPionTOFPIDcuts = configPID.pionTOFPIDcuts.value; + + float pt = candidate.pt(); + float ptSwitchToTOF = vPionTPCPIDpTintv.back(); + float tpcNsigmaPi = candidate.tpcNSigmaPi(); + float tofNsigmaPi = candidate.tofNSigmaPi(); + + bool tpcPIDPassed = false; + + // TPC PID (interval check) + for (size_t i = 0; i < vPionTPCPIDpTintv.size() - 1; ++i) { + if (pt > vPionTPCPIDpTintv[i] && pt < vPionTPCPIDpTintv[i + 1]) { + if (std::abs(tpcNsigmaPi) < vPionTPCPIDcuts[i]) + tpcPIDPassed = true; + } + } - if (cfgTrackCutQA && QA) { - fillQA(false, candidate, 4); + // TOF bypass option (for QA or MC) + if (configPID.cByPassTOF) { + return std::abs(tpcNsigmaPi) < vPionTPCPIDcuts.back(); } - // TPC - if (cfgTrackSquarePIDCut) { - if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) - tpcPIDPassed = true; - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaKa()) < cfgTrackTOFPIDnSig) { - tofPIDPassed = true; - } - } else { - if (!cfgTrackTOFHard) { - tofPIDPassed = true; - } else { - tofPIDPassed = false; + // Case 1: No TOF and pt ≤ threshold → accept only via TPC PID + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > threshold → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: Has TOF → use TPC + TOF (square or circular) + if (candidate.hasTOF()) { + if (configPID.cPIDcutType == SquareType) { + // Rectangular cut + for (size_t i = 0; i < vPionTOFPIDpTintv.size(); ++i) { + if (pt < vPionTOFPIDpTintv[i]) { + if (std::abs(tofNsigmaPi) < vPionTOFPIDcuts[i] && + std::abs(tpcNsigmaPi) < vPionTPCPIDcuts.back()) + return true; + } } - } - } // end of square cut - if (cfgTrackCirclePIDCut) { - if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) - tpcpid = std::abs(candidate.tpcNSigmaKa()); - tofpid = 0; - - if (candidate.hasTOF()) { - tofpid = std::abs(candidate.tofNSigmaKa()); - } else { - if (cfgTrackTOFHard) { - tofpid = 999; + } else if (configPID.cPIDcutType == CircularType) { + // Circular cut + for (size_t i = 0; i < vPionTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vPionTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = + tpcNsigmaPi * tpcNsigmaPi + + tofNsigmaPi * tofNsigmaPi; + if (combinedSigma2 < vPionTPCTOFCombinedPIDcuts[i] * vPionTPCTOFCombinedPIDcuts[i]) + return true; + } } } - if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { - tpcPIDPassed = true; - tofPIDPassed = true; - } - } // circular cut - - // TPC & TOF - if (tpcPIDPassed && tofPIDPassed) { - if (cfgTrackCutQA && QA) { - fillQA(true, candidate, 4); - } - return true; } + return false; } - template - bool trackPIDPion(const TrackPID& candidate, const bool QA) + template + bool ptDependentPidKaon(const T& candidate) { - double tpcpid = 0; - double tofpid = 0; - bool tpcPIDPassed{false}, tofPIDPassed{false}; + auto vKaonTPCPIDpTintv = configPID.kaonTPCPIDpTintv.value; + vKaonTPCPIDpTintv.insert(vKaonTPCPIDpTintv.begin(), configTracks.cMinPtcut); + auto vKaonTPCPIDcuts = configPID.kaonTPCPIDcuts.value; + auto vKaonTOFPIDpTintv = configPID.kaonTOFPIDpTintv.value; + auto vKaonTPCTOFCombinedpTintv = configPID.kaonTPCTOFCombinedpTintv.value; + auto vKaonTPCTOFCombinedPIDcuts = configPID.kaonTPCTOFCombinedPIDcuts.value; + auto vKaonTOFPIDcuts = configPID.kaonTOFPIDcuts.value; + + float pt = candidate.pt(); + float ptSwitchToTOF = vKaonTPCPIDpTintv.back(); + float tpcNsigmaKa = candidate.tpcNSigmaKa(); + float tofNsigmaKa = candidate.tofNSigmaKa(); + + bool tpcPIDPassed = false; + + // TPC PID interval-based check + for (size_t i = 0; i < vKaonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vKaonTPCPIDpTintv[i] && pt < vKaonTPCPIDpTintv[i + 1]) { + if (std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts[i]) { + tpcPIDPassed = true; + break; + } + } + } - if (cfgTrackCutQA && QA) { - fillQA(false, candidate, 5); + // TOF bypass option + if (configPID.cByPassTOF) { + return std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back(); } - // TPC - if (cfgTrackSquarePIDCut) { - if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) - tpcPIDPassed = true; - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPi()) < cfgTrackTOFPIDnSig) { - tofPIDPassed = true; - } - } else { - if (!cfgTrackTOFHard) { - tofPIDPassed = true; - } else { - tofPIDPassed = false; + // Case 1: No TOF and pt ≤ ptSwitch → use TPC-only + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > ptSwitch → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: TOF is available → apply TPC+TOF PID logic + if (candidate.hasTOF()) { + if (configPID.cPIDcutType == SquareType) { + // Rectangular cut + for (size_t i = 0; i < vKaonTOFPIDpTintv.size(); ++i) { + if (pt < vKaonTOFPIDpTintv[i]) { + if (std::abs(tofNsigmaKa) < vKaonTOFPIDcuts[i] && + std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back()) { + return true; + } + } } - } - } // end of square cut - if (cfgTrackCirclePIDCut) { - if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) - tpcpid = std::abs(candidate.tpcNSigmaPi()); - tofpid = 0; - - if (candidate.hasTOF()) { - tofpid = std::abs(candidate.tofNSigmaPi()); - } else { - if (cfgTrackTOFHard) { - tofpid = 999; + } else if (configPID.cPIDcutType == CircularType) { + // Circular cut + for (size_t i = 0; i < vKaonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vKaonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = tpcNsigmaKa * tpcNsigmaKa + + tofNsigmaKa * tofNsigmaKa; + if (combinedSigma2 < vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i]) { + return true; + } + } } } - if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { - tpcPIDPassed = true; - tofPIDPassed = true; - } - } // circular cut - - // TPC & TOF - if (tpcPIDPassed && tofPIDPassed) { - if (cfgTrackCutQA && QA) { - fillQA(true, candidate, 5); - } - return true; } + return false; } - template - ROOT::Math::PxPyPzMVector minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA, const bool flip) + auto static constexpr MinPtforProtonRejection = 1.0f; + auto static constexpr MaxPtforProtonRejection = 2.0f; + auto static constexpr MaxnSigmaforProtonRejection = 2.0f; + + template + bool rejectProton(const T& candidate) { - if (!trackSelection(trk1, false) || !trackSelection(trk2, false)) - return {}; - - if (!trackPIDKaon(trk1, QA) || !trackPIDPion(trk2, QA)) - return {}; - - if (trk1.globalIndex() >= trk2.globalIndex()) - return {}; - - ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; - if (!flip) { - lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); - } else { - lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massKa); + if (candidate.pt() > MinPtforProtonRejection && candidate.pt() < MaxPtforProtonRejection && !candidate.hasTOF() && candidate.tpcNSigmaPr() < MaxnSigmaforProtonRejection) { + return false; } - lResonance = lDecayDaughter1 + lDecayDaughter2; - - if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) - return {}; - return {lResonance}; + return true; } - template - ROOT::Math::PxPyPzMVector TrueReconstruction(const TracksType& trk1, const TracksType& trk2) - { - double conjugate = trk1.sign() * trk2.sign(); - if (conjugate > 0) - return {}; + auto static constexpr MaxNok892Daughters = 2; - auto particle1 = trk1.mcParticle(); - auto particle2 = trk2.mcParticle(); + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto centrality = centEst(collision); - if (!particle1.has_mothers() || !particle2.has_mothers()) { - return {}; + // Multiplicity correlation calibration plots + if (cFillMultQA) { + if constexpr (IsData) { + histos.fill(HIST("MultCalib/centGloPVpr"), centrality, dTracks1.size(), collision.multNTracksPV()); + histos.fill(HIST("MultCalib/centGloPVka"), centrality, dTracks2.size(), collision.multNTracksPV()); + } } - std::vector mothers1{}; - std::vector mothers1PDG{}; - for (auto& particle1_mom : particle1.template mothers_as()) { - mothers1.push_back(particle1_mom.globalIndex()); - mothers1PDG.push_back(particle1_mom.pdgCode()); + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hnTrksSameE"), dTracks1.size()); + } else if constexpr (IsMix) { + histos.fill(HIST("QAevent/hVertexZMixedE"), collision.posZ()); + histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), centrality); + histos.fill(HIST("QAevent/hnTrksMixedE"), dTracks1.size()); + } } + // LOG(info) << "After pass, Collision index:" << collision.index() << "multiplicity: " << collision.centFT0M() << endl; - std::vector mothers2{}; - std::vector mothers2PDG{}; - for (auto& particle2_mom : particle2.template mothers_as()) { - mothers2.push_back(particle2_mom.globalIndex()); - mothers2PDG.push_back(particle2_mom.pdgCode()); - } + LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, lResonance, ldaughterRot, lResonanceRot; - if (mothers1PDG[0] != 313) - return {}; // mother not K*0 - if (mothers2PDG[0] != 313) - return {}; // mothers not K*0 + for (const auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + // Full index policy is needed to consider all possible combinations + if (trk1.index() == trk2.index()) + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. - if (mothers1[0] != mothers2[0]) - return {}; // Kaon and pion not from the same K*0 + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; - if (std::fabs(particle1.pdgCode()) != 211 && std::fabs(particle1.pdgCode()) != 321) - return {}; - if (std::fabs(particle2.pdgCode()) != 211 && std::fabs(particle2.pdgCode()) != 321) - return {}; + //// Initialize variables + // Trk1: Pion + auto isTrk1hasTOF = trk1.hasTOF(); + auto trk1ptPi = trk1.pt(); + auto trk1etaPi = trk1.eta(); + auto trk1phiPi = trk1.phi(); + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.0f; + + // Trk2: Kaon + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk2ptKa = trk2.pt(); + auto trk2etaKa = trk2.eta(); + auto trk2phiKa = trk2.phi(); + auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.0f; + + auto deltaEta = 0.0f; + auto deltaPhi = 0.0f; + + if (cfgUseDeltaEtaPhiCuts) { + deltaEta = std::abs(trk1etaPi - trk2etaKa); + deltaPhi = std::abs(trk1phiPi - trk2phiKa); + deltaPhi = (deltaPhi > o2::constants::math::PI) ? (o2::constants::math::TwoPI - deltaPhi) : deltaPhi; + if (deltaEta >= cMaxDeltaEtaCut) + continue; + if (deltaPhi >= cMaxDeltaPhiCut) + continue; + } - double track1_mass, track2_mass; - if (std::fabs(particle1.pdgCode()) == 211) { - track1_mass = massPi; - } else { - track1_mass = massKa; - } + //// QA plots before the selection + // --- Track QA all + if constexpr (IsData) { + if (cFillTrackQA) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_pi_all"), centrality, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_pi_all"), centrality, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPConly_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTPC); + } + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPConly_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTPC); + } - if (std::fabs(particle2.pdgCode()) == 211) { - track2_mass = massPi; - } else { - track2_mass = massKa; - } + histos.fill(HIST("QA/QAbefore/Track/dcaZ_all"), trk1ptPi, trk1.dcaZ()); + histos.fill(HIST("QA/QAbefore/Track/dcaXY_all"), trk1ptPi, trk1.dcaXY()); + histos.fill(HIST("QA/QAbefore/Track/TPC_CR_all"), trk1ptPi, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAbefore/Track/pT_all"), trk1ptPi); + histos.fill(HIST("QA/QAbefore/Track/eta_all"), trk1etaPi); + } + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAbefore/deltaEta"), deltaEta); + histos.fill(HIST("QAbefore/deltaPhi"), deltaPhi); + } + } - if (track1_mass == track2_mass) { - return {}; - } + //// Apply the pid selection + if (crejectProton && rejectProton(trk2)) // to remove proton contamination from the kaon track + continue; - ROOT::Math::PxPyPzMVector lTrueDaughter1, lTrueDaughter2, lTrueReso; - lTrueDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), track1_mass); - lTrueDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), track2_mass); - lTrueReso = lTrueDaughter1 + lTrueDaughter2; + if (!ptDependentPidPion(trk1) || !ptDependentPidKaon(trk2)) + continue; - if (lTrueReso.M() < 0) - return {}; + //// QA plots after the selection + if constexpr (IsData) { // --- PID QA Pion + histos.fill(HIST("QA/QAafter/Pion/TPC_Nsigma_pi_selected"), centrality, trk1ptPi, trk1NSigmaPiTPC); + histos.fill(HIST("QA/QAafter/Pion/TPC_Signal_pi_selected"), trk1.tpcInnerParam(), trk1.tpcSignal()); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Pion/TOF_Nsigma_pi_selected"), centrality, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QA/QAafter/Pion/TOF_TPC_Map_pi_selected"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Pion/TPC_Nsigma_pi_TPConly_selected"), trk1ptPi, trk1NSigmaPiTPC); + } + histos.fill(HIST("QA/QAafter/Pion/dcaZ_selected"), trk1ptPi, trk1.dcaZ()); + histos.fill(HIST("QA/QAafter/Pion/dcaXY_selected"), trk1ptPi, trk1.dcaXY()); + histos.fill(HIST("QA/QAafter/Pion/TPC_CR_selected"), trk1ptPi, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Pion/pT_selected"), trk1ptPi); + histos.fill(HIST("QA/QAafter/Pion/eta_selected"), trk1etaPi); + histos.fill(HIST("QA/QAafter/Pion/TPCnclusterPhipi_selected"), trk1.tpcNClsFound(), trk1phiPi); + + // --- PID QA Kaon + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_selected"), centrality, trk2ptKa, trk2NSigmaKaTPC); + histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_selected"), trk2.tpcInnerParam(), trk2.tpcSignal()); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_selected"), centrality, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_selected"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly_selected"), trk2ptKa, trk2NSigmaKaTPC); + } + histos.fill(HIST("QA/QAafter/Kaon/dcaZ_selected"), trk2ptKa, trk2.dcaZ()); + histos.fill(HIST("QA/QAafter/Kaon/dcaXY_selected"), trk2ptKa, trk2.dcaXY()); + histos.fill(HIST("QA/QAafter/Kaon/TPC_CR_selected"), trk2ptKa, trk2.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Kaon/pT_selected"), trk2ptKa); + histos.fill(HIST("QA/QAafter/Kaon/eta_selected"), trk2etaKa); + histos.fill(HIST("QA/QAafter/Kaon/TPCnclusterPhika_selected"), trk2.tpcNClsFound(), trk2phiKa); + + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAafter/PhiPrafter"), trk1phiPi); + histos.fill(HIST("QAafter/PhiKaafter"), trk2phiKa); + histos.fill(HIST("QAafter/deltaEta"), deltaEta); + histos.fill(HIST("QAafter/deltaPhi"), deltaPhi); + } + } - return {lTrueReso}; - } + //// Resonance reconstruction + lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1ptPi, trk1etaPi, trk1phiPi, massPi); + lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2ptKa, trk2etaKa, trk2phiKa, massKa); - template - void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) - { - auto tracks1 = kaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); - auto tracks2 = pion->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); - - for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - for (bool flip : {false, true}) { - auto lReso = minvReconstruction(trk1, trk2, QA, flip); - if (lReso.M() < 0) + // Apply kinematic opening angle cut + if (cUseOpeningAngleCut) { + auto v1 = lDecayDaughter1.Vect(); + auto v2 = lDecayDaughter2.Vect(); + float alpha = std::acos(v1.Dot(v2) / (v1.R() * v2.R())); + if (alpha > cMinOpeningAngle && alpha < cMaxOpeningAngle) continue; + } - fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); - } // flip - } // for - } // TrackSlicing + lResonance = lDecayDaughter1 + lDecayDaughter2; - template - void TrackSlicingMC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) - { - auto tracks1 = kaonMC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); - auto tracks2 = pionMC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); + auto resonanceMass = lResonance.M(); + auto resonancePt = lResonance.Pt(); + auto resonanceRapidity = lResonance.Rapidity(); - for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) - continue; + if constexpr (IsData || IsMix) { + // Rapidity cut + if (std::abs(resonanceRapidity) > configTracks.cfgCutRapidity) + continue; + } - for (bool flip : {false, true}) { - auto lReso = minvReconstruction(trk1, trk2, QA, flip); - if (lReso.M() < 0) + if (cfgUseCutsOnMother) { + if (resonancePt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceMass >= cMaxMinvMotherCut) // excluding candidates in overflow continue; + } - fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); - } // flip - - //============================ - //| True Reconstruction - //============================ - auto lTrueReso = TrueReconstruction(trk1, trk2); - fillMinv(objectType::MBRecParticle, trk1, trk2, lTrueReso, centrality, IsMix, false); - } // tracks - } // TrackSlicingMC - - //======================================================= - //| - //| DATA STUFF (SE) - //| - //======================================================= - int nEvents = 0; - void processDataSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks) - { - if (cDebugLevel > 0) { - nEvents++; - if ((nEvents + 1) % 10000 == 0) { - std::cout << "Processed Data Events: " << nEvents << std::endl; + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hPairsCounterSameE"), 1.0f); + } else if (IsMix) { + histos.fill(HIST("QAevent/hPairsCounterMixedE"), 1.0f); + } } - } - auto [goodEv, code] = eventSelection(collision, true); - histos.fill(HIST("nEvents"), 0.5); + //// Un-like sign pair only + if (trk1.sign() * trk2.sign() < 0) { + if constexpr (IsRot) { + for (int i = 0; i < configBkg.cNofRotations; i++) { + float theta = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / configBkg.rotationalcut, o2::constants::math::PI + o2::constants::math::PI / configBkg.rotationalcut); + if (configBkg.cfgRotPi) { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk1ptPi, trk1etaPi, trk1phiPi + theta, massPi); + lResonanceRot = ldaughterRot + lDecayDaughter2; + } else { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk2ptKa, trk2etaKa, trk2phiKa + theta, massKa); + lResonanceRot = lDecayDaughter1 + ldaughterRot; + } + auto resonanceRotMass = lResonanceRot.M(); + auto resonanceRotPt = lResonanceRot.Pt(); + + // Rapidity cut + if (std::abs(lResonanceRot.Rapidity()) >= configTracks.cfgCutRapidity) + continue; + + if (cfgUseCutsOnMother) { + if (resonanceRotPt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceRotMass >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892InvMassRotation"), resonanceRotMass); + } + histos.fill(HIST("Result/Data/h3k892InvMassRotation"), centrality, resonanceRotPt, resonanceRotMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antik892InvMassRotation"), resonanceRotMass); + } + histos.fill(HIST("Result/Data/h3antik892InvMassRotation"), centrality, resonanceRotPt, resonanceRotMass); + } + } + } + if constexpr (IsData) { + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmass"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmass"), centrality, resonancePt, resonanceMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antik892invmass"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3antik892invmass"), centrality, resonancePt, resonanceMass); + } + } else if (IsMix) { + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmassME_UnlikeSign"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmassME_UnlikeSign"), centrality, resonancePt, resonanceMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antik892invmassME_UnlikeSign"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3antik892invmassME_UnlikeSign"), centrality, resonancePt, resonanceMass); + } + } - if (!goodEv) - return; + // MC + if constexpr (IsMC) { + // now we do mc true + // ------ Temporal lambda function to prevent error in build + auto getMothersIndeces = [&](auto const& theMcParticle) { + std::vector lMothersIndeces{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother index lMother: %d", lMother.globalIndex()); + lMothersIndeces.push_back(lMother.globalIndex()); + } + return lMothersIndeces; + }; + auto getMothersPDGCodes = [&](auto const& theMcParticle) { + std::vector lMothersPDGs{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %d", lMother.pdgCode()); + lMothersPDGs.push_back(lMother.pdgCode()); + } + return lMothersPDGs; + }; + // ------ + std::vector motherstrk1 = {-1, -1}; + std::vector mothersPDGtrk1 = {-1, -1}; + + std::vector motherstrk2 = {-1, -1}; + std::vector mothersPDGtrk2 = {-1, -1}; + + // + // Get the MC particle + const auto& mctrk1 = trk1.mcParticle(); + if (mctrk1.has_mothers()) { + motherstrk1 = getMothersIndeces(mctrk1); + mothersPDGtrk1 = getMothersPDGCodes(mctrk1); + } + while (motherstrk1.size() > MaxNok892Daughters) { + motherstrk1.pop_back(); + mothersPDGtrk1.pop_back(); + } - bool INELgt0 = false; - for (const auto& track : tracks) { - if (!trackSelection(track, true)) - continue; - if (std::fabs(track.eta()) < cfgTrackMaxEta) { - INELgt0 = true; + const auto& mctrk2 = trk2.mcParticle(); + if (mctrk2.has_mothers()) { + motherstrk2 = getMothersIndeces(mctrk2); + mothersPDGtrk2 = getMothersPDGCodes(mctrk2); + } + while (motherstrk2.size() > MaxNok892Daughters) { + motherstrk2.pop_back(); + mothersPDGtrk2.pop_back(); + } + + if (std::abs(mctrk1.pdgCode()) != kPiPlus || std::abs(mctrk2.pdgCode()) != kKPlus) + continue; + + if (motherstrk1[0] != motherstrk2[0]) // Same mother + continue; + + if (std::abs(mothersPDGtrk1[0]) != Pdg::kK0Star892) + continue; + + // LOGF(info, "mother trk1 id: %d, mother trk1: %d, trk1 id: %d, trk1 pdgcode: %d, mother trk2 id: %d, mother trk2: %d, trk2 id: %d, trk2 pdgcode: %d", motherstrk1[0], mothersPDGtrk1[0], trk1.globalIndex(), mctrk1.pdgCode(), motherstrk2[0], mothersPDGtrk2[0], trk2.globalIndex(), mctrk2.pdgCode()); + + if (cUseRapcutMC && std::abs(resonanceRapidity) > configTracks.cfgCutRapidity) // rapidity cut + continue; + + histos.fill(HIST("QA/MC/h2RecoEtaPt_after"), lResonance.Eta(), resonancePt); + histos.fill(HIST("QA/MC/h2RecoPhiRapidity_after"), lResonance.Phi(), resonanceRapidity); + + // Track selection check. + histos.fill(HIST("QA/MC/trkDCAxy_pi"), trk1ptPi, trk1.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAxy_ka"), trk2ptKa, trk2.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAz_pi"), trk1ptPi, trk1.dcaZ()); + histos.fill(HIST("QA/MC/trkDCAz_ka"), trk2ptKa, trk2.dcaZ()); + + histos.fill(HIST("QA/MC/TPC_Nsigma_pi_all"), centrality, trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_pi_all"), centrality, trk1ptPi, trk1NSigmaPiTOF); + } + histos.fill(HIST("QA/MC/TPC_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTOF); + } + + // MC histograms + if (mothersPDGtrk1[0] > 0) { + histos.fill(HIST("Result/MC/h3k892Recoinvmass"), centrality, resonancePt, resonanceMass); + } else { + histos.fill(HIST("Result/MC/h3antik892Recoinvmass"), centrality, resonancePt, resonanceMass); + } + } + } else { + if constexpr (IsData) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmassLSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmassLSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmassLSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmassLSMM"), centrality, resonancePt, resonanceMass); + } + } else if (IsMix) { + if (cFilladditionalMEPlots) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmassME_LSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmassME_LSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/k892invmassME_LSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3k892invmassME_LSMM"), centrality, resonancePt, resonanceMass); + } + } + } } } - if (!INELgt0) + } + + void processData(EventCandidates::iterator const& collision, + TrackCandidates const& tracks) + { + if (!isSelected(collision)) // Default event selection return; - histos.fill(HIST("nEvents"), 1.5); - TrackSlicing(collision, tracks, collision, tracks, false, true); + auto centrality = centEst(collision); - } // processSameEvents - PROCESS_SWITCH(kstar0analysis, processDataSameEvent, "process Data Same Event", false); + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centFT0M"), centrality); - //======================================================= - //| - //| DATA STUFF (ME) - //| - //======================================================= - int nEventsMix = 0; - void processDataMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Kstar0analysis, processData, "Process Event for data without partition", false); + + void processRotational(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (!isSelected(collision, false)) // Default event selection + return; + + if (!collision.isInelGt0()) // <-- + return; + + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Kstar0analysis, processRotational, "Process Rotational Background", false); + + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; + + void processME(EventCandidates const& collision, + TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); - BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) - SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; + + BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultPercentileBins}, true}; + SameKindPair pairs{colBinning, configBkg.nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - if (cDebugLevel > 0) { - nEventsMix++; - if ((nEventsMix + 1) % 10000 == 0) { - std::cout << "Processed DATA Mixed Events : " << nEventsMix << std::endl; - } - } - auto [goodEv1, code1] = eventSelection(collision1, false); - auto [goodEv2, code2] = eventSelection(collision2, false); - bool VtxMixFlag = false; - bool CentMixFlag = false; - // bool OccupanacyMixFlag = false; - if (std::fabs(collision1.posZ() - collision2.posZ()) <= cfgVtxMixCut) // set default to maybe 10 - VtxMixFlag = true; - if (std::fabs(collision1.centFT0C() - collision2.centFT0C()) <= cfgVtxMixCut) // set default to maybe 10 - CentMixFlag = true; - - if (!goodEv1 || !goodEv2) + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.globalIndex(), collision2.globalIndex()); + + // for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d)", t1.index(), t2.index(), collision1.index(), collision2.index()); + // } + + if (!isSelected(collision1, false)) // Default event selection continue; - if (!CentMixFlag) + + if (!isSelected(collision2, false)) // Default event selection continue; - if (!VtxMixFlag) + + if (!collision1.isInelGt0()) // <-- continue; - TrackSlicing(collision1, tracks1, collision2, tracks2, true, false); - } - } - PROCESS_SWITCH(kstar0analysis, processDataMixedEvent, "process DATA Mixed Event", false); - - //======================================================= - //| - //| MC STUFF (SE) - //| - //========================================================= - int nEventsMC = 0; - void processSameEventMC(EventCandidates::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&) - { - if (cDebugLevel > 0) { - nEventsMC++; - if ((nEventsMC + 1) % 10000 == 0) { - double histmem = histos.getSize(); - std::cout << histmem << std::endl; - std::cout << "process_SameEvent_MC: " << nEventsMC << std::endl; + if (!collision2.isInelGt0()) // <-- + continue; + + if (cFilladditionalQAeventPlots) { + // Fill histograms for the characteristics of the *mixed* events (collision1 and collision2) + // This will show the distribution of events that are actually being mixed. + if (cFill1DQAs) { + histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision1.posZ()); + histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision1.centFT0M()); + } + histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision1.posZ(), collision1.centFT0M()); + + // You might also want to fill for collision2 if you want to see both partners' distributions + // histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision2.posZ()); + // histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision2.centFT0M()); + // histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision2.posZ(), collision2.centFT0M()); } + fillHistograms(collision1, tracks1, tracks2); } - auto [goodEv, code] = eventSelection(collision, true); - - histos.fill(HIST("nEvents"), 0.5); + } + PROCESS_SWITCH(Kstar0analysis, processME, "Process EventMixing light without partition", false); - if (!goodEv) + void processMCRec(MCEventCandidates::iterator const& collision, + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) + { + if (!collision.has_mcCollision()) return; - bool INELgt0 = false; - for (const auto& track : tracks) { - if (!trackSelection(track, true)) - continue; - if (std::fabs(track.eta()) < cfgTrackMaxEta) { - INELgt0 = true; - } - } - if (!INELgt0) + if (!isSelected(collision)) return; - histos.fill(HIST("nEvents"), 1.5); + auto centrality = centEst(collision); - TrackSlicingMC(collision, tracks, collision, tracks, false, true); - } // processSameEvents_MC - PROCESS_SWITCH(kstar0analysis, processSameEventMC, "process Same Event MC", false); + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centFT0M"), centrality); - //======================================================= - //| - //| MC STUFF (ME) - //| - //======================================================= - int nEventsMCMix = 0; - void processMixedEventMC(EventCandidates const& collisions, TrackCandidatesMC const& tracks, aod::McParticles const&) + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Kstar0analysis, processMCRec, "Process Event for MC Rec without partition", false); + + Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == static_cast(Pdg::kK0Star892)); // K(892) + + void processMCGen(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - auto tracksTuple = std::make_tuple(tracks); - BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) - SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; - for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - if (cDebugLevel > 0) { - nEventsMCMix++; - if ((nEventsMCMix + 1) % 10000 == 0) { - std::cout << "Processed Mixed Events: " << nEventsMCMix << std::endl; - } + if (!collision.has_mcCollision()) + return; + + bool isInAfterAllCuts = isSelected(collision, false); + + auto mcPartsAll = mcParticles.sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + // bool isTrueINELgt0 = pwglf::isINELgt0mc(mcPartsAll, pdg); + bool isTrueINELgt0 = collision.isInelGt0(); // <-- + + auto centrality = centEst(collision); + + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + // Not related to the real collisions + for (const auto& part : mcParts) { // loop over all K(892) particles + + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; } - auto [goodEv1, code1] = eventSelection(collision1, false); - auto [goodEv2, code2] = eventSelection(collision2, false); - if (!goodEv1 || !goodEv2) { + + bool pass1 = std::abs(daughterPDGs[0]) == kKPlus || std::abs(daughterPDGs[1]) == kKPlus; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == kPiPlus || std::abs(daughterPDGs[1]) == kPiPlus; // At least one decay to Pion + + // Checking if we have both decay products + if (!pass1 || !pass2) + continue; + + // LOGF(info, "Part PDG: %d", part.pdgCode(), "DAU_ID1: %d", pass1, "DAU_ID2: %d", pass2); + + histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), part.phi(), part.y()); + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) // rapidity cut continue; + + if (cfgUseDaughterEtaCutMC) { + for (auto const& daughters : part.daughters_as()) { + if (std::fabs(daughters.eta()) > configTracks.cfgCutEta) + continue; // eta cut for daughters + } // loop over daughters } - TrackSlicingMC(collision1, tracks1, collision2, tracks2, true, false); - } // mixing - } // processMixedEvent_MC - PROCESS_SWITCH(kstar0analysis, processMixedEventMC, "process Mixed Event MC", false); - - //====================================== - //| - //| GENERATED STUFF - //| - //====================================== - int nEventsGen = 0; - void processGen(EventCandidatesTrue::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles) + histos.fill(HIST("QA/MC/h2GenEtaPt_afterRapcut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterRapcut"), part.phi(), part.y()); + + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + { + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genk892pt"), part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantik892pt"), part.pt(), centrality); + } + } + } + PROCESS_SWITCH(Kstar0analysis, processMCGen, "Process Event for MC only", false); + + void processEventFactor(MCEventCandidates const& collisions, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) { - if (cDebugLevel > 0) { - ++nEventsGen; - if (nEventsGen % 10000 == 0) { - std::cout << "Processed MC (GEN) Events: " << nEventsGen << std::endl; + // Loop on reconstructed collisions + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; } + const auto& mcCollision = collision.mcCollision_as>(); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cacheMC); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + bool isInAfterAllCuts = isSelected(collision, false); + + float centrality = mcCollision.centFT0M(); + + if (isTrueINELgt0 && isInAfterAllCuts) + histos.fill(HIST("Event/MultiplicityRecoEv"), centrality); } - //======================= - //|| Event & Signal loss - //======================= - if (cfgMCHistos) { - histos.fill(HIST("nEvents_Gen"), 0.5); + + // Loop on generated collisions to fill the event factor for the INEL>0 correction + for (const auto& mccolls : mcCollisions) { + float centrality = mccolls.centFT0M(); + bool inVtx10 = std::abs(mccolls.posZ()) <= configEvents.cfgEvtZvtx; + + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolls.globalIndex(), cacheMC); + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); // QA for Trigger efficiency + + if (inVtx10 && isTrueINELgt0) + histos.fill(HIST("Event/MultiplicityGenEv"), centrality); } + } + PROCESS_SWITCH(Kstar0analysis, processEventFactor, "Process Event factor", false); + + void processSignalLoss(MCEventCandidates const& collisions, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) + { + // Loop on reconstructed collisions + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + const auto& mcCollision = collision.mcCollision_as>(); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cacheMC); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + bool isInAfterAllCuts = isSelected(collision, false); + bool inVtx10 = std::abs(mcCollision.posZ()) <= configEvents.cfgEvtZvtx; - for (auto& particle : mcParticles) { - if (particle.pdgCode() != 313) + float centrality = mcCollision.centFT0M(); + + // ===== NUM ===== + if (!(inVtx10 && isTrueINELgt0)) continue; - if (std::fabs(particle.eta()) > cfgTrackMaxEta) + + if (!isInAfterAllCuts) continue; - if (fabs(collision.posZ()) > cfgEventVtxCut) - break; - if (cfgMCHistos) { - histos.fill(HIST("hGen_pT_Raw"), particle.pt()); - } - } // Unreconstructed collisions(=Raw coll) for correction + for (const auto& part : particlesInCollision) { + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) + continue; - if (recocolls.size() <= 0) { // not reconstructed - if (cfgForceGenReco) { - return; + float pt = part.pt(); + + // kaon + if (std::abs(part.pdgCode()) == Pdg::kK0Star892) { + if (part.pdgCode() > 0) + histos.fill(HIST("Result/SignalLoss/GenTruek892pt_num"), pt, centrality); + else + histos.fill(HIST("Result/SignalLoss/GenTrueantik892pt_num"), pt, centrality); + } } } - double centrality = -1; - for (auto& recocoll : recocolls) { - centrality = recocoll.centFT0C(); - auto [goodEv, code] = eventSelection(recocoll, true); - if (cfgMCHistos) { - histos.fill(HIST("nEvents_Gen"), 1.5); - } - if (!goodEv) - continue; - } // recocolls (=reconstructed collisions) - - //================= - //|| Efficiency - //================= - for (auto& particle : mcParticles) { - if (particle.pdgCode() != 313) - continue; // Not K*0 - if (std::fabs(particle.eta()) > cfgTrackMaxEta) + // Loop on generated collisions to fill the event factor for the INEL>0 correction + for (const auto& mccolls : mcCollisions) { + float centrality = mccolls.centFT0M(); + + bool inVtx10 = std::abs(mccolls.posZ()) <= configEvents.cfgEvtZvtx; + + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolls.globalIndex(), cacheMC); + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + + if (!(inVtx10 && isTrueINELgt0)) continue; - if (cfgMCHistos) { - histos.fill(HIST("nEvents_Gen"), 2.5); - histos.fill(HIST("hGen_pT_GoodEv"), centrality, particle.pt()); - } // cfgMCHistos - } // loop over particles - } // processMCTrue - PROCESS_SWITCH(kstar0analysis, processGen, "process Generated Particles", false); + for (const auto& part : particlesInCollision) { - void processEventsDummy(EventCandidates::iterator const&, TrackCandidates const&) - { - return; + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) + continue; + + // ========================= + // ===== K(892) ====== + // ========================= + if (std::abs(part.pdgCode()) == Pdg::kK0Star892) { + + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; + } + + bool pass1 = std::abs(daughterPDGs[0]) == kKPlus || std::abs(daughterPDGs[1]) == kKPlus; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == kPiPlus || std::abs(daughterPDGs[1]) == kPiPlus; // At least one decay to Pion + + // Checking if we have both decay products + if (!pass1 || !pass2) + continue; + + if (part.pdgCode() > 0) + histos.fill(HIST("Result/SignalLoss/GenTruek892pt_den"), part.pt(), centrality); + else + histos.fill(HIST("Result/SignalLoss/GenTrueantik892pt_den"), part.pt(), centrality); + } + } + } } - PROCESS_SWITCH(kstar0analysis, processEventsDummy, "dummy", false); -}; // kstar0analysis + PROCESS_SWITCH(Kstar0analysis, processSignalLoss, "Process SignalLoss", false); +}; // Kstar0analysis WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; diff --git a/PWGLF/Tasks/Resonances/phi1020analysis.cxx b/PWGLF/Tasks/Resonances/phi1020analysis.cxx index 609a69af24d..5aa6fcd35ce 100644 --- a/PWGLF/Tasks/Resonances/phi1020analysis.cxx +++ b/PWGLF/Tasks/Resonances/phi1020analysis.cxx @@ -10,13 +10,14 @@ // or submit itself to any jurisdiction. /// \file phi1020analysis.cxx -/// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance OO analysis -/// -/// -/// \author Adrian Fereydon Nassirpour #include #include #include @@ -32,192 +34,383 @@ #include #include #include +#include #include #include #include #include +#include #include +#include #include -#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include #include -#include -#include +#include #include -#include #include -#include - using namespace o2; +using namespace o2::soa; +using namespace o2::aod; +using namespace o2::aod::rctsel; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; -struct phi1020analysis { +using LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; +enum TrackSelectionType { + AllTracks = 0, + GlobalTracks, + GlobalTracksWoPtEta, + GlobalTracksWoDCA, + QualityTracks, + InAcceptanceTracks, +}; + +enum PIDCutType { + SquareType = 1, + CircularType, +}; + +struct Phi1020analysis { + // Define slice per collision + Preslice perCollision = o2::aod::track::collisionId; SliceCache cache; - Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + SliceCache cacheMC; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - // Event configurables - Configurable cfg_Event_Sel{"cfg_Event_Sel", "sel8", "choose event selection"}; - Configurable cfg_Event_VtxCut{"cfg_Event_VtxCut", 10.0, "V_z cut selection"}; - Configurable cfg_Event_Timeframe{"cfg_Event_Timeframe", true, "Timeframe border cut"}; - Configurable cfg_Event_Timerange{"cfg_Event_Timerange", true, "Timerange border cut"}; - Configurable cfg_Event_Centrality{"cfg_Event_Centrality", true, "Centrality cut"}; - Configurable cfg_Event_CentralityMax{"cfg_Event_CentralityMax", 100, "CentralityMax cut"}; - Configurable cfg_Event_Pileup{"cfg_Event_Pileup", true, "Pileup border cut"}; - Configurable cfg_Event_OccupancyCut{"cfg_Event_OccupancyCut", true, "Occupancy border cut"}; - Configurable cfg_Event_MaxOccupancy{"cfg_Event_MaxOccupancy", 1, "Max TPC Occupancy"}; + Service pdg; + RCTFlagsChecker rctChecker; + + struct : ConfigurableGroup { + Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.0f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtNoTFBorderCut{"cfgEvtNoTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtNoITSROFrameBorderCut{"cfgEvtNoITSROFrameBorderCut", false, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgEvtIsRCTFlagpassed{"cfgEvtIsRCTFlagpassed", false, "Evt sel: apply RCT flag selection"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable cfgEvtSel8{"cfgEvtSel8", false, "Evt Sel 8 check for offline selection"}; + Configurable cfgEvtIsINELgt0{"cfgEvtIsINELgt0", false, "Evt sel: apply INEL>0 selection"}; + } configEvents; + + struct : ConfigurableGroup { + // Pre-selection Track cuts + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; + Configurable cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"}; + Configurable cMinTPCNClsFound{"cMinTPCNClsFound", 120, "minimum TPCNClsFound value for good track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgCutRapidity{"cfgCutRapidity", 0.5f, "rapidity range for particles"}; + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"}; + + // DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1f, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1f, "Track DCAz cut to PV Maximum"}; + + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cTPCNClsFound{"cTPCNClsFound", false, "Switch to turn on/off TPCNClsFound cut"}; + Configurable cDCAr7SigCut{"cDCAr7SigCut", false, "Track DCAr 7 Sigma cut to PV Maximum"}; + } configTracks; + + struct : ConfigurableGroup { + /// PID Selections + Configurable pidnSigmaPreSelectionCut{"pidnSigmaPreSelectionCut", 4.0f, "pidnSigma Cut for pre-selection of tracks"}; + Configurable cByPassTOF{"cByPassTOF", false, "By pass TOF PID selection"}; // By pass TOF PID selection + Configurable cPIDcutType{"cPIDcutType", 2, "cPIDcutType = 1 for square cut, 2 for circular cut"}; // By pass TOF PID selection + + // Kaon + Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {0.5f}, "pT intervals for Kaon TPC PID cuts"}; + Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; + Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.0f}, "pT intervals for Kaon TOF PID cuts"}; + Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedpTintv{"kaonTPCTOFCombinedpTintv", {999.0f}, "pT intervals for Kaon TPC-TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedPIDcuts{"kaonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Kaon TPC-TOF PID cuts"}; + } configPID; + + struct : ConfigurableGroup { + /// Event Mixing + Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; + ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}, "Mixing bins - z-vertex"}; + ConfigurableAxis cfgMultPercentileBins{"cfgMultPercentileBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - multiplicity"}; + + // Rotational background + Configurable rotationalcut{"rotationalcut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable cNofRotations{"cNofRotations", 3, "Number of random rotations in the rotational background"}; + Configurable cfgRotTrk1{"cfgRotTrk1", true, "rotate Kaon 1"}; + } configBkg; + + // Additional purity check + Configurable crejectPion{"crejectPion", false, "Switch to turn on/off pion contamination"}; + Configurable cUseOpeningAngleCut{"cUseOpeningAngleCut", false, "Kinematic Cuts for p-K pair opening angle"}; + Configurable cMinOpeningAngle{"cMinOpeningAngle", 1.4f, "Minimum opening angle between daughters"}; + Configurable cMaxOpeningAngle{"cMaxOpeningAngle", 2.4f, "Maximum opening angle between daughters"}; + Configurable cfgUseDeltaEtaPhiCuts{"cfgUseDeltaEtaPhiCuts", false, "Switch to turn on/off delta eta and delta phi cuts"}; + Configurable cfgUseDaughterEtaCutMC{"cfgUseDaughterEtaCutMC", false, "Switch to turn on/off eta cuts for daughters in MC"}; + + // MC selection cut + Configurable cUseRapcutMC{"cUseRapcutMC", true, "Use rapidity cut for MC"}; + + // cuts on mother + Configurable cfgUseCutsOnMother{"cfgUseCutsOnMother", false, "Enable additional cuts on mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 15.0f, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 1.5f, "Maximum Minv of mother cut"}; + Configurable cMaxDeltaEtaCut{"cMaxDeltaEtaCut", 0.7f, "Maximum deltaEta between daughters"}; + Configurable cMaxDeltaPhiCut{"cMaxDeltaPhiCut", 1.5f, "Maximum deltaPhi between daughters"}; + + // switches + Configurable cFillMultQA{"cFillMultQA", false, "Turn on/off additional QA plots"}; + Configurable cFillTrackQA{"cFillTrackQA", false, "Turn on/off additional QA plots"}; + Configurable cFilladditionalQAeventPlots{"cFilladditionalQAeventPlots", false, "Additional QA event plots"}; + Configurable cFilladditionalMEPlots{"cFilladditionalMEPlots", false, "Additional Mixed event plots"}; + Configurable cFilldeltaEtaPhiPlots{"cFilldeltaEtaPhiPlots", false, "Enable additional cuts on daughters"}; + Configurable cFill1DQAs{"cFill1DQAs", false, "Invariant mass 1D"}; Configurable centEstimator{"centEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; - // Track configurables - Configurable cfg_Track_Sel{"cfg_Track_Sel", "globalTracks", "set track selections"}; - Configurable cfg_Track_MinPt{"cfg_Track_MinPt", 0.15, "set track min pT"}; - Configurable cfg_Track_MaxEta{"cfg_Track_MaxEta", 0.9, "set track max Eta"}; - Configurable cfg_Track_MaxDCArToPVcut{"cfg_Track_MaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; - Configurable cfg_Track_MaxDCAzToPVcut{"cfg_Track_MaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; - Configurable cfg_Track_PrimaryTrack{"cfg_Track_PrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfg_Track_ConnectedToPV{"cfg_Track_ConnectedToPV", true, "PV contributor track selection"}; // PV Contributor - Configurable cfg_Track_GlobalWoDCATrack{"cfg_Track_GlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cfg_Track_nFindableTPCClusters{"cfg_Track_FindableTPCClusters", 50, "nFindable TPC Clusters"}; - Configurable cfg_Track_nTPCCrossedRows{"cfg_Track_TPCCrossedRows", 70, "nCrossed TPC Rows"}; - Configurable cfg_Track_nRowsOverFindable{"cfg_Track_RowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; - Configurable cfg_Track_nTPCChi2{"cfg_Track_TPCChi2", 4.0, "nTPC Chi2 per Cluster"}; - Configurable cfg_Track_nITSChi2{"cfg_Track_ITSChi2", 36.0, "nITS Chi2 per Cluster"}; - Configurable cfg_Track_TPCPID{"cfg_Track_TPCPID", true, "Enables TPC PID"}; - Configurable cfg_Track_TOFPID{"cfg_Track_TOFPID", true, "Enables TOF PID"}; - Configurable cfg_Track_Hard_TOFPID{"cfg_Track_Hard_TOFPID", true, "Enables STRICT TOF Reqruirement"}; - Configurable cfg_Track_TPCPID_nSig{"cfg_Track_TPCPID_nSig", 4, "nTPC PID sigma"}; - Configurable cfg_Track_TOFPID_nSig{"cfg_Track_TOFPID_nSig", 4, "nTOF PID sigma"}; - Configurable cfg_Track_Explicit_PID{"cfg_Track_Explicit_PID", true, "Enables explicit pid cehck"}; - Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; - - // Pair configurables - Configurable cfg_Pair_MinvBins{"cfg_Pair_MinvBins", 300, "Number of bins for Minv axis"}; - Configurable cfg_Pair_MinvMin{"cfg_Pair_MinvMin", 0.90, "Minimum Minv value"}; - Configurable cfg_Pair_MinvMax{"cfg_Pair_MinvMax", 1.50, "Maximum Minv value"}; - - Configurable cfg_Mix_NMixedEvents{"cfg_Mix_NMixedEvents", 5, "Number of mixed events per event"}; - - // MCGen configurables - Configurable cfg_Force_GenReco{"cfg_Force_GenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; - Configurable cfg_Force_BR{"cfg_Force_BR", false, "Only consider phi->K+K-"}; - Configurable cfg_Force_Kaon_Acceptence{"cfg_Force_Kaon_Acceptence", false, "Only consider phi's whose daughters decay inside acceptence (no signal loss)"}; - - // Histogram Configurables - Configurable cfg_Event_CutQA{"cfg_Event_CutsQA", true, "Enables Track QA plots"}; - Configurable cfg_Track_CutQA{"cfg_Track_CutsQA", true, "Enables Track QA plots"}; - - // Configurables for axis - ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; - ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; - ConfigurableAxis cfg_bins_Cent{"cfg_bins_Cent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0}, "Binning of the centrality axis"}; - ConfigurableAxis cfg_bins_MixVtx{"cfg_bins_MixVtx", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis cfg_bins_MixMult{"cfg_bins_MixMult", {VARIABLE_WIDTH, 0.0f, 1.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f}, "Mixing bins - z-vertex"}; + TRandom* rn = new TRandom(); + + // Pre-filters for efficient process + Filter zVtxFilter = (nabs(o2::aod::collision::posZ) <= configEvents.cfgEvtZvtx); + Filter collisionFilterMC = nabs(aod::mccollision::posZ) <= configEvents.cfgEvtZvtx; + + Filter acceptanceFilter = (nabs(aod::track::eta) < configTracks.cfgCutEta && nabs(aod::track::pt) > configTracks.cMinPtcut) && + (nabs(aod::track::dcaXY) < configTracks.cMaxDCArToPVcut) && (nabs(aod::track::dcaZ) < configTracks.cMaxDCAzToPVcut); + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Filtered>; + + // for MC reco + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Filtered>; + + Partition posKaon = aod::track::signed1Pt > static_cast(0); + Partition negKaon = aod::track::signed1Pt < static_cast(0); + + Partition PosKaon_MC = aod::track::signed1Pt > static_cast(0); + Partition NegKaon_MC = aod::track::signed1Pt < static_cast(0); + + /// Figures + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.12f, 0.14f, 0.16f, 0.18f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.5f, 0.55f, 0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.75f, 1.8f, 1.9f, 2.0f, 2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f, 3.0f, 3.1f, 3.2f, 3.3f, 3.4f, 3.6f, 3.7f, 3.8f, 3.9f, 4.0f, 4.1f, 4.2f, 4.5f, 4.6f, 4.8f, 4.9f, 5.0f, 5.5f, 5.6f, 6.0f, 6.4f, 6.5f, 7.0f, 7.2f, 8.0f, 9.0f, 9.5f, 9.6f, 10.0f, 11.0f, 11.5f, 12.0f, 13.0f, 14.0f, 14.4f, 15.0f, 16.0f, 18.0f, 19.2f, 20.0f}, "Binning of the pT axis"}; + ConfigurableAxis binsEta{"binsEta", {150, -1.5f, 1.5f}, ""}; + ConfigurableAxis binsMass{"binsMass", {300, 0.9f, 1.6f}, "Invariant Mass (GeV/#it{c}^2)"}; + ConfigurableAxis binsMult{"binsMult", {105, 0.0f, 105.0f}, "mult_{FT0M}"}; + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsTPCXrows{"binsTPCXrows", {100, 60, 160}, ""}; + ConfigurableAxis binsnSigma{"binsnSigma", {130, -6.5f, 6.5f}, ""}; + ConfigurableAxis binsnTPCSignal{"binsnTPCSignal", {1000, 0, 1000}, ""}; + ConfigurableAxis binsEtaPhi{"binsEtaPhi", {350, -3.5f, 3.5f}, ""}; void init(o2::framework::InitContext&) { - const AxisSpec MinvAxis = {cfg_Pair_MinvBins, cfg_Pair_MinvMin, cfg_Pair_MinvMax}; - const AxisSpec PtAxis = {200, 0, 20.0}; - const AxisSpec MultAxis = {100, 0, 100}; - const AxisSpec dRAxis = {100, 0, 100}; - const AxisSpec pidAxis = {100, -5, 5}; - const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; - const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; - - // Event QA - if (cfg_Event_CutQA) { - histos.add("hPosZ_BC", "PosZ_BC", kTH1F, {{240, -12.0, 12.0}}); - histos.add("hcentFT0_BC", "centFT0_BC", kTH1F, {{110, 0.0, 110.0}}); - histos.add("hOccupancy_BC", "Occupancy_BC", kTH1F, {{100, 0.0, 20000}}); - // - histos.add("hcentFT0_AC", "centFT0_AC", kTH1F, {{110, 0.0, 110.0}}); - histos.add("hPosZ_AC", "PosZ_AC", kTH1F, {{240, -12.0, 12.0}}); - histos.add("hOccupancy_AC", "Occupancy_AC", kTH1F, {{100, 0.0, 20000}}); + rctChecker.init(configEvents.cfgEvtRCTFlagCheckerLabel, configEvents.cfgEvtRCTFlagCheckerZDCCheck, configEvents.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + // axes + AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{binsEta, "#eta"}; + AxisSpec axisRap{binsEta, "#it{y}"}; + AxisSpec axisMassphi1020{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec axisMult{binsMult, "mult_{FT0M}"}; + AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; + AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; + AxisSpec axisPIDQA{binsnSigma, "#sigma"}; + AxisSpec axisTPCSignal{binsnTPCSignal, ""}; + AxisSpec axisEtaPhi{binsEtaPhi, ""}; + AxisSpec axisPhi{350, 0, 7, "#Phi"}; + AxisSpec axisMultMix{configBkg.cfgMultPercentileBins, "Multiplicity Percentile"}; + AxisSpec axisVtxMix{configBkg.cfgVtxBins, "Vertex Z (cm)"}; + + histos.add("CollCutCounts", "No. of event after cuts", kTH1I, {{10, 0, 10}}); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(1, "All Events"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(2, "|Vz| < cut"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(6, "rctChecker"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(7, "sel8"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(8, "IsINELgt0"); + histos.get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(9, "All Passed Events"); + + histos.add("Event/posZ", "; vtx_{z} (cm); Entries", HistType::kTH1F, {{250, -12.5, 12.5}}); + histos.add("Event/centFT0M", "; FT0M Percentile; Entries", HistType::kTH1F, {{110, 0, 110}}); + + if (cFilladditionalQAeventPlots) { + // event histograms + if (doprocessData) { + histos.add("QAevent/hPairsCounterSameE", "total valid no. of pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0, 1000.0}}); + } + // Gen on Mixed event + if (doprocessME) { + + // Histograms for Mixed Event Pool characteristics + histos.add("QAevent/hMixPool_VtxZ", "Mixed Event Pool: Vertex Z;Vtx Z (cm);Counts", HistType::kTH1F, {axisVtxMix}); + histos.add("QAevent/hMixPool_Multiplicity", "Mixed Event Pool: Multiplicity;Multiplicity;Counts", HistType::kTH1F, {axisMultMix}); + histos.add("QAevent/hMixPool_VtxZ_vs_Multiplicity", "Mixed Event Pool: Vertex Z vs Multiplicity;Counts", HistType::kTH2F, {axisVtxMix, axisMultMix}); + + histos.add("QAevent/hPairsCounterMixedE", "total valid no. of pairs mixedE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("QAevent/hVertexZMixedE", "Collision Vertex Z position", HistType::kTH1F, {{100, -15.0f, 15.0f}}); + histos.add("QAevent/hMultiplicityPercentMixedE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); + histos.add("QAevent/hnTrksMixedE", "n tracks per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + } } - // Track QA - if (cfg_Track_CutQA) { - histos.add("hDCArToPv_BC", "DCArToPv_BC", kTH1F, {axisDCAxy}); - histos.add("hDCAzToPv_BC", "DCAzToPv_BC", kTH1F, {axisDCAz}); - histos.add("hIsPrim_BC", "hIsPrim_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsGood_BC", "hIsGood_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsPrimCont_BC", "hIsPrimCont_BC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hFindableTPCClusters_BC", "hFindableTPCClusters_BC", kTH1F, {{200, 0, 200}}); - histos.add("hFindableTPCRows_BC", "hFindableTPCRows_BC", kTH1F, {{200, 0, 200}}); - histos.add("hClustersVsRows_BC", "hClustersVsRows_BC", kTH1F, {{200, 0, 2}}); - histos.add("hTPCChi2_BC", "hTPCChi2_BC", kTH1F, {{200, 0, 100}}); - histos.add("hITSChi2_BC", "hITSChi2_BC", kTH1F, {{200, 0, 100}}); - histos.add("hTPC_nSigma_BC", "hTPC_nSigma_BC", kTH1F, {pidAxis}); - histos.add("hTOF_nSigma_BC", "hTOF_nSigma_BC", kTH1F, {pidAxis}); - histos.add("hTPC_nSigma_v_pt_BC", "hTPC_nSigma_v_pt_BC", HistType::kTHnSparseD, {pidAxis, PtAxis}); - histos.add("hTOF_nSigma_v_pt_BC", "hTOF_nSigma_v_pt_BC", HistType::kTHnSparseD, {pidAxis, PtAxis}); - // - histos.add("hDCArToPv_AC", "DCArToPv_AC", kTH1F, {axisDCAxy}); - histos.add("hDCAzToPv_AC", "DCAzToPv_AC", kTH1F, {axisDCAz}); - histos.add("hIsPrim_AC", "hIsPrim_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsGood_AC", "hIsGood_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hIsPrimCont_AC", "hIsPrimCont_AC", kTH1F, {{2, -0.5, 1.5}}); - histos.add("hFindableTPCClusters_AC", "hFindableTPCClusters_AC", kTH1F, {{200, 0, 200}}); - histos.add("hFindableTPCRows_AC", "hFindableTPCRows_AC", kTH1F, {{200, 0, 200}}); - histos.add("hClustersVsRows_AC", "hClustersVsRows_AC", kTH1F, {{200, 0, 2}}); - histos.add("hTPCChi2_AC", "hTPCChi2_AC", kTH1F, {{200, 0, 100}}); - histos.add("hITSChi2_AC", "hITSChi2_AC", kTH1F, {{200, 0, 100}}); - histos.add("hTPC_nSigma_AC", "hTPC_nSigma_AC", kTH1F, {pidAxis}); - histos.add("hTOF_nSigma_AC", "hTOF_nSigma_AC", kTH1F, {pidAxis}); - histos.add("hTPC_nSigma_v_pt_AC", "hTPC_nSigma_v_pt_AC", HistType::kTHnSparseD, {pidAxis, PtAxis}); - histos.add("hTOF_nSigma_v_pt_AC", "hTOF_nSigma_v_pt_AC", HistType::kTHnSparseD, {pidAxis, PtAxis}); + + if (doprocessData) { + // Track QA before cuts + // --- Track + if (cFillTrackQA) { + histos.add("QA/QAbefore/Track/TOF_TPC_Map_all", "TOF + TPC Combined PID for All Kaons;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_all", "TOF NSigma for All Kaons;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_all", "TPC NSigma for All Kaons;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_all", "TPC NSigma for All Kaons;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/dcaZ_all", "DCA_{Z} distribution of selected All Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY_all", "DCA_{XY} momentum distribution of All Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR_all", "# TPC Xrows distribution of All Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/pT_all", "pT distribution of All Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAbefore/Track/eta_all", "#eta distribution of All Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + } + if (cFillMultQA) { + // Multiplicity correlation calibrations + histos.add("MultCalib/centGloPVTrk1", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + histos.add("MultCalib/centGloPVTrk2", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + } + + // PID QA after cuts + // --- Track 1 + histos.add("QA/QAafter/Trk1/TOF_TPC_Map_selected", "TOF + TPC Combined PID for selected Kaon 1;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Trk1/TOF_Nsigma_selected", "TOF NSigma for selected Kaon 1;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk1/TPC_Nsigma_selected", "TPC NSigma for selected Kaon 1;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk1/TPC_Nsigma_TPConly_selected", "TPC NSigma for selected Kaon 1;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk1/dcaZ_selected", "DCA_{Z} distribution of selected Kaon 1; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Trk1/dcaXY_selected", "DCA_{XY} momentum distribution of selected Kaon 1; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Trk1/TPC_CR_selected", "# TPC Xrows distribution of selected Kaon 1; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Trk1/pT_selected", "pT distribution of selected Kaon 1; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Trk1/eta_selected", "#eta distribution of selected Kaon 1; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Trk1/TPC_Signal_selected", "TPC Signal for selected Kaon 1;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Trk1/TPCnclusterPhipr_selected", "TPC ncluster vs phi for selected Kaon 1", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // --- Track 2 + histos.add("QA/QAafter/Trk2/TOF_TPC_Map_selected", "TOF + TPC Combined PID for selected Kaon 2;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Trk2/TOF_Nsigma_selected", "TOF NSigma for selected Kaon 2;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk2/TPC_Nsigma_selected", "TPC NSigma for selected Kaon 2;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk2/TPC_Nsigma_TPConly_selected", "TPC NSigma for selected Kaon 2;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Trk2/dcaZ_selected", "DCA_{Z} distribution of selected Kaon 2; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Trk2/dcaXY_selected", "DCA_{XY} momentum distribution of selected Kaon 2; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Trk2/TPC_CR_selected", "# TPC Xrows distribution of selected Kaon 2; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Trk2/pT_selected", "pT distribution of selected Kaon 2; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Trk2/eta_selected", "#eta distribution of selected Kaon 2; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Trk2/TPC_Signal_selected", "TPC Signal for selected Kaon 2;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Trk2/TPCnclusterPhika_selected", "TPC ncluster vs phi for selected Kaon 2", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // Mass QA 1D for quick check + if (cFill1DQAs) { + histos.add("Result/Data/phi1020invmass", "Invariant mass of #phi(1020) K^{#pm}K^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); + histos.add("Result/Data/phi1020invmassLSPP", "Invariant mass of #phi(1020) Like Sign Method K^{#plus}K^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); // K+ + K+ + histos.add("Result/Data/phi1020invmassLSMM", "Invariant mass of #phi(1020) Like Sign Method K^{#minus}K^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); // K- + K- + } + // eta phi QA + if (cFilldeltaEtaPhiPlots) { + histos.add("QAbefore/deltaEta", "deltaEta of kaon 1 and 2 candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAbefore/deltaPhi", "deltaPhi of kaon 1 and 2 candidates", HistType::kTH1F, {axisEtaPhi}); + + histos.add("QAafter/deltaEta", "deltaEta of kaon 1 and 2 candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAafter/deltaPhi", "deltaPhi of kaon 1 and 2 candidates", HistType::kTH1F, {axisEtaPhi}); + + histos.add("QAafter/PhiafterTrk1", "Phi of kaon 1 candidates", HistType::kTH1F, {axisPhi}); + histos.add("QAafter/PhiafterTrk2", "Phi of kaon 2 candidates", HistType::kTH1F, {axisPhi}); + } + + // 3d histogram + histos.add("Result/Data/h3phi1020invmass", "Invariant mass of #phi(1020) K^{#pm}K^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); + histos.add("Result/Data/h3phi1020invmassLSPP", "Invariant mass of #phi(1020) Like Sign Method K^{#plus}K^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); // K+ + K+ + histos.add("Result/Data/h3phi1020invmassLSMM", "Invariant mass of #phi(1020) Like Sign Method K^{#minus}K^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); // K- + K- + } + + if (doprocessRotational) { + if (cFill1DQAs) { + histos.add("Result/Data/phi1020InvMassRotation", "Invariant mass of #phi(1020) rotational Method K^{#plus}K^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); // K+ + K+ + } + histos.add("Result/Data/h3phi1020InvMassRotation", "Invariant mass of #phi(1020) rotational Method K^{#plus}K^{#plus}", kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); + } + // Mixed event histograms + if (doprocessME) { + if (cFill1DQAs) { + histos.add("Result/Data/phi1020invmassME", "Invariant mass of #phi(1020) mixed event K^{#pm}K^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); + } + histos.add("Result/Data/h3phi1020invmassME", "Invariant mass of #phi(1020) mixed event K^{#pm}K^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); + + if (cFilladditionalMEPlots) { + if (cFill1DQAs) { + histos.add("Result/Data/phi1020invmassME_LSPP", "Invariant mass of #phi(1020) Like Sign Method K^{#plus}K^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); // K+ + K+ + histos.add("Result/Data/phi1020invmassME_LSMM", "Invariant mass of #phi(1020) Like Sign Method K^{#minus}K^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassphi1020}}); // K- + K- + } + histos.add("Result/Data/h3phi1020invmassME_LSPP", "Invariant mass of #phi(1020) mixed event Like Sign Method K^{#plus}K^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); // K+ + K+ + histos.add("Result/Data/h3phi1020invmassME_LSMM", "Invariant mass of #phi(1020) mixed event Like Sign Method K^{#minus}K^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); // K- + K- + } } - // Data histos - histos.add("hUSS", "hUSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hLSS", "hLSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hUSS_Mix", "hUSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hLSS_Mix", "hLSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - - // MC histos - histos.add("hMC_USS", "hMC_USS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hMC_LSS", "hMC_LSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hMC_USS_Mix", "hMC_USS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hMC_LSS_Mix", "hMC_LSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hMC_USS_True", "hMC_USS_True", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); - histos.add("hMC_Phi_True", "hMC_Phi_True", HistType::kTHnSparseD, {cfg_bins_Cent, PtAxis}); - - // Event Histograms - histos.add("hnEvents", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); - histos.add("hnEvents_MC", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); - histos.add("hnEvents_MC_True", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); + // MC QA + if (doprocessEventFactor) { + histos.add("Event/MultiplicityGenEv", "hMCEventIndices", kTH1D, {axisMult}); + histos.add("Event/MultiplicityRecoEv", "Multiplicity of Reconstructed Events", kTH1D, {axisMult}); + } + + if (doprocessMCGen) { + histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #phi(1020); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); + histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #phi(1020); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterRapcut", " #phi-#it{p}_{T} distribution of Generated #phi(1020); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); + histos.add("QA/MC/h2GenPhiRapidity_afterRapcut", " #phi-y distribution of Generated #phi(1020); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + + histos.add("Result/MC/Genphi1020pt", "pT distribution of True MC #phi(1020)0", kTH2F, {axisPt, axisMult}); + } + + if (doprocessMCRec) { + histos.add("QA/MC/h2RecoEtaPt_after", " #eta-#it{p}_{T} distribution of Reconstructed #phi(1020); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); + histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #phi(1020); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + + histos.add("QA/MC/trkDCAxy_Trk1", "DCAxy distribution of kaon 1 track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAxy_Trk2", "DCAxy distribution of kaon 2 track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAz_Trk1", "DCAz distribution of kaon 1 track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/trkDCAz_Trk2", "DCAz distribution of kaon 2 track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/TOF_Nsigma_selected_Trk1", "TOF NSigma for Kaon 1;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_selected_Trk1", "TPC NSigma for Kaon 1;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TOF_Nsigma_selected_Trk2", "TOF NSigma for Kaon 2;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_selected_Trk2", "TPC NSigma for Kaon 2;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + + histos.add("Result/MC/h3phi1020Recoinvmass", "Invariant mass of Reconstructed MC #phi(1020)0", kTHnSparseF, {axisMult, axisPt, axisMassphi1020}); + } + + if (doprocessSignalLoss) { + histos.add("Result/SignalLoss/GenTruephi1020pt_den", "True phi1020 (den)", kTH2F, {axisPt, axisMult}); + + histos.add("Result/SignalLoss/GenTruephi1020pt_num", "True phi1020 (num)", kTH2F, {axisPt, axisMult}); + } + + // Print output histograms statistics + LOG(info) << "Size of the histograms in Phi1020analysis:"; + histos.print(); } // end of init - Filter collisionFilter = nabs(aod::collision::posZ) <= cfg_Event_VtxCut; - Filter collisionFilter_MC = nabs(aod::mccollision::posZ) <= cfg_Event_VtxCut; - // Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; - Filter acceptanceFilter = (nabs(aod::track::eta) < cfg_Track_MaxEta && nabs(aod::track::pt) >= cfg_Track_MinPt); - using EventCandidates = soa::Filtered>; - using EventCandidates_True = soa::Filtered; - - using TrackCandidates = soa::Filtered>; - using TrackCandidates_MC = soa::Filtered>; - - using BinningTypeVtxCent = ColumnBinningPolicy; - - Partition PosKaon_MC = - (aod::track::signed1Pt > static_cast(0)) && - (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); - Partition NegKaon_MC = - (aod::track::signed1Pt < static_cast(0)) && - (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); - Partition PosKaon = - (aod::track::signed1Pt > static_cast(0)) && - (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); - Partition NegKaon = - (aod::track::signed1Pt < static_cast(0)) && - (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); - - double massKa = o2::constants::physics::MassKPlus; + float massKa = MassKaonCharged; // Centralicity estimator selection template @@ -241,452 +434,764 @@ struct phi1020analysis { return returnValue; } - //***********************************// - // First, we declare some helper functions - template - void fillQA(const bool pass, const objType& obj, const int objecttype = 0) + template + bool isSelected(const Coll& collision, bool fillHist = true) { + auto applyCut = [&](bool enabled, bool condition, int bin) { + if (!enabled) + return true; + if (!condition) + return false; + if (fillHist) + histos.fill(HIST("CollCutCounts"), bin); + return true; + }; - if (objecttype == 1) { - if constexpr (requires { obj.posZ(); }) { - if (!pass) { - histos.fill(HIST("hPosZ_BC"), obj.posZ()); - histos.fill(HIST("hcentFT0_BC"), centEst(obj)); - } else { - histos.fill(HIST("hPosZ_AC"), obj.posZ()); - histos.fill(HIST("hcentFT0_AC"), centEst(obj)); - } - } - } - if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { - if (objecttype == 2) { - if (!pass) { - histos.fill(HIST("hDCArToPv_BC"), obj.dcaXY()); - histos.fill(HIST("hDCAzToPv_BC"), obj.dcaZ()); - histos.fill(HIST("hIsPrim_BC"), obj.isPrimaryTrack()); - histos.fill(HIST("hIsGood_BC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_BC"), obj.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_BC"), obj.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_BC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_BC"), obj.tpcChi2NCl()); - } else { - histos.fill(HIST("hDCArToPv_AC"), obj.dcaXY()); - histos.fill(HIST("hDCAzToPv_AC"), obj.dcaZ()); - histos.fill(HIST("hIsPrim_AC"), obj.isPrimaryTrack()); - histos.fill(HIST("hIsGood_AC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_AC"), obj.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_AC"), obj.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_AC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_AC"), obj.tpcChi2NCl()); - } - } - if (objecttype == 3) { - if (!pass) { - histos.fill(HIST("hTPC_nSigma_BC"), obj.tpcNSigmaKa()); - histos.fill(HIST("hTOF_nSigma_BC"), obj.tofNSigmaKa()); - histos.fill(HIST("hTPC_nSigma_v_pt_BC"), obj.tpcNSigmaKa(), obj.pt()); - histos.fill(HIST("hTOF_nSigma_v_pt_BC"), obj.tofNSigmaKa(), obj.pt()); - } else { - histos.fill(HIST("hTPC_nSigma_AC"), obj.tpcNSigmaKa()); - histos.fill(HIST("hTOF_nSigma_AC"), obj.tofNSigmaKa()); - histos.fill(HIST("hTPC_nSigma_v_pt_AC"), obj.tpcNSigmaKa(), obj.pt()); - histos.fill(HIST("hTOF_nSigma_v_pt_AC"), obj.tofNSigmaKa(), obj.pt()); - } - } - } - }; - //***********************************// + if (fillHist) + histos.fill(HIST("CollCutCounts"), 0); - // evsel - template - std::pair eventSelection(const EventType event, const bool QA) - { + if (!applyCut(true, std::abs(collision.posZ()) <= configEvents.cfgEvtZvtx, 1)) + return false; - if (cfg_Track_CutQA && QA) - fillQA(false, event, 1); - - if (!event.sel8()) - return {false, 1}; - if (std::abs(event.posZ()) > cfg_Event_VtxCut) - return {false, 2}; - if (cfg_Event_Timeframe && (!event.selection_bit(aod::evsel::kNoTimeFrameBorder) || !event.selection_bit(aod::evsel::kNoITSROFrameBorder))) - return {false, 3}; - if (cfg_Event_Timerange && (!event.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) - return {false, 4}; - if (cfg_Event_Pileup && (!event.selection_bit(aod::evsel::kNoSameBunchPileup) || !event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) - return {false, 5}; - if (cfg_Event_Centrality && (centEst(event) > cfg_Event_CentralityMax)) - return {false, 6}; - if (cfg_Event_OccupancyCut && (event.trackOccupancyInTimeRange() > cfg_Event_MaxOccupancy)) - return {false, 7}; - - if (cfg_Track_CutQA && QA) - fillQA(true, event, 1); - - return {true, 8}; - }; - - // tracksel - template - bool trackSelection(const TrackType track, const bool QA) - { - if (cfg_Track_CutQA && QA) - fillQA(false, track, 2); + if (!applyCut(configEvents.cfgEvtTriggerTVXSel, + collision.selection_bit(aod::evsel::kIsTriggerTVX), 2)) + return false; - // basic track cuts - if (track.pt() < cfg_Track_MinPt) + if (!applyCut(configEvents.cfgEvtNoTFBorderCut, + collision.selection_bit(aod::evsel::kNoTimeFrameBorder), 3)) + return false; + + if (!applyCut(configEvents.cfgEvtNoITSROFrameBorderCut, + collision.selection_bit(aod::evsel::kNoITSROFrameBorder), 4)) + return false; + + if (!applyCut(configEvents.cfgEvtIsRCTFlagpassed, rctChecker(collision), 5)) return false; - if (std::abs(track.eta()) > cfg_Track_MaxEta) + + if (!applyCut(configEvents.cfgEvtSel8, collision.sel8(), 6)) return false; - if (std::abs(track.dcaXY()) > cfg_Track_MaxDCArToPVcut) + + if (!applyCut(configEvents.cfgEvtIsINELgt0, collision.isInelGt0(), 7)) return false; - if (std::abs(track.dcaZ()) > cfg_Track_MaxDCAzToPVcut) + + if (fillHist) + histos.fill(HIST("CollCutCounts"), 8); + + return true; + } + + template + bool trackCut(const TrackType track) + { + // basic track cuts + if (configTracks.cDCAr7SigCut && std::abs(track.dcaXY()) > (0.004f + 0.013f / (track.pt()))) // 7 - Sigma cut return false; - if (cfg_Track_PrimaryTrack && !track.isPrimaryTrack()) + if (configTracks.cTPCNClsFound && (track.tpcNClsFound() < configTracks.cMinTPCNClsFound)) return false; - if (track.tpcNClsFindable() < cfg_Track_nFindableTPCClusters) + if (track.tpcNClsCrossedRows() < configTracks.cfgMinCrossedRows) return false; - if (track.tpcNClsCrossedRows() < cfg_Track_nTPCCrossedRows) + if (configTracks.cfgHasTOF && !track.hasTOF()) return false; - if (track.tpcCrossedRowsOverFindableCls() > cfg_Track_nRowsOverFindable) + if (configTracks.cfgPrimaryTrack && !track.isPrimaryTrack()) return false; - if (track.tpcChi2NCl() > cfg_Track_nTPCChi2) + if (configTracks.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (track.itsChi2NCl() > cfg_Track_nITSChi2) + if (configTracks.cfgPVContributor && !track.isPVContributor()) return false; - if (cfg_Track_ConnectedToPV && !track.isPVContributor()) + if (configTracks.cfgGlobalTrack && !track.isGlobalTrack()) return false; - if (cfg_Track_CutQA && QA) - fillQA(true, track, 2); return true; - }; - - // trackpid + } - template - bool trackPIDKaon(const TrackPID& candidate, const bool QA) + template + bool ptDependentPidKaon(const T& candidate) { - bool tpcPIDPassed{false}, tofPIDPassed{false}; + auto vKaonTPCPIDpTintv = configPID.kaonTPCPIDpTintv.value; + vKaonTPCPIDpTintv.insert(vKaonTPCPIDpTintv.begin(), configTracks.cMinPtcut); + auto vKaonTPCPIDcuts = configPID.kaonTPCPIDcuts.value; + auto vKaonTOFPIDpTintv = configPID.kaonTOFPIDpTintv.value; + auto vKaonTPCTOFCombinedpTintv = configPID.kaonTPCTOFCombinedpTintv.value; + auto vKaonTPCTOFCombinedPIDcuts = configPID.kaonTPCTOFCombinedPIDcuts.value; + auto vKaonTOFPIDcuts = configPID.kaonTOFPIDcuts.value; + + float pt = candidate.pt(); + float ptSwitchToTOF = vKaonTPCPIDpTintv.back(); + float tpcNsigmaKa = candidate.tpcNSigmaKa(); + float tofNsigmaKa = candidate.tofNSigmaKa(); + + bool tpcPIDPassed = false; + + // TPC PID interval-based check + for (size_t i = 0; i < vKaonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vKaonTPCPIDpTintv[i] && pt < vKaonTPCPIDpTintv[i + 1]) { + if (std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts[i]) { + tpcPIDPassed = true; + break; + } + } + } - if (cfg_Track_CutQA && QA) - fillQA(false, candidate, 3); + // TOF bypass option + if (configPID.cByPassTOF) { + return std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back(); + } - if (!cfg_Track_TPCPID) { - tpcPIDPassed = true; - } else { - if (std::abs(candidate.tpcNSigmaKa()) < cfg_Track_TPCPID_nSig) - tpcPIDPassed = true; + // Case 1: No TOF and pt ≤ ptSwitch → use TPC-only + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; } - if (!cfg_Track_TOFPID) { - tofPIDPassed = true; - } else { - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaKa()) < cfg_Track_TOFPID_nSig) { - tofPIDPassed = true; - } - } else if (!cfg_Track_Hard_TOFPID) { - tofPIDPassed = true; - } - if (!candidate.hasTOF()) { - // std::cout << candidate.tofNSigmaKa() << std::endl; - } + // Case 2: No TOF but pt > ptSwitch → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; } - if (tpcPIDPassed && tofPIDPassed) { - if (cfg_Track_CutQA && QA) { - fillQA(true, candidate, 3); + + // Case 3: TOF is available → apply TPC+TOF PID logic + if (candidate.hasTOF()) { + if (configPID.cPIDcutType == SquareType) { + // Rectangular cut + for (size_t i = 0; i < vKaonTOFPIDpTintv.size(); ++i) { + if (pt < vKaonTOFPIDpTintv[i]) { + if (std::abs(tofNsigmaKa) < vKaonTOFPIDcuts[i] && + std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back()) { + return true; + } + } + } + } else if (configPID.cPIDcutType == CircularType) { + // Circular cut + for (size_t i = 0; i < vKaonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vKaonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = tpcNsigmaKa * tpcNsigmaKa + + tofNsigmaKa * tofNsigmaKa; + if (combinedSigma2 < vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i]) { + return true; + } + } + } } - return true; } + return false; } - template - void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool QA, const bool IsMix) + auto static constexpr MinPtforPionRejection = 1.0f; + auto static constexpr MaxPtforPionRejection = 2.0f; + auto static constexpr MaxnSigmaforPionRejection = 2.0f; + + template + bool rejectPion(const T& candidate) { - auto slicedtracks1 = PosKaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); - auto slicedtracks2 = NegKaon->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = centEst(collision1); - for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { - auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); - if (Minv < 0) + if (candidate.pt() > MinPtforPionRejection && candidate.pt() < MaxPtforPionRejection && !candidate.hasTOF() && candidate.tpcNSigmaPi() < MaxnSigmaforPionRejection) { + return false; + } + return true; + } + + auto static constexpr MaxNophi1020Daughters = 2; + + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto centrality = centEst(collision); + + // Multiplicity correlation calibration plots + if (cFillMultQA) { + if constexpr (IsData) { + histos.fill(HIST("MultCalib/centGloPVTrk1"), centrality, dTracks1.size(), collision.multNTracksPV()); + histos.fill(HIST("MultCalib/centGloPVTrk2"), centrality, dTracks2.size(), collision.multNTracksPV()); + } + } + + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hnTrksSameE"), dTracks1.size()); + } else if constexpr (IsMix) { + histos.fill(HIST("QAevent/hVertexZMixedE"), collision.posZ()); + histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), centrality); + histos.fill(HIST("QAevent/hnTrksMixedE"), dTracks1.size()); + } + } + // LOG(info) << "After pass, Collision index:" << collision.index() << "multiplicity: " << collision.centFT0M() << endl; + + LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, lResonance, ldaughterRot, lResonanceRot; + + for (const auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + // Full index policy is needed to consider all possible combinations + if (trk1.index() == trk2.index()) + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) continue; - double conjugate = track1.sign() * track2.sign(); - if (!IsMix) { - if (conjugate < 0) { - histos.fill(HIST("hUSS"), centrality, Minv, PhiPt); - } else if (conjugate > 0) { - histos.fill(HIST("hLSS"), centrality, Minv, PhiPt); + + //// Initialize variables + // Trk1: Proton + auto isTrk1hasTOF = trk1.hasTOF(); + auto trk1pt = trk1.pt(); + auto trk1eta = trk1.eta(); + auto trk1phi = trk1.phi(); + auto trk1NSigmaTPC = trk1.tpcNSigmaKa(); + auto trk1NSigmaTOF = (isTrk1hasTOF) ? trk1.tofNSigmaKa() : -999.0f; + + // Trk2: Kaon + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk2pt = trk2.pt(); + auto trk2eta = trk2.eta(); + auto trk2phi = trk2.phi(); + auto trk2NSigmaTPC = trk2.tpcNSigmaKa(); + auto trk2NSigmaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.0f; + + auto deltaEta = 0.0f; + auto deltaPhi = 0.0f; + + if (cfgUseDeltaEtaPhiCuts) { + deltaEta = std::abs(trk1eta - trk2eta); + deltaPhi = std::abs(trk1phi - trk2phi); + deltaPhi = (deltaPhi > o2::constants::math::PI) ? (o2::constants::math::TwoPI - deltaPhi) : deltaPhi; + if (deltaEta >= cMaxDeltaEtaCut) + continue; + if (deltaPhi >= cMaxDeltaPhiCut) + continue; + } + + //// QA plots before the selection + // --- Track QA all + if constexpr (IsData) { + if (cFillTrackQA) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_all"), centrality, trk2pt, trk2NSigmaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_all"), centrality, trk2pt, trk2NSigmaTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_all"), trk2NSigmaTOF, trk2NSigmaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPConly_Nsigma_all"), trk2pt, trk2NSigmaTPC); + } + + histos.fill(HIST("QA/QAbefore/Track/dcaZ_all"), trk1pt, trk1.dcaZ()); + histos.fill(HIST("QA/QAbefore/Track/dcaXY_all"), trk1pt, trk1.dcaXY()); + histos.fill(HIST("QA/QAbefore/Track/TPC_CR_all"), trk1pt, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAbefore/Track/pT_all"), trk1pt); + histos.fill(HIST("QA/QAbefore/Track/eta_all"), trk1eta); } - } else { - if (conjugate < 0) { - histos.fill(HIST("hUSS_Mix"), centrality, Minv, PhiPt); - } else if (conjugate > 0) { - histos.fill(HIST("hLSS_Mix"), centrality, Minv, PhiPt); + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAbefore/deltaEta"), deltaEta); + histos.fill(HIST("QAbefore/deltaPhi"), deltaPhi); } } - } - } // TrackSlicing - template - void TrackSlicing_MC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool QA, const bool IsMix) - { - auto slicedtracks1 = PosKaon_MC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); - auto slicedtracks2 = NegKaon_MC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = centEst(collision1); - for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { - auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); - if (Minv < 0) + //// Apply the pid selection + if (crejectPion && rejectPion(trk2)) // to remove pion contamination from the kaon track continue; - double conjugate = track1.sign() * track2.sign(); - if (!IsMix) { - if (conjugate < 0) { - histos.fill(HIST("hMC_USS"), centrality, Minv, PhiPt); - } else if (conjugate > 0) { - histos.fill(HIST("hMC_LSS"), centrality, Minv, PhiPt); + + if (!ptDependentPidKaon(trk1) || !ptDependentPidKaon(trk2)) + continue; + + //// QA plots after the selection + if constexpr (IsData) { // --- PID QA Proton + histos.fill(HIST("QA/QAafter/Trk1/TPC_Nsigma_selected"), centrality, trk1pt, trk1NSigmaTPC); + histos.fill(HIST("QA/QAafter/Trk1/TPC_Signal_selected"), trk1.tpcInnerParam(), trk1.tpcSignal()); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Trk1/TOF_Nsigma_selected"), centrality, trk1pt, trk1NSigmaTOF); + histos.fill(HIST("QA/QAafter/Trk1/TOF_TPC_Map_selected"), trk1NSigmaTOF, trk1NSigmaTPC); } - } else { - if (conjugate < 0) { - histos.fill(HIST("hMC_USS_Mix"), centrality, Minv, PhiPt); - } else if (conjugate > 0) { - histos.fill(HIST("hMC_LSS_Mix"), centrality, Minv, PhiPt); + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Trk1/TPC_Nsigma_TPConly_selected"), trk1pt, trk1NSigmaTPC); + } + histos.fill(HIST("QA/QAafter/Trk1/dcaZ_selected"), trk1pt, trk1.dcaZ()); + histos.fill(HIST("QA/QAafter/Trk1/dcaXY_selected"), trk1pt, trk1.dcaXY()); + histos.fill(HIST("QA/QAafter/Trk1/TPC_CR_selected"), trk1pt, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Trk1/pT_selected"), trk1pt); + histos.fill(HIST("QA/QAafter/Trk1/eta_selected"), trk1eta); + histos.fill(HIST("QA/QAafter/Trk1/TPCnclusterPhipr_selected"), trk1.tpcNClsFound(), trk1phi); + + // --- PID QA Kaon + histos.fill(HIST("QA/QAafter/Trk2/TPC_Nsigma_selected"), centrality, trk2pt, trk2NSigmaTPC); + histos.fill(HIST("QA/QAafter/Trk2/TPC_Signal_selected"), trk2.tpcInnerParam(), trk2.tpcSignal()); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Trk2/TOF_Nsigma_selected"), centrality, trk2pt, trk2NSigmaTOF); + histos.fill(HIST("QA/QAafter/Trk2/TOF_TPC_Map_selected"), trk2NSigmaTOF, trk2NSigmaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Trk2/TPC_Nsigma_TPConly_selected"), trk2pt, trk2NSigmaTPC); + } + histos.fill(HIST("QA/QAafter/Trk2/dcaZ_selected"), trk2pt, trk2.dcaZ()); + histos.fill(HIST("QA/QAafter/Trk2/dcaXY_selected"), trk2pt, trk2.dcaXY()); + histos.fill(HIST("QA/QAafter/Trk2/TPC_CR_selected"), trk2pt, trk2.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Trk2/pT_selected"), trk2pt); + histos.fill(HIST("QA/QAafter/Trk2/eta_selected"), trk2eta); + histos.fill(HIST("QA/QAafter/Trk2/TPCnclusterPhika_selected"), trk2.tpcNClsFound(), trk2phi); + + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAafter/PhiafterTrk1"), trk1phi); + histos.fill(HIST("QAafter/PhiafterTrk2"), trk2phi); + histos.fill(HIST("QAafter/deltaEta"), deltaEta); + histos.fill(HIST("QAafter/deltaPhi"), deltaPhi); } } - // now we do mc true - if (!track1.has_mcParticle() || !track2.has_mcParticle()) + + //// Resonance reconstruction + lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1pt, trk1eta, trk1phi, massKa); + lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2pt, trk2eta, trk2phi, massKa); + + // Apply kinematic opening angle cut + if (cUseOpeningAngleCut) { + auto v1 = lDecayDaughter1.Vect(); + auto v2 = lDecayDaughter2.Vect(); + float alpha = std::acos(v1.Dot(v2) / (v1.R() * v2.R())); + if (alpha > cMinOpeningAngle && alpha < cMaxOpeningAngle) + continue; + } + + lResonance = lDecayDaughter1 + lDecayDaughter2; + + auto resonanceMass = lResonance.M(); + auto resonancePt = lResonance.Pt(); + auto resonanceRapidity = lResonance.Rapidity(); + + // Rapidity cut + if (std::abs(resonanceRapidity) > configTracks.cfgCutRapidity) continue; - auto part1 = track1.mcParticle(); - auto part2 = track2.mcParticle(); - if (std::fabs(part1.pdgCode()) != 321) - continue; // Not Kaon - if (std::fabs(part2.pdgCode()) != 321) - continue; // Not Kaon - - if (!part1.has_mothers()) - continue; // Not decaying Kaon - if (!part2.has_mothers()) - continue; // Not decaying Kaon - - std::vector mothers1{}; - std::vector mothers1PDG{}; - for (auto& part1_mom : part1.template mothers_as()) { - mothers1.push_back(part1_mom.globalIndex()); - mothers1PDG.push_back(part1_mom.pdgCode()); + + if (cfgUseCutsOnMother) { + if (resonancePt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceMass >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; } - std::vector mothers2{}; - std::vector mothers2PDG{}; - for (auto& part2_mom : part2.template mothers_as()) { - mothers2.push_back(part2_mom.globalIndex()); - mothers2PDG.push_back(part2_mom.pdgCode()); + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hPairsCounterSameE"), 1.0f); + } else if (IsMix) { + histos.fill(HIST("QAevent/hPairsCounterMixedE"), 1.0f); + } } - if (mothers1PDG[0] != 333) - continue; // mother not phi - if (mothers2PDG[0] != 333) - continue; // mother not phi + //// Un-like sign pair only + if (trk1.sign() * trk2.sign() < 0) { + if constexpr (IsRot) { + for (int i = 0; i < configBkg.cNofRotations; i++) { + float theta = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / configBkg.rotationalcut, o2::constants::math::PI + o2::constants::math::PI / configBkg.rotationalcut); + if (configBkg.cfgRotTrk1) { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk1pt, trk1eta, trk1phi + theta, massKa); + lResonanceRot = ldaughterRot + lDecayDaughter2; + } else { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk2pt, trk2eta, trk2phi + theta, massKa); + lResonanceRot = lDecayDaughter1 + ldaughterRot; + } + auto resonanceRotMass = lResonanceRot.M(); + auto resonanceRotPt = lResonanceRot.Pt(); + + // Rapidity cut + if (std::abs(lResonanceRot.Rapidity()) >= configTracks.cfgCutRapidity) + continue; + + if (cfgUseCutsOnMother) { + if (resonanceRotPt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceRotMass >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020InvMassRotation"), resonanceRotMass); + } + histos.fill(HIST("Result/Data/h3phi1020InvMassRotation"), centrality, resonanceRotPt, resonanceRotMass); + } + } + if constexpr (IsData) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmass"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmass"), centrality, resonancePt, resonanceMass); + } else if (IsMix) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmassME"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmassME"), centrality, resonancePt, resonanceMass); + } - if (mothers1[0] != mothers2[0]) - continue; // Kaons not from the same phi + // MC + if constexpr (IsMC) { + // now we do mc true + // ------ Temporal lambda function to prevent error in build + auto getMothersIndeces = [&](auto const& theMcParticle) { + std::vector lMothersIndeces{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother index lMother: %d", lMother.globalIndex()); + lMothersIndeces.push_back(lMother.globalIndex()); + } + return lMothersIndeces; + }; + auto getMothersPDGCodes = [&](auto const& theMcParticle) { + std::vector lMothersPDGs{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %d", lMother.pdgCode()); + lMothersPDGs.push_back(lMother.pdgCode()); + } + return lMothersPDGs; + }; + // ------ + std::vector motherstrk1 = {-1, -1}; + std::vector mothersPDGtrk1 = {-1, -1}; + + std::vector motherstrk2 = {-1, -1}; + std::vector mothersPDGtrk2 = {-1, -1}; + + // + // Get the MC particle + const auto& mctrk1 = trk1.mcParticle(); + if (mctrk1.has_mothers()) { + motherstrk1 = getMothersIndeces(mctrk1); + mothersPDGtrk1 = getMothersPDGCodes(mctrk1); + } + while (motherstrk1.size() > MaxNophi1020Daughters) { + motherstrk1.pop_back(); + mothersPDGtrk1.pop_back(); + } - histos.fill(HIST("hMC_USS_True"), centrality, Minv, PhiPt); - } - } // TrackSlicing + const auto& mctrk2 = trk2.mcParticle(); + if (mctrk2.has_mothers()) { + motherstrk2 = getMothersIndeces(mctrk2); + mothersPDGtrk2 = getMothersPDGCodes(mctrk2); + } + while (motherstrk2.size() > MaxNophi1020Daughters) { + motherstrk2.pop_back(); + mothersPDGtrk2.pop_back(); + } - // Invariant mass - template - std::pair minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA) - { - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - //==================================================== + if (std::abs(mctrk1.pdgCode()) != kKPlus || std::abs(mctrk2.pdgCode()) != kKPlus) + continue; - if (!trackSelection(trk1, QA) || !trackSelection(trk2, false)) - return {-1.0, -1.0}; + if (motherstrk1[0] != motherstrk2[0]) // Same mother + continue; - if (cfg_Track_Explicit_PID) { - if (!trackPIDKaon(trk1, QA) || !trackPIDKaon(trk2, false)) - return {-1.0, -1.0}; - } + if (std::abs(mothersPDGtrk1[0]) != Pdg::kPhi) + continue; - if (trk1.globalIndex() >= trk2.globalIndex()) - return {-1.0, -1.0}; + // LOGF(info, "mother trk1 id: %d, mother trk1: %d, trk1 id: %d, trk1 pdgcode: %d, mother trk2 id: %d, mother trk2: %d, trk2 id: %d, trk2 pdgcode: %d", motherstrk1[0], mothersPDGtrk1[0], trk1.globalIndex(), mctrk1.pdgCode(), motherstrk2[0], mothersPDGtrk2[0], trk2.globalIndex(), mctrk2.pdgCode()); - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); - lResonance = lDecayDaughter1 + lDecayDaughter2; + histos.fill(HIST("QA/MC/h2RecoEtaPt_after"), lResonance.Eta(), resonancePt); + histos.fill(HIST("QA/MC/h2RecoPhiRapidity_after"), lResonance.Phi(), resonanceRapidity); - return {lResonance.M(), lResonance.Pt()}; - } // MinvReconstruction + // Track selection check. + histos.fill(HIST("QA/MC/trkDCAxy_Trk1"), trk1pt, trk1.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAxy_Trk2"), trk2pt, trk2.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAz_Trk1"), trk1pt, trk1.dcaZ()); + histos.fill(HIST("QA/MC/trkDCAz_Trk2"), trk2pt, trk2.dcaZ()); - //***************// - // DATA - //***************// + histos.fill(HIST("QA/MC/TPC_Nsigma_selected_Trk1"), centrality, trk1pt, trk1NSigmaTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_selected_Trk1"), centrality, trk1pt, trk1NSigmaTOF); + } + histos.fill(HIST("QA/MC/TPC_Nsigma_selected_Trk2"), centrality, trk2pt, trk2NSigmaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_selected_Trk2"), centrality, trk2pt, trk2NSigmaTOF); + } - int nEvents = 0; - void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks) - { - if (cDebugLevel > 0) { - ++nEvents; - if (nEvents % 10000 == 0) { - std::cout << "Processed Data Events: " << nEvents << std::endl; + // MC histograms + histos.fill(HIST("Result/MC/h3phi1020Recoinvmass"), centrality, resonancePt, resonanceMass); + } + } else { + if constexpr (IsData) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmassLSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmassLSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmassLSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmassLSMM"), centrality, resonancePt, resonanceMass); + } + } else if (IsMix) { + if (cFilladditionalMEPlots) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmassME_LSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmassME_LSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/phi1020invmassME_LSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3phi1020invmassME_LSMM"), centrality, resonancePt, resonanceMass); + } + } + } } } + } + + void processData(EventCandidates::iterator const& collision, + TrackCandidates const& tracks) + { + if (!isSelected(collision)) // Default event selection + return; + + auto centrality = centEst(collision); + + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centFT0M"), centrality); + + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Phi1020analysis, processData, "Process Event for data without partition", false); - auto [goodEv, code] = eventSelection(collision, true); - histos.fill(HIST("hnEvents"), code); - if (!goodEv) + void processRotational(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (!isSelected(collision, false)) // Default event selection return; - TrackSlicing(collision, tracks, collision, tracks, true, false); - } // end of process + if (!collision.isInelGt0()) // <-- + return; - PROCESS_SWITCH(phi1020analysis, processSameEvent, "Process Same events", true); + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Phi1020analysis, processRotational, "Process Rotational Background", false); - //***************// - // DATA (MIX) - //***************// + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; - int nEvents_Mix = 0; - void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + void processME(EventCandidates const& collision, + TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); - BinningTypeVtxCent colBinning{{cfg_bins_MixVtx, cfg_bins_MixMult}, true}; - SameKindPair pairs{colBinning, cfg_Mix_NMixedEvents, -1, collisions, tracksTuple, &cache}; + + BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultPercentileBins}, true}; + SameKindPair pairs{colBinning, configBkg.nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - if (cDebugLevel > 0) { - ++nEvents_Mix; - if (nEvents_Mix % 10000 == 0) { - std::cout << "Processed Mixed Events: " << nEvents_Mix << std::endl; - } - } - auto [goodEv1, code1] = eventSelection(collision1, false); - auto [goodEv2, code2] = eventSelection(collision2, false); - if (!goodEv1 || !goodEv2) + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.globalIndex(), collision2.globalIndex()); + + // for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d)", t1.index(), t2.index(), collision1.index(), collision2.index()); + // } + + if (!isSelected(collision1, false)) // Default event selection continue; - TrackSlicing(collision1, tracks1, collision2, tracks2, false, true); - } // mixing - } // end of process - PROCESS_SWITCH(phi1020analysis, processMixedEvent, "Process Mixed events", false); - //***************// - // RECONSTRUCTED MC - //***************// + if (!isSelected(collision2, false)) // Default event selection + continue; - int nEvents_MC = 0; - void processSameEvent_MC(EventCandidates::iterator const& collision, TrackCandidates_MC const& tracks, aod::McParticles const&) - { - if (cDebugLevel > 0) { - ++nEvents_MC; - if (nEvents_MC % 10000 == 0) { - std::cout << "Processed MC (REC) Events: " << nEvents_MC << std::endl; + if (!collision1.isInelGt0()) // <-- + continue; + + if (!collision2.isInelGt0()) // <-- + continue; + + if (cFilladditionalQAeventPlots) { + // Fill histograms for the characteristics of the *mixed* events (collision1 and collision2) + // This will show the distribution of events that are actually being mixed. + if (cFill1DQAs) { + histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision1.posZ()); + histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision1.centFT0M()); + } + histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision1.posZ(), collision1.centFT0M()); + + // You might also want to fill for collision2 if you want to see both partners' distributions + // histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision2.posZ()); + // histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision2.centFT0M()); + // histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision2.posZ(), collision2.centFT0M()); } + fillHistograms(collision1, tracks1, tracks2); } + } + PROCESS_SWITCH(Phi1020analysis, processME, "Process EventMixing light without partition", false); - auto [goodEv, code] = eventSelection(collision, true); - histos.fill(HIST("hnEvents_MC"), code); - if (!goodEv) + void processMCRec(MCEventCandidates::iterator const& collision, + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) + { + if (!collision.has_mcCollision()) return; - TrackSlicing_MC(collision, tracks, collision, tracks, true, false); - } // end of process - PROCESS_SWITCH(phi1020analysis, processSameEvent_MC, "Process Same events (MC)", true); + if (!isSelected(collision)) + return; - //***************// - // RECONSTRUCTED MC (MIX) - //***************// + auto centrality = centEst(collision); - int nEvents_MC_Mix = 0; - void processMixedEvent_MC(EventCandidates const& collisions, TrackCandidates_MC const& tracks, aod::McParticles const&) + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centFT0M"), centrality); + + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Phi1020analysis, processMCRec, "Process Event for MC Rec without partition", false); + + Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == static_cast(Pdg::kPhi)); // Lambda(1520) + + void processMCGen(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - auto tracksTuple = std::make_tuple(tracks); - BinningTypeVtxCent colBinning{{cfg_bins_MixVtx, cfg_bins_MixMult}, true}; - SameKindPair pairs{colBinning, cfg_Mix_NMixedEvents, -1, collisions, tracksTuple, &cache}; - for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - if (cDebugLevel > 0) { - ++nEvents_MC_Mix; - if (nEvents_MC_Mix % 10000 == 0) { - std::cout << "Processed Mixed Events: " << nEvents_MC_Mix << std::endl; - } + if (!collision.has_mcCollision()) + return; + + bool isInAfterAllCuts = isSelected(collision, false); + + auto mcPartsAll = mcParticles.sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + // bool isTrueINELgt0 = pwglf::isINELgt0mc(mcPartsAll, pdg); + bool isTrueINELgt0 = collision.isInelGt0(); // <-- + + auto centrality = centEst(collision); + + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + // Not related to the real collisions + for (const auto& part : mcParts) { // loop over all Lambda(1520) particles + + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; + } + + if (std::abs(daughterPDGs[0]) != PDG_t::kKPlus || std::abs(daughterPDGs[1]) != PDG_t::kKPlus) { // At least one decay to Kaon + continue; } - auto [goodEv1, code1] = eventSelection(collision1, false); - auto [goodEv2, code2] = eventSelection(collision2, false); - if (!goodEv1 || !goodEv2) + + // LOGF(info, "Part PDG: %d", part.pdgCode(), "DAU_ID1: %d", pass1, "DAU_ID2: %d", pass2); + + histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), part.phi(), part.y()); + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) // rapidity cut continue; - TrackSlicing_MC(collision1, tracks1, collision2, tracks2, false, true); - } // mixing - } // end of process - PROCESS_SWITCH(phi1020analysis, processMixedEvent_MC, "Process Mixed events (MC)", false); - //***************// - // GENERATED MC - //***************// + if (cfgUseDaughterEtaCutMC) { + for (auto const& daughters : part.daughters_as()) { + if (std::fabs(daughters.eta()) > configTracks.cfgCutEta) + continue; // eta cut for daughters + } // loop over daughters + } + + histos.fill(HIST("QA/MC/h2GenEtaPt_afterRapcut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterRapcut"), part.phi(), part.y()); - int nEvents_True = 0; - void processParticles(EventCandidates_True::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& particles) + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + histos.fill(HIST("Result/MC/Genphi1020pt"), part.pt(), centrality); + } + } + PROCESS_SWITCH(Phi1020analysis, processMCGen, "Process Event for MC only", false); + + void processEventFactor(MCEventCandidates const& collisions, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) { - if (cDebugLevel > 0) { - ++nEvents_True; - if (nEvents_True % 10000 == 0) { - std::cout << "Processed MC (GEN) Events: " << nEvents_True << std::endl; + // Loop on reconstructed collisions + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; } - } + const auto& mcCollision = collision.mcCollision_as>(); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cacheMC); - if (fabs(collision.posZ()) > cfg_Event_VtxCut) - return; + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + bool isInAfterAllCuts = isSelected(collision, false); - if (recocolls.size() <= 0) { // not reconstructed - if (cfg_Force_GenReco) { - return; - } + float centrality = mcCollision.centFT0M(); + + if (isTrueINELgt0 && isInAfterAllCuts) + histos.fill(HIST("Event/MultiplicityRecoEv"), centrality); } - double centrality = -1; - for (auto& recocoll : recocolls) { // poorly reconstructed - centrality = centEst(recocoll); - auto [goodEv, code] = eventSelection(recocoll, false); - histos.fill(HIST("hnEvents_MC_True"), code); - if (!goodEv) - return; + // Loop on generated collisions to fill the event factor for the INEL>0 correction + for (const auto& mccolls : mcCollisions) { + float centrality = mccolls.centFT0M(); + bool inVtx10 = std::abs(mccolls.posZ()) <= configEvents.cfgEvtZvtx; + + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolls.globalIndex(), cacheMC); + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); // QA for Trigger efficiency + + if (inVtx10 && isTrueINELgt0) + histos.fill(HIST("Event/MultiplicityGenEv"), centrality); } + } + PROCESS_SWITCH(Phi1020analysis, processEventFactor, "Process Event factor", false); + + void processSignalLoss(MCEventCandidates const& collisions, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) + { + // Loop on reconstructed collisions + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + const auto& mcCollision = collision.mcCollision_as>(); + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cacheMC); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + bool isInAfterAllCuts = isSelected(collision, false); + bool inVtx10 = std::abs(mcCollision.posZ()) <= configEvents.cfgEvtZvtx; - for (auto& particle : particles) { - if (particle.pdgCode() != 333) + float centrality = mcCollision.centFT0M(); + + // ===== NUM ===== + if (!(inVtx10 && isTrueINELgt0)) continue; - if (std::fabs(particle.eta()) > cfg_Track_MaxEta) + + if (!isInAfterAllCuts) continue; - if (cfg_Force_BR) { - bool baddecay = false; - for (auto& phidaughter : particle.daughters_as()) { - if (std::fabs(phidaughter.pdgCode()) != 321) { - baddecay = true; - break; - } - if (cfg_Force_Kaon_Acceptence) { - if (std::fabs(phidaughter.eta()) > cfg_Track_MaxEta) { - baddecay = true; - break; - } - } - } // loop over daughters + for (const auto& part : particlesInCollision) { + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) + continue; - if (baddecay) + float pt = part.pt(); + + // phi + if (std::abs(part.pdgCode()) == Pdg::kPhi) + histos.fill(HIST("Result/SignalLoss/GenTruephi1020pt_num"), pt, centrality); + } + } + + // Loop on generated collisions to fill the event factor for the INEL>0 correction + for (const auto& mccolls : mcCollisions) { + float centrality = mccolls.centFT0M(); + + bool inVtx10 = std::abs(mccolls.posZ()) <= configEvents.cfgEvtZvtx; + + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolls.globalIndex(), cacheMC); + bool isTrueINELgt0 = pwglf::isINELgt0mc(particlesInCollision, pdg); + + if (!(inVtx10 && isTrueINELgt0)) + continue; + + for (const auto& part : particlesInCollision) { + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) continue; - } // enforce BR restriction - histos.fill(HIST("hMC_Phi_True"), centrality, particle.pt()); - } // loop over particles + // ========================= + // ===== PHI(1020) ====== + // ========================= + if (std::abs(part.pdgCode()) == Pdg::kPhi) { + + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; + } - } // end of process - PROCESS_SWITCH(phi1020analysis, processParticles, "Process Particles", false); + if (std::abs(daughterPDGs[0]) != PDG_t::kKPlus || std::abs(daughterPDGs[1]) != PDG_t::kKPlus) { // At least one decay to Kaon + continue; + } + histos.fill(HIST("Result/SignalLoss/GenTruephi1020pt_den"), part.pt(), centrality); + } + } + } + } + PROCESS_SWITCH(Phi1020analysis, processSignalLoss, "Process SignalLoss", false); }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; From 69d71935a747384f2286bdf24e8a4aeba13deff4 Mon Sep 17 00:00:00 2001 From: Kai Cui <129373281+kcui1@users.noreply.github.com> Date: Mon, 11 May 2026 15:00:49 +0200 Subject: [PATCH 124/449] [PWGLF] Add Midrapidity hist In H-Scorrelation task (#16194) --- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index bd03393379a..f5f41d16af4 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -161,6 +161,7 @@ struct HStrangeCorrelation { ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; ConfigurableAxis axisMassNSigma{"axisMassNSigma", {40, -2, 2}, "Axis for mass Nsigma"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 20, 40, 60, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300}, "Binning of the Multiplicity axis in model prediction process"}; + ConfigurableAxis axisMidrapidityMultiplicity{"axisMidrapidityMultiplicity", {VARIABLE_WIDTH, 0, 20, 40, 60, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300}, "Binning of the Midrapidity Multiplicity axis in model prediction process"}; } axesConfigurations; @@ -1803,7 +1804,7 @@ struct HStrangeCorrelation { bool hStrange = false; for (int i = 0; i < AssocParticleTypes; i++) { - if (TESTBIT(doCorrelation, i)) { + if (TESTBIT(doCorrelation, i) && (doprocessSameEventHV0s || doprocessSameEventHCascades)) { if (masterConfigurations.doFullCorrelationStudy) histos.add(fmt::format("sameEvent/Signal/{}", Particlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); if (doDeltaPhiStarCheck && masterConfigurations.doFullCorrelationStudy) { @@ -1829,13 +1830,13 @@ struct HStrangeCorrelation { } } } - if (TESTBIT(doCorrelation, 7)) { + if (TESTBIT(doCorrelation, 7) && doprocessSameEventHPions) { histos.add("hPionEtaVsPtAllSelected", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); histos.add("hPionEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); histos.add("hPositivePionEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); histos.add("hNegativePionEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); } - if (TESTBIT(doCorrelation, 8)) { + if (TESTBIT(doCorrelation, 8) && doprocessSameEventHHadrons) { histos.add("hAsssocTrackEtaVsPtVsPhi", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); histos.add("hAssocPrimaryEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); histos.add("hAssocHadronsAllSelectedEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); @@ -1931,9 +1932,15 @@ struct HStrangeCorrelation { } else { if (masterConfigurations.doSeparateFT0Prediction) { histos.add("Prediction/hTriggerFT0A", "Trigger Tracks FT0A", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + histos.add("Prediction/hFT0AvsNchEta08", "Nch in 0.8 vs FT0A multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); + histos.add("Prediction/hFT0AvsNchEta05", "Nch in 0.5 vs FT0A multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); histos.add("Prediction/hTriggerFT0C", "Trigger Tracks FT0C", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + histos.add("Prediction/hFT0CvsNchEta08", "Nch in 0.8 vs FT0C multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); + histos.add("Prediction/hFT0CvsNchEta05", "Nch in 0.5 vs FT0C multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); } histos.add("Prediction/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMultiplicity}); + histos.add("Prediction/hFT0MvsNchEta08", "Nch in 0.8 vs FT0M multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); + histos.add("Prediction/hFT0MvsNchEta05", "Nch in 0.5 vs FT0M multiplicity", kTH2F, {axesConfigurations.axisMultiplicity, axesConfigurations.axisMidrapidityMultiplicity}); } for (int i = 0; i < AssocParticleTypes; i++) { if (TESTBIT(doCorrelation, i)) @@ -3317,6 +3324,8 @@ struct HStrangeCorrelation { float multFT0M = -1; float multFT0A = -1; float multFT0C = -1; + float multEta08 = -1; + float multEta05 = -1; histos.fill(HIST("Prediction/hEventSelection"), 0.5); if (masterConfigurations.selectINELgtZERO && !o2::pwglf::isINELgt0mc(mcParticles, pdgDB)) { return; @@ -3334,6 +3343,18 @@ struct HStrangeCorrelation { multFT0M = mCounter.countFT0A(mcParticles) + mCounter.countFT0C(mcParticles); multFT0A = mCounter.countFT0A(mcParticles); multFT0C = mCounter.countFT0C(mcParticles); + multEta08 = mCounter.countEta08(mcParticles); + multEta05 = mCounter.countEta05(mcParticles); + } + if (!masterConfigurations.useCentralityinPrediction) { + if (masterConfigurations.doSeparateFT0Prediction) { + histos.fill(HIST("Prediction/hFT0AvsNchEta08"), multFT0A, multEta08); + histos.fill(HIST("Prediction/hFT0AvsNchEta05"), multFT0A, multEta05); + histos.fill(HIST("Prediction/hFT0CvsNchEta08"), multFT0C, multEta08); + histos.fill(HIST("Prediction/hFT0CvsNchEta05"), multFT0C, multEta05); + } + histos.fill(HIST("Prediction/hFT0MvsNchEta08"), multFT0M, multEta08); + histos.fill(HIST("Prediction/hFT0MvsNchEta05"), multFT0M, multEta05); } int iteratorNum = -1; for (auto const& mcParticle : mcParticles) { From a6682ca4f3fc686c97db99d52802b2b07af982c9 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 11 May 2026 16:38:37 +0200 Subject: [PATCH 125/449] [PWGEM/Dilepton] add impact parameters in taggingHFE (#16197) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 47 +++++++------ PWGEM/Dilepton/Tasks/taggingHFE.cxx | 60 +++++++--------- PWGEM/Dilepton/Utils/SemiCharmTag.h | 93 +++++++++++++++++-------- 3 files changed, 112 insertions(+), 88 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index e8eb1a58458..b332f509bb1 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -219,11 +219,11 @@ DECLARE_SOA_INDEX_COLUMN(EMMLLepton, emmllepton); //! most propable emeventId DECLARE_SOA_COLUMN(RapidityV0, rapidityV0, float); //! rapidity of associated V0 DECLARE_SOA_COLUMN(RapidityC, rapidityC, float); //! rapidity of associated Cascade -DECLARE_SOA_COLUMN(ImpParXY, impParXY, float); //! impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParZ, impParZ, float); //! impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParCYY, impParCYY, float); //! sigma of impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParCZY, impParCZY, float); //! sigma of impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParCZZ, impParCZZ, float); //! sigma of impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParHXY, impParHXY, float); //! impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParHZ, impParHZ, float); //! impact parameter for V0/Cascade in Z plane +DECLARE_SOA_COLUMN(ImpParHCYY, impParHCYY, float); //! sigma of impact parameter for V0/Cascade in XY +DECLARE_SOA_COLUMN(ImpParHCZY, impParHCZY, float); //! sigma of impact parameter for V0/Cascade, correlaion term +DECLARE_SOA_COLUMN(ImpParHCZZ, impParHCZZ, float); //! sigma of impact parameter for V0/Cascade in Z DECLARE_SOA_COLUMN(V0CosPA, v0copa, float); //! cosPA of V0 DECLARE_SOA_COLUMN(V0CosPAXY, v0copaXY, float); //! cosPA of V0 in XY plane @@ -236,12 +236,18 @@ DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron DECLARE_SOA_COLUMN(CosPA, cospa, float); //! flight direction of LH pair DECLARE_SOA_COLUMN(CosPAXY, cospaXY, float); //! flight direction of LH pair in XY -DECLARE_SOA_COLUMN(Lxyz, lxyz, float); //! decay length of LH pair -DECLARE_SOA_COLUMN(LxyzSigma, lxyzSigma, float); //! decay length resolution of LH pair -DECLARE_SOA_COLUMN(Lxy, lxy, float); //! decay length of LH pair -DECLARE_SOA_COLUMN(LxySigma, lxySigma, float); //! decay length resolution of LH pair -DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair -DECLARE_SOA_COLUMN(LzSigma, lzSigma, float); //! decay length resolution of LH pair +DECLARE_SOA_COLUMN(Lxy, lxy, float); //! decay length of LH pair +DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair +DECLARE_SOA_COLUMN(Lxyz, lxyz, float); //! decay length of LH pair +DECLARE_SOA_COLUMN(LxyErr, lxyErr, float); //! decay length resolution of LH pair +DECLARE_SOA_COLUMN(LzErr, lzErr, float); //! decay length resolution of LH pair +DECLARE_SOA_COLUMN(LxyzErr, lxyzErr, float); //! decay length resolution of LH pair + +DECLARE_SOA_COLUMN(ImpParXY, impParXY, float); //! impact parameter for LH in XY plane +DECLARE_SOA_COLUMN(ImpParZ, impParZ, float); //! impact parameter for LH in Z plane +DECLARE_SOA_COLUMN(ImpParCYY, impParCYY, float); //! sigma of impact parameter for LH in XY +DECLARE_SOA_COLUMN(ImpParCZY, impParCZY, float); //! sigma of impact parameter for LH, correlation term +DECLARE_SOA_COLUMN(ImpParCZZ, impParCZZ, float); //! sigma of impact parameter for LH in Z DECLARE_SOA_COLUMN(PdgCodeH, pdgCodeH, int); //! pdg code of associated hadron DECLARE_SOA_COLUMN(PdgCodeIM, pdgCodeIM, int); //! pdg code of intermediate hadron from HF hadrons. e.g K*, D* @@ -256,9 +262,8 @@ DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, - emmllhpair::Lxyz, emmllhpair::LxyzSigma, - emmllhpair::Lxy, emmllhpair::LxySigma, - emmllhpair::Lz, emmllhpair::LzSigma, + emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, + emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLHPair = EMMLLHPairs::iterator; @@ -267,11 +272,10 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::EMMLLeptonId, track::Pt, emmllhpair::RapidityV0, emmllhpair::V0CosPA, emmllhpair::V0CosPAXY, - emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, + emmllhpair::ImpParHXY, emmllhpair::ImpParHZ, emmllhpair::ImpParHCYY, emmllhpair::ImpParHCZY, emmllhpair::ImpParHCZZ, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, - emmllhpair::Lxyz, emmllhpair::LxyzSigma, - emmllhpair::Lxy, emmllhpair::LxySigma, - emmllhpair::Lz, emmllhpair::LzSigma, + emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, + emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLV0Pair = EMMLLV0Pairs::iterator; @@ -280,11 +284,10 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCAPAIR", //! emmllhpair::EMMLLeptonId, track::Pt, emmllhpair::RapidityC, emmllhpair::CascCosPA, emmllhpair::CascCosPAXY, - emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, + emmllhpair::ImpParHXY, emmllhpair::ImpParHZ, emmllhpair::ImpParHCYY, emmllhpair::ImpParHCZY, emmllhpair::ImpParHCZZ, emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, - emmllhpair::Lxyz, emmllhpair::LxyzSigma, - emmllhpair::Lxy, emmllhpair::LxySigma, - emmllhpair::Lz, emmllhpair::LzSigma, + emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, + emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLCascPair = EMMLLCascPairs::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 0e9e92ffe4b..fc3e540fd07 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1710,9 +1710,8 @@ struct taggingHFE { kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, - eKpair.lxyz, eKpair.lxyzErr, - eKpair.lxy, eKpair.lxyErr, - eKpair.lz, eKpair.lzErr, + eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, + eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1774,9 +1773,8 @@ struct taggingHFE { kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, - eKpair.lxyz, eKpair.lxyzErr, - eKpair.lxy, eKpair.lxyErr, - eKpair.lz, eKpair.lzErr, + eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, + eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1851,9 +1849,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, - eV0pair.lxyz, eV0pair.lxyzErr, - eV0pair.lxy, eV0pair.lxyErr, - eV0pair.lz, eV0pair.lzErr, + eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, + eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -1912,9 +1909,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, - eV0pair.lxyz, eV0pair.lxyzErr, - eV0pair.lxy, eV0pair.lxyErr, - eV0pair.lz, eV0pair.lzErr, + eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, + eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Lambda loop @@ -1978,9 +1974,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, - eCpair.lxyz, eCpair.lxyzErr, - eCpair.lxy, eCpair.lxyErr, - eCpair.lz, eCpair.lzErr, + eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, + eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi- loop @@ -2044,9 +2039,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, - eCpair.lxyz, eCpair.lxyzErr, - eCpair.lxy, eCpair.lxyErr, - eCpair.lz, eCpair.lzErr, + eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, + eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega- loop @@ -2137,9 +2131,8 @@ struct taggingHFE { kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, - eKpair.lxyz, eKpair.lxyzErr, - eKpair.lxy, eKpair.lxyErr, - eKpair.lz, eKpair.lzErr, + eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, + eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -2202,9 +2195,8 @@ struct taggingHFE { kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, - eKpair.lxyz, eKpair.lxyzErr, - eKpair.lxy, eKpair.lxyErr, - eKpair.lz, eKpair.lzErr, + eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, + eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -2278,9 +2270,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, - eV0pair.lxyz, eV0pair.lxyzErr, - eV0pair.lxy, eV0pair.lxyErr, - eV0pair.lz, eV0pair.lzErr, + eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, + eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -2339,9 +2330,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, - eV0pair.lxyz, eV0pair.lxyzErr, - eV0pair.lxy, eV0pair.lxyErr, - eV0pair.lz, eV0pair.lzErr, + eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, + eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Anti-Lambda loop @@ -2405,9 +2395,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, - eCpair.lxyz, eCpair.lxyzErr, - eCpair.lxy, eCpair.lxyErr, - eCpair.lz, eCpair.lzErr, + eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, + eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi+ loop @@ -2471,9 +2460,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, - eCpair.lxyz, eCpair.lxyzErr, - eCpair.lxy, eCpair.lxyErr, - eCpair.lz, eCpair.lzErr, + eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, + eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega+ loop diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index ebfa9162c56..b8bfaffb118 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -21,9 +21,11 @@ #include #include +#include #include -#include -#include +// #include +// #include +#include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include @@ -39,11 +41,16 @@ struct LHPair { // struct to store electron-hadron pair information float cospa{-999.f}; float cospaXY{-999.f}; float lxy{-999.f}; - float lxyErr{-999.f}; float lz{-999.f}; - float lzErr{-999.f}; float lxyz{-999.f}; + float lxyErr{-999.f}; + float lzErr{-999.f}; float lxyzErr{-999.f}; + float impParXY{-999.f}; + float impParZ{-999.f}; + float impParCYY{-999.f}; + float impParCZY{-999.f}; + float impParCZZ{-999.f}; bool isOK{false}; }; @@ -95,12 +102,29 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton auto primaryVertex = getPrimaryVertex(collision); std::array covVtxLK = fitter.calcPCACovMatrixFlat(); - double phiLK{}, thetaLK{}; - getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, svpos, phiLK, thetaLK); - pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLK, thetaLK) + getRotatedCovMatrixXX(covVtxLK, phiLK, thetaLK)); - pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLK, 0.) + getRotatedCovMatrixXX(covVtxLK, phiLK, 0.)); + double phiLH{}, thetaLK{}; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, svpos, phiLH, thetaLK); + pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, thetaLK) + getRotatedCovMatrixXX(covVtxLK, phiLH, thetaLK)); + pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, 0.) + getRotatedCovMatrixXX(covVtxLK, phiLH, 0.)); pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLK) + getRotatedCovMatrixXX(covVtxLK, 0, thetaLK)); + // propagate the 2 prongs to the secondary vertex + leptonParCov.propagateTo(vtx[0], fitter.getBz()); + trackParCov.propagateTo(vtx[0], fitter.getBz()); + + // calculate impact parameter + o2::dataformats::DCA dcaLH; + auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, trackParCov); + trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + + pair.impParXY = dcaLH.getY(); + pair.impParZ = dcaLH.getZ(); + pair.impParCYY = dcaLH.getSigmaY2(); + pair.impParCZY = dcaLH.getSigmaYZ(); + pair.impParCZZ = dcaLH.getSigmaZ2(); + + // LOGF(info, "fitter.getBz() = %f, dcaLH.getY() = %f, dcaLH.getZ() = %f", fitter.getBz(), dcaLH.getY(), dcaLH.getZ()); + ROOT::Math::PxPyPzMVector v1(pvec0[0], pvec0[1], pvec0[2], o2::constants::physics::MassElectron); if (leptonId == o2::track::PID::Electron) { v1.SetM(o2::constants::physics::MassElectron); @@ -113,23 +137,10 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton } ROOT::Math::PxPyPzMVector v2(pvec1[0], pvec1[1], pvec1[2], o2::constants::physics::MassPionCharged); - // if (strHadId == o2::track::PID::Kaon) { - // v2.SetM(o2::constants::physics::MassPionCharged); - // } else { - // LOGF(info, "strHadId supports only Kaon."); - // pair.isOK = false; - // return pair; - // } - ROOT::Math::PxPyPzMVector v12 = v1 + v2; - pair.mass = v12.M(); - // pair.dca2legs = dca2legs; - // pair.cospa = cospa; - // pair.lxy = lxy; - // pair.lz = lz; - pair.isOK = true; + pair.isOK = true; return pair; } @@ -197,6 +208,21 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLV0, 0.) + getRotatedCovMatrixXX(covVtxLV0, phiLV0, 0.)); pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLV0) + getRotatedCovMatrixXX(covVtxLV0, 0, thetaLV0)); + // propagate the 2 prongs to the secondary vertex + leptonParCov.propagateTo(vtx[0], fitter.getBz()); + v0ParCov.propagateTo(vtx[0], fitter.getBz()); + + // calculate impact parameter + o2::dataformats::DCA dcaLH; + auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, v0ParCov); + trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + + pair.impParXY = dcaLH.getY(); + pair.impParZ = dcaLH.getZ(); + pair.impParCYY = dcaLH.getSigmaY2(); + pair.impParCZY = dcaLH.getSigmaYZ(); + pair.impParCZZ = dcaLH.getSigmaZ2(); + ROOT::Math::PxPyPzMVector v1(pvec0[0], pvec0[1], pvec0[2], o2::constants::physics::MassElectron); if (leptonId == o2::track::PID::Electron) { v1.SetM(o2::constants::physics::MassElectron); @@ -222,10 +248,6 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); - // pair.dca2legs = dca2legs; - // pair.cospa = cospa; - // pair.lxy = lxy; - // pair.lz = lz; pair.isOK = true; return pair; @@ -299,6 +321,21 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLC) + getRotatedCovMatrixXX(covVtxLC, 0, thetaLC)); pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLC, thetaLC) + getRotatedCovMatrixXX(covVtxLC, phiLC, thetaLC)); + // propagate the 2 prongs to the secondary vertex + leptonParCov.propagateTo(vtx[0], fitter.getBz()); + cascParCov.propagateTo(vtx[0], fitter.getBz()); + + // calculate impact parameter + o2::dataformats::DCA dcaLH; + auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, cascParCov); + trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + + pair.impParXY = dcaLH.getY(); + pair.impParZ = dcaLH.getZ(); + pair.impParCYY = dcaLH.getSigmaY2(); + pair.impParCZY = dcaLH.getSigmaYZ(); + pair.impParCZZ = dcaLH.getSigmaZ2(); + ROOT::Math::PxPyPzMVector v1(pvec0[0], pvec0[1], pvec0[2], o2::constants::physics::MassElectron); if (leptonId == o2::track::PID::Electron) { v1.SetM(o2::constants::physics::MassElectron); @@ -324,10 +361,6 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); - // pair.dca2legs = dca2legs; - // pair.cospa = cospa; - // pair.lxy = lxy; - // pair.lz = lz; pair.isOK = true; return pair; From 64011eb2459c5ec548bd5d6bf8d6cc85811802ee Mon Sep 17 00:00:00 2001 From: vojmach <137265951+vojmach@users.noreply.github.com> Date: Mon, 11 May 2026 16:46:11 +0200 Subject: [PATCH 126/449] [PWGCF] Add pT-dependent DCAz cut (#16195) Co-authored-by: Vojtech Machacek Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowMc.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index 77b8f96d86d..e6d883c55a0 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -89,6 +89,8 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgDCAxyFunction, std::string, "(0.0015+0.005/(x^1.1))", "Functional form of pt-dependent DCAxy cut"); O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz cut for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") + O2_DEFINE_CONFIGURABLE(cfgDCAzFunction, std::string, "(0.0015+0.005/(x^1.1))", "Functional form of pt-dependent DCAz cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the z direction"); O2_DEFINE_CONFIGURABLE(cfgEnableITSCuts, bool, true, "switch of enabling ITS based track selection cuts") O2_DEFINE_CONFIGURABLE(cfgTrkSelRun3ITSMatch, bool, false, "GlobalTrackRun3ITSMatching::Run3ITSall7Layers selection") O2_DEFINE_CONFIGURABLE(cfgFlowAcceptance, std::string, "", "CCDB path to acceptance object") @@ -137,6 +139,7 @@ struct FlowMc { // Additional filters for tracks TrackSelection myTrackSel; TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; // Cent vs IP TH1D* mCentVsIPTruth = nullptr; @@ -310,9 +313,13 @@ struct FlowMc { myTrackSel.SetMinNCrossedRowsTPC(cfgCutTPCcrossedrows); if (cfgEnableITSCuts) myTrackSel.SetMinNClustersITS(cfgCutITSclu); - if (!cfgCutDCAzPtDepEnabled) + if (!cfgCutDCAzPtDepEnabled) { myTrackSel.SetMaxDcaZ(cfgCutDCAz); - + } else { + fPtDepDCAz = new TF1("ptDepDCAxy", Form("[0]*%s", cfgDCAzFunction->c_str()), 0.001, 100); + fPtDepDCAz->SetParameter(0, cfgDCAzNSigma); + LOGF(info, "DCAz pt-dependence function: %s", Form("[0]*%s", cfgDCAzFunction->c_str())); + } if (cfgTrackDensityCorrUse) { std::vector pTEffBins = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0}; hFindPtBin = new TH1D("hFindPtBin", "hFindPtBin", pTEffBins.size() - 1, &pTEffBins[0]); @@ -472,7 +479,7 @@ struct FlowMc { template bool trackSelected(TTrack track) { - if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) { + if (cfgCutDCAzPtDepEnabled && (std::fabs(track.dcaZ()) > fPtDepDCAz->Eval(track.pt()))) { return false; } return myTrackSel.IsSelected(track); From 28b32d66029061fae5b9a82652cef0e39463bf46 Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Mon, 11 May 2026 23:07:01 +0800 Subject: [PATCH 127/449] [PWGDQ] Add and change the code for the energy correlator study (#16199) Co-authored-by: Cape --- PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 84 ++++++++++++++++++----- 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx index 9df32a2871a..06c997df1fd 100644 --- a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -130,11 +130,12 @@ struct AnalysisEnergyCorrelator { Configurable fConfigAddDileptonHadronHistogram{"cfgAddDileptonHadronHistogram", "", "Dilepton-hadron histograms"}; Configurable fConfigMCRecSignals{"cfgMCRecDileptonHadronSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable fConfigMCGenSignals{"cfgMCGenDileptonHadronSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigMCGenPairSignals{"cfgMCGenDileptonHadronPairSignals", "", "Comma separated list of MC pair signals (generated)"}; Configurable fConfigMCRecSignalsJSON{"cfgMCRecDileptonHadronSignalsJSON", "", "Additional list of MC signals (reconstructed) via JSON"}; Configurable fConfigMCGenSignalsJSON{"cfgMCGenDileptonHadronSignalsJSON", "", "Comma separated list of MC signals (generated) via JSON"}; + Configurable fConfigMCGenPairSignalsJSON{"cfgMCGenDileptonHadronPairSignalsJSON", "", "Comma separated list of MC pair signals (generated) via JSON"}; Configurable fConfigMCGenHadronEtaAbs{"cfgMCGenHadronEtaAbs", 0.9f, "eta abs range for the hadron"}; Configurable fConfigMCGenHadronPtMin{"cfgMCGenHadronPtMin", 0.1f, "minimum pt for the hadron"}; - Configurable fConfigContainlepton{"cfgContainlepton", false, "If true, require the hadron to contain the lepton in its decay tree for the energy correlator study"}; Configurable fConfigUsePionMass{"cfgUsePionMass", false, "If true, use pion mass for the hadron in the energy correlator study"}; Configurable fConfigApplyEfficiency{"cfgApplyEfficiency", false, "If true, apply efficiency correction for the energy correlator study"}; Configurable fConfigApplyEfficiencyME{"cfgApplyEfficiencyME", false, "If true, apply efficiency correction for the energy correlator study"}; @@ -167,6 +168,7 @@ struct AnalysisEnergyCorrelator { std::vector fRecMCTrackSignals; // MC signals for reconstructed tracks std::vector fRecMCSignals; // MC signals for reconstructed pairs std::vector fGenMCSignals; + std::vector fGenMCPairSignals; std::vector fRecMCTripleSignals; // MC signals for reconstructed triples Service fCCDB; @@ -183,6 +185,7 @@ struct AnalysisEnergyCorrelator { TH2F* hEfficiency_dilepton; TH2F* hEfficiency_hadron; TH1F* hMasswindow; + TH2F* hReweighthadron; void init(o2::framework::InitContext& context) { @@ -337,6 +340,29 @@ struct AnalysisEnergyCorrelator { } } + // Add histogram classes for each specified MCsignal at the generator level + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function + TString sigpairGenNamesStr = fConfigDileptonHadronOptions.fConfigMCGenPairSignals.value; + std::unique_ptr objGenPairSigArray(sigpairGenNamesStr.Tokenize(",")); + for (int isig = 0; isig < objGenPairSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenPairSigArray->At(isig)->GetName()); + if (sig) { + fGenMCPairSignals.push_back(sig); + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsPairGenStr = fConfigDileptonHadronOptions.fConfigMCGenPairSignalsJSON.value; + if (addMCSignalsPairGenStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsPairGenStr.Data()); + for (auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != 2) { // NOTE: only 2 prong signals + continue; + } + fGenMCPairSignals.push_back(mcIt); + } + } + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function TString sigRecTrackNamesStr = fConfigTrackOptions.fConfigMCRecTrackSignals.value; std::unique_ptr objRecTrackSigArray(sigRecTrackNamesStr.Tokenize(",")); @@ -440,6 +466,14 @@ struct AnalysisEnergyCorrelator { if (sig->GetNProngs() == 1) { if (isMCGen_energycorrelators) { DefineHistograms(fHistMan, Form("MCTruthGenSel_%s", sig->GetName()), ""); + } + } + } + + for (auto& sig : fGenMCPairSignals) { + LOG(info) << "Defining histograms for pair signal: " << sig->GetNProngs(); + if (sig->GetNProngs() == 2) { + if (isMCGen_energycorrelators) { DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_Pion_%s", sig->GetName()), ""); } @@ -472,7 +506,8 @@ struct AnalysisEnergyCorrelator { hAcceptance_rec = static_cast(listAccs->FindObject("hAcceptance_rec")); hAcceptance_gen = static_cast(listAccs->FindObject("hAcceptance_gen")); hMasswindow = static_cast(listAccs->FindObject("hMasswindow")); - if (!hAcceptance_rec || !hAcceptance_gen || !hEfficiency_dilepton || !hEfficiency_hadron || !hMasswindow) { + hReweighthadron = static_cast(listAccs->FindObject("hReweighthadron")); + if (!hAcceptance_rec || !hAcceptance_gen || !hEfficiency_dilepton || !hEfficiency_hadron || !hMasswindow || !hReweighthadron) { LOG(fatal) << "Problem getting histograms from the TList object with efficiencies!"; } } @@ -533,11 +568,22 @@ struct AnalysisEnergyCorrelator { float Effdilepton = GetSafeInterpolationWeight(hEfficiency_dilepton, dilepton_rap, dilepton_pt); float Effhadron = GetSafeInterpolationWeight(hEfficiency_hadron, hadron_eta, hadron.pt()); float Masswindow = hMasswindow->Interpolate(dilepton_pt); - Accweight_gen = Accweight_gen * Effdilepton * Effhadron; + float Reweighthadron = 1.0f; + if (std::abs(hadronMC.pdgCode()) == PDG_t::kPiPlus) { + int bin = hReweighthadron->FindBin(0, hadron.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } else if (std::abs(hadronMC.pdgCode()) == PDG_t::kProton) { + int bin = hReweighthadron->FindBin(1, hadron.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } else if (std::abs(hadronMC.pdgCode()) == PDG_t::kKPlus) { + int bin = hReweighthadron->FindBin(2, hadron.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } + Accweight_gen = Accweight_gen * Effdilepton * Effhadron * Reweighthadron; if (fConfigDileptonHadronOptions.fConfigApplyEfficiencyME) { - Effweight_rec = Effdilepton * Effhadron * Masswindow; // for the moment, apply the efficiency correction also for the mixed event pairs, but this can be changed in case we want to apply it only for the same event pairs + Effweight_rec = Effdilepton * Effhadron * Masswindow * Reweighthadron; // for the moment, apply the efficiency correction also for the mixed event pairs, but this can be changed in case we want to apply it only for the same event pairs } else { - Effweight_rec = Effweight_rec * Effdilepton * Effhadron * Masswindow; // apply acceptance and efficiency correction for the real pairs + Effweight_rec = Effweight_rec * Effdilepton * Effhadron * Masswindow * Reweighthadron; // apply acceptance and efficiency correction for the real pairs } } @@ -936,25 +982,16 @@ struct AnalysisEnergyCorrelator { continue; // for the energy correlators for (auto& t2 : groupedMCTracks2) { - auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); if (t2.mcCollisionId() != event2.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event continue; } - if (!t2_raw.isPhysicalPrimary()) { - continue; - } if (t2_raw.has_mothers()) { auto mother_raw = t2_raw.template mothers_first_as(); if (mother_raw.globalIndex() == t1_raw.globalIndex()) { continue; } } - if (fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton && std::abs(t2_raw.pdgCode()) != PDG_t::kElectron && std::abs(t2_raw.pdgCode()) != PDG_t::kMuonMinus) { - continue; - } - if (!fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton) { - continue; - } if (t2_raw.pt() < fConfigDileptonHadronOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigDileptonHadronOptions.fConfigMCGenHadronEtaAbs.value) { continue; } @@ -966,11 +1003,24 @@ struct AnalysisEnergyCorrelator { float hadron_phi = t2_raw.phi(); float deltaphi = RecoDecay::constrainAngle(dilepton_phi - hadron_phi, -0.5 * o2::constants::math::PI); acceptance = hAcceptance_gen->Interpolate(dilepton_eta - hadron_eta, deltaphi); + float Reweighthadron = 1.0f; + if (std::abs(t2_raw.pdgCode()) == PDG_t::kPiPlus) { + int bin = hReweighthadron->FindBin(0, t2_raw.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } else if (std::abs(t2_raw.pdgCode()) == PDG_t::kProton) { + int bin = hReweighthadron->FindBin(1, t2_raw.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } else if (std::abs(t2_raw.pdgCode()) == PDG_t::kKPlus) { + int bin = hReweighthadron->FindBin(2, t2_raw.pt()); + Reweighthadron = hReweighthadron->GetBinContent(bin); + } + acceptance = acceptance * Reweighthadron; } std::vector fTransRange = fConfigDileptonHadronOptions.fConfigTransRange; VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1], 1. / acceptance); - for (auto& sig : fGenMCSignals) { - if (sig->CheckSignal(true, t1_raw)) { + for (auto& sig : fGenMCPairSignals) { + + if (sig->CheckSignal(true, t1_raw, t2_raw)) { if (!MixedEvent && !PionMass) { fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); } From 0720b96d2ad8c9b568add762abb85a9b3e785378 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 11 May 2026 19:23:46 +0200 Subject: [PATCH 128/449] [ALICE3,PWGCF] replace -1 with 1 in getForTimeStamp (#16204) --- ALICE3/Core/FastTracker.cxx | 2 +- ALICE3/TableProducer/alice3-centrality.cxx | 2 +- PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx | 2 +- PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx | 2 +- PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx | 2 +- PWGCF/Flow/Tasks/flowEventPlane.cxx | 4 ++-- .../Tasks/Lambdacascadecorrelation.cxx | 2 +- .../TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 254ab8d6643..2379cba22ac 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -187,7 +187,7 @@ void FastTracker::AddGenericDetector(o2::fastsim::GeometryEntry configMap, o2::c LOG(fatal) << "CCDB manager is null, cannot retrieve file " << ccdbPath; return; } - TGraph* g = ccdbManager->getForTimeStamp(ccdbPath, -1); + TGraph* g = ccdbManager->getForTimeStamp(ccdbPath, 1); addedLayer->setDeadPhiRegions(g); } else { // Taking it as local file diff --git a/ALICE3/TableProducer/alice3-centrality.cxx b/ALICE3/TableProducer/alice3-centrality.cxx index bc06a838697..d5afacd69b4 100644 --- a/ALICE3/TableProducer/alice3-centrality.cxx +++ b/ALICE3/TableProducer/alice3-centrality.cxx @@ -67,7 +67,7 @@ struct ALICE3Centrality { void process(const o2::aod::Collision& collision, const soa::Join& tracks) { if (!centralityLoaded) { - hCumMultALICE3 = ccdb->getForTimeStamp("Analysis/ALICE3/Centrality", -1); + hCumMultALICE3 = ccdb->getForTimeStamp("Analysis/ALICE3/Centrality", 1); centralityLoaded = true; LOGF(info, "ALICE 3 centrality calibration loaded!"); } diff --git a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx index 205ec98bf88..ff63af24227 100644 --- a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx @@ -185,7 +185,7 @@ struct EventMeanPtId { ccdb->setLocalObjectValidityChecking(); // ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); // LOGF(info, "Getting object %s", ccdbPath.value.data()); - TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); + TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, 1); ptHistogramAllchargeRec = reinterpret_cast(lst->FindObject("hPtEta_rec")); } std::vector ptBinning = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0}; diff --git a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx index e5d0739e8d3..491859bec09 100644 --- a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx @@ -174,7 +174,7 @@ struct MeanPtFlucId { ccdb->setURL(cfgUrlCCDB.value); ccdb->setCaching(true); - TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); + TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, 1); hWeightPt = reinterpret_cast(lst->FindObject("hWeightPt")); hWeightPtPi = reinterpret_cast(lst->FindObject("hWeightPtPi")); hWeightPtKa = reinterpret_cast(lst->FindObject("hWeightPtKa")); diff --git a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx index 7b5cf8ad25d..76d4ef30e91 100644 --- a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx @@ -417,7 +417,7 @@ struct NetchargeFluctuations { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - TList* list = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); + TList* list = ccdb->getForTimeStamp(cfgPathCCDB.value, 1); efficiencyPos = reinterpret_cast(list->FindObject("efficiency_Pos_Run3")); efficiencyNeg = reinterpret_cast(list->FindObject("efficiency_Neg_Run3")); // Log fatal error if efficiency histogram is not found diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index b0c97685508..5253f04a7ab 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -379,7 +379,7 @@ struct SpectatorPlaneTableProducer { // Load ZDC gain calibration if (cDoGainCalib) { std::string ccdbPath = static_cast(cCcdbPath) + "/GainCalib" + "/Run" + std::to_string(cRunNum); - auto ccdbObj = ccdbService->getForTimeStamp(ccdbPath, -1); + auto ccdbObj = ccdbService->getForTimeStamp(ccdbPath, 1); CorrectionHistContainer.hGainCalib[0] = reinterpret_cast(ccdbObj->FindObject("hZNASignal")); CorrectionHistContainer.hGainCalib[1] = reinterpret_cast(ccdbObj->FindObject("hZNCSignal")); } @@ -407,7 +407,7 @@ struct SpectatorPlaneTableProducer { std::string ccdbPath = static_cast(cCcdbPath) + "/CorrItr_" + std::to_string(i + 1) + "/Run" + std::to_string(cRunNum); // Get object from CCDB - auto ccdbObject = ccdbService->getForTimeStamp(ccdbPath, -1); + auto ccdbObject = ccdbService->getForTimeStamp(ccdbPath, 1); // Check CCDB Object if (!ccdbObject) { diff --git a/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx index d844dd72bfb..197ed2dfecb 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx @@ -897,7 +897,7 @@ struct LambdaTableProducer { } // Get from CCDB - auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, -1); + auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, 1); // Check CCDB Object if (!ccdbObj) { diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx index 7635688b9fb..adbd36a53da 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx @@ -802,7 +802,7 @@ struct LambdaTableProducer { return 1.; // Get from CCDB - auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, -1); + auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, 1); if (!ccdbObj) { LOGF(warning, "CCDB OBJECT NOT FOUND"); return 1.; From a116a02510fadff6d78ab16294f6acf22c55c356 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 11 May 2026 19:51:34 +0200 Subject: [PATCH 129/449] [PWGEM/Dilepton] improve CCDB access in smearing.cxx (#16205) --- PWGEM/Dilepton/Tasks/smearing.cxx | 40 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/smearing.cxx b/PWGEM/Dilepton/Tasks/smearing.cxx index 3d5a8668244..0d1e850413a 100644 --- a/PWGEM/Dilepton/Tasks/smearing.cxx +++ b/PWGEM/Dilepton/Tasks/smearing.cxx @@ -129,8 +129,30 @@ struct ApplySmearing { MomentumSmearer smearer_StandaloneMuon; MomentumSmearer smearer_GlobalMuon; Service ccdb; + int mRunNumber{0}; void init(InitContext&) + { + mRunNumber = 0; + if (fTimestamp < 0) { + LOG(fatal) << "Don't use time stamp = -1"; + } + if (doprocessCocktail) { + initResolutionMap(fTimestamp); + } + } + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + initResolutionMap(bc.timestamp()); + mRunNumber = bc.runNumber(); + } + + void initResolutionMap(const int64_t timestamp) { smearer_Electron.setNDSmearing(electron_filenames.fConfigNDSmearing.value); smearer_Electron.setResFileName(TString(electron_filenames.fConfigResFileName)); @@ -180,19 +202,19 @@ struct ApplySmearing { smearer_Electron.setCcdbPathRes(TString(electron_filenames.fConfigCcdbPathRes)); smearer_Electron.setCcdbPathEff(TString(electron_filenames.fConfigCcdbPathEff)); smearer_Electron.setCcdbPathDCA(TString(electron_filenames.fConfigCcdbPathDCA)); - smearer_Electron.setTimestamp(fTimestamp); + smearer_Electron.setTimestamp(timestamp); smearer_Electron.setCcdb(ccdb); smearer_StandaloneMuon.setCcdbPathRes(TString(sa_muon_filenames.fConfigCcdbPathRes)); smearer_StandaloneMuon.setCcdbPathEff(TString(sa_muon_filenames.fConfigCcdbPathEff)); smearer_StandaloneMuon.setCcdbPathDCA(TString(sa_muon_filenames.fConfigCcdbPathDCA)); - smearer_StandaloneMuon.setTimestamp(fTimestamp); + smearer_StandaloneMuon.setTimestamp(timestamp); smearer_StandaloneMuon.setCcdb(ccdb); smearer_GlobalMuon.setCcdbPathRes(TString(gl_muon_filenames.fConfigCcdbPathRes)); smearer_GlobalMuon.setCcdbPathEff(TString(gl_muon_filenames.fConfigCcdbPathEff)); smearer_GlobalMuon.setCcdbPathDCA(TString(gl_muon_filenames.fConfigCcdbPathDCA)); - smearer_GlobalMuon.setTimestamp(fTimestamp); + smearer_GlobalMuon.setTimestamp(timestamp); smearer_GlobalMuon.setCcdb(ccdb); } smearer_Electron.init(); @@ -203,7 +225,7 @@ struct ApplySmearing { template void applySmearing(TTracksMC const& tracksMC, TCollisions const& collisions, TMCCollisions const&) { - for (auto& mctrack : tracksMC) { + for (const auto& mctrack : tracksMC) { float ptgen = mctrack.pt(); float etagen = mctrack.eta(); float phigen = mctrack.phi(); @@ -269,14 +291,10 @@ struct ApplySmearing { void processMCanalysisEM(aod::EMMCParticles const& tracksMC, MyCollisions const& collisions, MyMCCollisions const& mccollisions) { + initCCDB(collisions.iteratorAt(0)); applySmearing(tracksMC, collisions, mccollisions); } - // void processMCanalysisDQ(ReducedMCTracks const& tracksMC) - // { - // applySmearing(tracksMC); - // } - void processCocktail(aod::McParticles const& tracksMC) { applySmearing(tracksMC, nullptr, nullptr); @@ -285,7 +303,7 @@ struct ApplySmearing { void processDummyCocktail(aod::McParticles const& tracksMC) { // don't apply smearing - for (auto& mctrack : tracksMC) { + for (const auto& mctrack : tracksMC) { int pdgCode = mctrack.pdgCode(); if (std::abs(pdgCode) == 11) { smearedelectron(mctrack.pt(), mctrack.eta(), mctrack.phi(), 1.0, 0.0); @@ -356,7 +374,7 @@ struct CheckSmearing { template void Check(TTracksMC const& tracksMC, TMCCollisions const&) { - for (auto& mctrack : tracksMC) { + for (const auto& mctrack : tracksMC) { if (std::abs(mctrack.pdgCode()) != fPdgCode) { continue; } From f2753a5a561e3373db140a7f5a54403366529412 Mon Sep 17 00:00:00 2001 From: a-m-andrushko <96832230+a-m-andrushko@users.noreply.github.com> Date: Mon, 11 May 2026 20:31:34 +0200 Subject: [PATCH 130/449] [PWGCF] FemtoUniverse -- Add "fake" K0Short histograms. (#16198) --- .../femtoUniversePairTaskTrackV0Helicity.cxx | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx index d832430f99d..60cd704ca06 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -326,20 +326,24 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.add("Theta/NegativeChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel1", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassMotherHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassLambdaMC", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel1", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel2", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel3", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassLambdaMCHel4", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/hInvMassK0ShortMC", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel1", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel2", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel3", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/hInvMassK0ShortMCHel4", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel1", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel1", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel2", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel3", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel4", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMC", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel1", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel2", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel3", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel4", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassK0ShortMC", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassK0ShortMCHel1", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassK0ShortMCHel2", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassK0ShortMCHel3", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); + thetaRegistry.add("Theta/Mother/MCReco/hInvMassK0ShortMCHel4", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); /// MC Truth registryMCtruth.add("plus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); @@ -492,6 +496,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { auto negChildMass = pdg->Mass(V0configs.confPDGCodeNegChild); auto posChildBoosted = FemtoUniverseMath::boostPRF(posChild, posChildMass, negChild, negChildMass); auto cosineTheta = (posChildBoosted.Px() * part.px() + posChildBoosted.Py() * part.py() + posChildBoosted.Pz() * part.pz()) / (posChildBoosted.P() * part.p()); + auto invMassK0Short = TMath::Sqrt(TMath::Power(TMath::Sqrt(posChild.p() * posChild.p() + pdg->Mass(V0configs.confPDGCodePosChild) * pdg->Mass(V0configs.confPDGCodePosChild)) + TMath::Sqrt(negChild.p() * negChild.p() + pdg->Mass(V0configs.confPDGCodeNegChild) * pdg->Mass(V0configs.confPDGCodeNegChild)), 2) - TMath::Power(posChild.p() + negChild.p(), 2)); // "fake" K0Short invariant mass to estimate their fraction in the Lambda sample trackHistoPartTwo.fillQA(part); posChildHistos.fillQA(posChild); @@ -507,43 +512,48 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negChild.eta(), cosineTheta); thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); - if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel1"), part.pt(), part.mLambda()); - else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel2"), part.pt(), part.mLambda()); - else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel3"), part.pt(), part.mLambda()); - else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel4"), part.pt(), part.mLambda()); + if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) { + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel1"), part.pt(), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel1"), invMassK0Short); + } else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) { + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel2"), part.pt(), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel2"), invMassK0Short); + } else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) { + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel3"), part.pt(), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel3"), invMassK0Short); + } else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) { + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel4"), part.pt(), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel4"), invMassK0Short); + } - /// Histogramming for MC Reco to calculate fraction of K0S in the Lambda sample for each helicity bin + /// Histogramming for MC Reco to calculate fraction of K0Short in the Lambda sample for each helicity bin if constexpr (confIsMC) { if (part.has_fdMCParticle()) { if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMC"), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMC"), part.mLambda()); else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMC"), part.mKaon()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMC"), part.mKaon()); if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) { if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel1"), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel1"), part.mLambda()); else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel1"), part.mKaon()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel1"), part.mKaon()); } else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) { if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel2"), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel2"), part.mLambda()); else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel2"), part.mKaon()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel2"), part.mKaon()); } else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) { if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel3"), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel3"), part.mLambda()); else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel3"), part.mKaon()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel3"), part.mKaon()); } else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) { if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassLambdaMCHel4"), part.mLambda()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel4"), part.mLambda()); else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/hInvMassK0ShortMCHel4"), part.mKaon()); + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel4"), part.mKaon()); } } } From f69ded50879f11bf38249d10a64c7feea0170f16 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Mon, 11 May 2026 22:50:47 +0200 Subject: [PATCH 131/449] [Common] Tune pp mult calib on derived data (#16207) Co-authored-by: ALICE Builder --- Common/Tasks/centralityStudypp.cxx | 66 +++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index 68d2e1c947c..839c34accfb 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -72,6 +72,7 @@ struct centralityStudypp { // _______________________________________ // event selection criteria Configurable applyVertexZEqualization{"applyVertexZEqualization", false, "0 - no, 1 - yes"}; + Configurable saveUnequalized{"saveUnequalized", false, "save unequalized raw: 0 - no, 1 - yes"}; Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; Configurable requireINELgtZERO{"requireINELgtZERO", true, "0 no, 1 - yes"}; @@ -83,22 +84,13 @@ struct centralityStudypp { Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; Configurable rejectSameBunchPileup{"rejectSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC"}; - // Configurable Axes for 2d plots, etc - // ConfigurableAxis axisMultFV0A{"axisMultFV0A", {1000, 0, 100000}, "FV0A amplitude"}; - // ConfigurableAxis axisMultFT0A{"axisMultFT0A", {1000, 0, 100000}, "FT0A amplitude"}; - // ConfigurableAxis axisMultFT0C{"axisMultFT0C", {1000, 0, 100000}, "FT0C amplitude"}; - // ConfigurableAxis axisMultFT0M{"axisMultFT0M", {1000, 0, 100000}, "FT0M amplitude"}; - // ConfigurableAxis axisMultFDDA{"axisMultFDDA", {1000, 0, 100000}, "FDDA amplitude"}; - // ConfigurableAxis axisMultFDDC{"axisMultFDDC", {1000, 0, 100000}, "FDDC amplitude"}; - // ConfigurableAxis axisMultPVContributors{"axisMultPVContributors", {200, 0, 6000}, "Number of PV Contributors"}; - // ConfigurableAxis axisMultGlobalTracks{"axisMultGlobalTracks", {500, 0, 5000}, "Number of global tracks"}; - // ConfigurableAxis axisMultMFTTracks{"axisMultMFTTracks", {500, 0, 5000}, "Number of MFT tracks"}; - // For one-dimensional plots, where binning is no issue ConfigurableAxis axisMultUltraFineFV0A{"axisMultUltraFineFV0A", {60000, 0, 60000}, "FV0A amplitude"}; - ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; - ConfigurableAxis axisMultUltraFineFT0C{"axisMultUltraFineFT0C", {60000, 0, 60000}, "FT0C amplitude"}; ConfigurableAxis axisMultUltraFineFT0A{"axisMultUltraFineFT0A", {60000, 0, 60000}, "FT0A amplitude"}; + ConfigurableAxis axisMultUltraFineFT0C{"axisMultUltraFineFT0C", {60000, 0, 60000}, "FT0C amplitude"}; + ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; + ConfigurableAxis axisMultUltraFineFDDA{"axisMultUltraFineFDDA", {60000, 0, 60000}, "FDDA amplitude"}; + ConfigurableAxis axisMultUltraFineFDDC{"axisMultUltraFineFDDC", {60000, 0, 60000}, "FDDC amplitude"}; ConfigurableAxis axisMultUltraFinePVContributors{"axisMultUltraFinePVContributors", {10000, 0, 10000}, "Number of PV Contributors"}; ConfigurableAxis axisMultUltraFineGlobalTracks{"axisMultUltraFineGlobalTracks", {5000, 0, 5000}, "Number of global tracks"}; ConfigurableAxis axisMultUltraFineMFTTracks{"axisMultUltraFineMFTTracks", {5000, 0, 5000}, "Number of MFT tracks"}; @@ -146,6 +138,10 @@ struct centralityStudypp { histos.add("hFT0A_Collisions", "hFT0A_Collisions", kTH1D, {axisMultUltraFineFT0A}); histos.add("hFT0C_Collisions", "hFT0C_Collisions", kTH1D, {axisMultUltraFineFT0C}); histos.add("hFT0M_Collisions", "hFT0M_Collisions", kTH1D, {axisMultUltraFineFT0M}); + + histos.add("hFDDA_Collisions", "hFDDA_Collisions", kTH1D, {axisMultUltraFineFDDA}); + histos.add("hFDDC_Collisions", "hFDDC_Collisions", kTH1D, {axisMultUltraFineFDDC}); + histos.add("hFV0A_Collisions", "hFV0A_Collisions", kTH1D, {axisMultUltraFineFV0A}); histos.add("hNGlobalTracks", "hNGlobalTracks", kTH1D, {axisMultUltraFineGlobalTracks}); histos.add("hNMFTTracks", "hNMFTTracks", kTH1D, {axisMultUltraFineMFTTracks}); @@ -153,6 +149,8 @@ struct centralityStudypp { histos.add("hFT0AvsPVz_Collisions", "hFT0AvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hFT0CvsPVz_Collisions", "hFT0CvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hFDDAvsPVz_Collisions", "hFDDAvsPVz_Collisions", kTProfile, {axisPVz}); + histos.add("hFDDCvsPVz_Collisions", "hFDDCvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hFV0AvsPVz_Collisions", "hFV0AvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hNGlobalTracksvsPVz_Collisions", "hNGlobalTracksvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hNMFTTracksvsPVz_Collisions", "hNMFTTracksvsPVz_Collisions", kTProfile, {axisPVz}); @@ -176,14 +174,14 @@ struct centralityStudypp { hVtxZFV0A = static_cast(hCalibObjects->FindObject("hVtxZFV0A")); hVtxZFT0A = static_cast(hCalibObjects->FindObject("hVtxZFT0A")); hVtxZFT0C = static_cast(hCalibObjects->FindObject("hVtxZFT0C")); - // hVtxZFDDA = static_cast(hCalibObjects->FindObject("hVtxZFDDA")); - // hVtxZFDDC = static_cast(hCalibObjects->FindObject("hVtxZFDDC")); + hVtxZFDDA = static_cast(hCalibObjects->FindObject("hVtxZFDDA")); + hVtxZFDDC = static_cast(hCalibObjects->FindObject("hVtxZFDDC")); hVtxZNTracks = static_cast(hCalibObjects->FindObject("hVtxZNTracksPV")); hVtxZNGlobals = static_cast(hCalibObjects->FindObject("hVtxZNGlobals")); hVtxZMFT = static_cast(hCalibObjects->FindObject("hVtxZMFT")); // Capture error - if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZNTracks || !hVtxZNGlobals || !hVtxZMFT) { + if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZFDDA || !hVtxZFDDC || !hVtxZNTracks || !hVtxZNGlobals || !hVtxZMFT) { LOGF(error, "Problem loading CCDB objects! Please check"); } } @@ -203,17 +201,26 @@ struct centralityStudypp { getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(11, "Pass INEL > 0"); - histPointers.insert({histPath + "hFT0C_Collisions", histos.add((histPath + "hFT0C_Collisions").c_str(), "hFT0C_Collisions", {kTH1D, {{axisMultUltraFineFT0C}}})}); histPointers.insert({histPath + "hFT0A_Collisions", histos.add((histPath + "hFT0A_Collisions").c_str(), "hFT0A_Collisions", {kTH1D, {{axisMultUltraFineFT0A}}})}); + histPointers.insert({histPath + "hFT0C_Collisions", histos.add((histPath + "hFT0C_Collisions").c_str(), "hFT0C_Collisions", {kTH1D, {{axisMultUltraFineFT0C}}})}); histPointers.insert({histPath + "hFT0M_Collisions", histos.add((histPath + "hFT0M_Collisions").c_str(), "hFT0M_Collisions", {kTH1D, {{axisMultUltraFineFT0M}}})}); + + histPointers.insert({histPath + "hFDDA_Collisions", histos.add((histPath + "hFDDA_Collisions").c_str(), "hFDDA_Collisions", {kTH1D, {{axisMultUltraFineFDDA}}})}); + histPointers.insert({histPath + "hFDDC_Collisions", histos.add((histPath + "hFDDC_Collisions").c_str(), "hFDDC_Collisions", {kTH1D, {{axisMultUltraFineFDDC}}})}); + histPointers.insert({histPath + "hFV0A_Collisions", histos.add((histPath + "hFV0A_Collisions").c_str(), "hFV0A_Collisions", {kTH1D, {{axisMultUltraFineFV0A}}})}); histPointers.insert({histPath + "hNGlobalTracks", histos.add((histPath + "hNGlobalTracks").c_str(), "hNGlobalTracks", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); histPointers.insert({histPath + "hNMFTTracks", histos.add((histPath + "hNMFTTracks").c_str(), "hNMFTTracks", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); histPointers.insert({histPath + "hNPVContributors", histos.add((histPath + "hNPVContributors").c_str(), "hNPVContributors", {kTH1D, {{axisMultUltraFinePVContributors}}})}); - if (applyVertexZEqualization) { + if (applyVertexZEqualization && saveUnequalized) { + histPointers.insert({histPath + "hFT0A_Collisions_Unequalized", histos.add((histPath + "hFT0A_Collisions_Unequalized").c_str(), "hFT0A_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0A}}})}); histPointers.insert({histPath + "hFT0C_Collisions_Unequalized", histos.add((histPath + "hFT0C_Collisions_Unequalized").c_str(), "hFT0C_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0C}}})}); histPointers.insert({histPath + "hFT0M_Collisions_Unequalized", histos.add((histPath + "hFT0M_Collisions_Unequalized").c_str(), "hFT0M_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0M}}})}); + + histPointers.insert({histPath + "hFDDA_Collisions_Unequalized", histos.add((histPath + "hFDDA_Collisions_Unequalized").c_str(), "hFDDA_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFDDA}}})}); + histPointers.insert({histPath + "hFDDC_Collisions_Unequalized", histos.add((histPath + "hFDDC_Collisions_Unequalized").c_str(), "hFDDC_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFDDC}}})}); + histPointers.insert({histPath + "hFV0A_Collisions_Unequalized", histos.add((histPath + "hFV0A_Collisions_Unequalized").c_str(), "hFV0A_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFV0A}}})}); histPointers.insert({histPath + "hNGlobalTracks_Unequalized", histos.add((histPath + "hNGlobalTracks_Unequalized").c_str(), "hNGlobalTracks_Unequalized", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); histPointers.insert({histPath + "hNMFTTracks_Unequalized", histos.add((histPath + "hNMFTTracks_Unequalized").c_str(), "hNMFTTracks_Unequalized", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); @@ -222,6 +229,8 @@ struct centralityStudypp { histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFT0CvsPVz_Collisions", histos.add((histPath + "hFT0CvsPVz_Collisions").c_str(), "hFT0CvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFDDAvsPVz_Collisions", histos.add((histPath + "hFDDAvsPVz_Collisions").c_str(), "hFDDAvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFDDCvsPVz_Collisions", histos.add((histPath + "hFDDCvsPVz_Collisions").c_str(), "hFDDCvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFV0AvsPVz_Collisions", histos.add((histPath + "hFV0AvsPVz_Collisions").c_str(), "hFV0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hNGlobalTracksvsPVz_Collisions", histos.add((histPath + "hNGlobalTracksvsPVz_Collisions").c_str(), "hNGlobalTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hNMFTTracksvsPVz_Collisions", histos.add((histPath + "hNMFTTracksvsPVz_Collisions").c_str(), "hNMFTTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); @@ -245,6 +254,8 @@ struct centralityStudypp { float multFV0A = collision.multFV0A(); float multFT0A = collision.multFT0A(); float multFT0C = collision.multFT0C(); + float multFDDA = collision.multFDDA(); + float multFDDC = collision.multFDDC(); float multNTracksGlobal = collision.multNTracksGlobal(); float mftNtracks = collision.mftNtracks(); float multNTracksPV = collision.multNTracksPV(); @@ -253,6 +264,8 @@ struct centralityStudypp { multFV0A = -1.0f; multFT0A = -1.0f; multFT0C = -1.0f; + multFDDA = -1.0f; + multFDDC = -1.0f; multNTracksGlobal = -1.0f; mftNtracks = -1.0f; multNTracksPV = -1.0f; @@ -266,6 +279,12 @@ struct centralityStudypp { if (hVtxZFT0C->Interpolate(collision.multPVz()) > epsilon) { multFT0C = hVtxZFT0C->Interpolate(0.0) * collision.multFT0C() / hVtxZFT0C->Interpolate(collision.multPVz()); } + if (hVtxZFDDA->Interpolate(collision.multPVz()) > epsilon) { + multFDDA = hVtxZFDDA->Interpolate(0.0) * collision.multFDDA() / hVtxZFDDA->Interpolate(collision.multPVz()); + } + if (hVtxZFDDC->Interpolate(collision.multPVz()) > epsilon) { + multFDDC = hVtxZFDDC->Interpolate(0.0) * collision.multFDDC() / hVtxZFDDC->Interpolate(collision.multPVz()); + } if (hVtxZNGlobals->Interpolate(collision.multPVz()) > epsilon) { multNTracksGlobal = hVtxZNGlobals->Interpolate(0.0) * collision.multNTracksGlobal() / hVtxZNGlobals->Interpolate(collision.multPVz()); } @@ -293,6 +312,8 @@ struct centralityStudypp { // all runs histos.fill(HIST("hFT0AvsPVz_Collisions"), collision.multPVz(), collision.multFT0A()); histos.fill(HIST("hFT0CvsPVz_Collisions"), collision.multPVz(), collision.multFT0C()); + histos.fill(HIST("hFDDAvsPVz_Collisions"), collision.multPVz(), collision.multFDDA()); + histos.fill(HIST("hFDDCvsPVz_Collisions"), collision.multPVz(), collision.multFDDC()); histos.fill(HIST("hFV0AvsPVz_Collisions"), collision.multPVz(), collision.multFV0A()); histos.fill(HIST("hNGlobalTracksvsPVz_Collisions"), collision.multPVz(), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracksvsPVz_Collisions"), collision.multPVz(), collision.mftNtracks()); @@ -300,6 +321,8 @@ struct centralityStudypp { // per run getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C); getHist(TProfile, histPath + "hFT0AvsPVz_Collisions")->Fill(collision.multPVz(), multFT0A); + getHist(TProfile, histPath + "hFDDAvsPVz_Collisions")->Fill(collision.multPVz(), multFDDA); + getHist(TProfile, histPath + "hFDDCvsPVz_Collisions")->Fill(collision.multPVz(), multFDDC); getHist(TProfile, histPath + "hFV0AvsPVz_Collisions")->Fill(collision.multPVz(), multFV0A); getHist(TProfile, histPath + "hNGlobalTracksvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksGlobal); getHist(TProfile, histPath + "hNMFTTracksvsPVz_Collisions")->Fill(collision.multPVz(), mftNtracks); @@ -368,6 +391,8 @@ struct centralityStudypp { histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A()); histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C()); histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C())); + histos.fill(HIST("hFDDA_Collisions"), collision.multFDDA()); + histos.fill(HIST("hFDDC_Collisions"), collision.multFDDC()); histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A()); histos.fill(HIST("hNGlobalTracks"), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracks"), collision.mftNtracks()); @@ -381,11 +406,14 @@ struct centralityStudypp { getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); - if (applyVertexZEqualization.value) { + if (applyVertexZEqualization.value && saveUnequalized.value) { // save unequalized for cross-checks getHist(TH1, histPath + "hNPVContributors_Unequalized")->Fill(collision.multNTracksPV()); + getHist(TH1, histPath + "hFT0A_Collisions_Unequalized")->Fill(collision.multFT0A()); getHist(TH1, histPath + "hFT0C_Collisions_Unequalized")->Fill(collision.multFT0C()); getHist(TH1, histPath + "hFT0M_Collisions_Unequalized")->Fill((collision.multFT0A() + collision.multFT0C())); + getHist(TH1, histPath + "hFDDA_Collisions_Unequalized")->Fill(collision.multFDDA()); + getHist(TH1, histPath + "hFDDC_Collisions_Unequalized")->Fill(collision.multFDDC()); getHist(TH1, histPath + "hFV0A_Collisions_Unequalized")->Fill(collision.multFV0A()); getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); From 745cb01dce2cd4242086684e2891a5cf0b1a2a94 Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Tue, 12 May 2026 07:53:21 +0900 Subject: [PATCH 132/449] [PWGLF] Add a configurable to turn on and off INELGt0 condition (#16206) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/chk892LI.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chk892LI.cxx b/PWGLF/Tasks/Resonances/chk892LI.cxx index fef4a7d8cf9..16f96d876b8 100644 --- a/PWGLF/Tasks/Resonances/chk892LI.cxx +++ b/PWGLF/Tasks/Resonances/chk892LI.cxx @@ -251,7 +251,8 @@ struct Chk892LI { Configurable cfgNrotBkg{"cfgNrotBkg", 4, "Number of rotated copies (background) per each original candidate"}; } BkgEstimationConfig; - Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", true, "Truth denominator: require INEL>0"}; + Configurable cfgRecoUseInelGt0{"cfgRecoUseInelGt0", false, "Data/Reco require INEL>0"}; + Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", false, "Truth denominator: require INEL>0"}; Configurable cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", true, "Truth denominator: also require |vtxz| EventCuts.cfgEventCentralityMax) return; - if (!collision.isInelGt0()) + if (cfgRecoUseInelGt0 && !collision.isInelGt0()) return; colCuts.fillQA(collision); @@ -1508,7 +1509,7 @@ struct Chk892LI { return; if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) return; - if (!collision.isInelGt0()) + if (cfgRecoUseInelGt0 && !collision.isInelGt0()) return; if (!collision.has_mcCollision()) return; From b01cdd6cf63e9f42aa16558aa2bee87b32eddd95 Mon Sep 17 00:00:00 2001 From: blacwovie Date: Tue, 12 May 2026 12:06:08 +0800 Subject: [PATCH 133/449] [PWGCF] new deuteron PID cut (#16200) Co-authored-by: ALICE Action Bot --- .../TableProducer/HadNucleiFemto.cxx | 101 ++++++++++++------ 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index e424be7f54d..a8ef42e5973 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -192,7 +192,6 @@ struct HadNucleiFemto { Configurable settingCutClSizeItsDe{"settingCutClSizeItsDe", 4.0f, "Minimum ITS cluster size for De"}; Configurable settingCutDeptMin{"settingCutDeptMin", 0.6f, "Minimum PT cut on De"}; Configurable settingCutDeptMax{"settingCutDeptMax", 1.6f, "Maximum PT cut on De"}; - Configurable settingCutDeDCAzMin{"settingCutDeDCAzMin", 0.2f, "DCAxy Min for De"}; Configurable settingCutPinMinTOFITSDe{"settingCutPinMinTOFITSDe", 1.2f, "Minimum p to apply the TOF ITS cut on De"}; Configurable settingCutNsigmaTPCDe{"settingCutNsigmaTPCDe", 2.5f, "Value of the TPC Nsigma cut on De"}; Configurable settingCutNsigmaITSDe{"settingCutNsigmaITSDe", 2.5f, "Value of the ITD Nsigma cut on De"}; @@ -255,11 +254,11 @@ struct HadNucleiFemto { {"hEmptyPool", "svPoolCreator did not find track pairs false/true", {HistType::kTH1F, {{2, -0.5, 1.5}}}}, // Candidate topology and kinematics - {"hTrackSel", "Accepted tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, + {"hTrackSel", "Accepted hadron tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, + {"hTrackSelDe", "Accepted deuteron tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, {"hdcaxyNu", ";DCA_{xy} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, {"hdcazNu", ";DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hdcazNu_min", ";DCA_{z}-min (cm)", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, {"hNClsNuITS", ";N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, {"hNuPt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, {"hSingleNuPt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, @@ -409,6 +408,7 @@ struct HadNucleiFemto { std::vector selectionLabels = {"All", "Track selection", "PID"}; for (int i = 0; i < Selections::kAll; i++) { mQaRegistry.get(HIST("hTrackSel"))->GetXaxis()->SetBinLabel(i + 1, selectionLabels[i].c_str()); + mQaRegistry.get(HIST("hTrackSelDe"))->GetXaxis()->SetBinLabel(i + 1, selectionLabels[i].c_str()); } std::vector eventsLabels = {"All", "Selected", "Zorro De events"}; @@ -513,6 +513,34 @@ struct HadNucleiFemto { return true; } + template + bool selectTrackDe(const Ttrack& candidate) + { + if (std::abs(candidate.eta()) > settingCutEta) { + return false; + } + + constexpr int minTPCNClsFound = 110; + constexpr int minTPCNClsCrossedRows = 100; + constexpr float minTPCCrossedRowsOverFound = 0.f; + constexpr int maxTPCNClsShared = 160; + constexpr float maxSharedTPCFraction = 1.f; + constexpr int minITSNClsInnerBarrel = 1; + const float tpcCrossedRowsOverFound = candidate.tpcNClsFound() > 0 ? static_cast(candidate.tpcNClsCrossedRows()) / candidate.tpcNClsFound() : 0.f; + + if (candidate.tpcNClsFound() < minTPCNClsFound || + candidate.tpcNClsCrossedRows() < minTPCNClsCrossedRows || + tpcCrossedRowsOverFound < minTPCCrossedRowsOverFound || + candidate.tpcNClsShared() > maxTPCNClsShared || + candidate.tpcFractionSharedCls() > maxSharedTPCFraction || + candidate.itsNCls() < settingCutNCls || + candidate.itsNClsInnerBarrel() < minITSNClsInnerBarrel) { + return false; + } + + return true; + } + template bool selectionPIDKaon(const Ttrack& candidate) { @@ -582,7 +610,7 @@ struct HadNucleiFemto { return false; mQaRegistry.fill(HIST("h2NsigmaHadPrTOF"), candidate.tofNSigmaPr()); - if (candidate.hasTOF() && candidate.tpcInnerParam() >= settingCutPinMinTOFHad) { + if (candidate.hasTOF() && std::abs(candidate.pt()) > settingCutPinMinTOFHad) { auto tofNSigmaPi = candidate.tofNSigmaPi(); auto combNsigma = std::sqrt(tofNSigmaPi * tofNSigmaPi + tpcNSigmaPi * tpcNSigmaPi); @@ -598,7 +626,7 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("h2NsigmaHadComb"), candidate.sign() * candidate.pt(), combNsigma); mQaRegistry.fill(HIST("h2dEdxHadcandidates"), candidate.sign() * candidate.tpcInnerParam(), candidate.tpcSignal()); return true; - } else if (candidate.tpcInnerParam() < settingCutPinMinTOFHad) { + } else if (std::abs(candidate.pt()) <= settingCutPinMinTOFHad) { if (std::abs(tpcNSigmaPi) > settingCutNsigmaTPCHad) { return false; } @@ -639,10 +667,6 @@ struct HadNucleiFemto { float tpcInnerParam = candidate.tpcInnerParam(); mQaRegistry.fill(HIST("h2dEdx"), candidate.sign() * tpcInnerParam, candidate.tpcSignal()); - float DeDCAxyMin = 0.015 + 0.0305 / TMath::Power(candidate.pt(), 1.1); - if (std::abs(candidate.dcaXY()) > DeDCAxyMin || std::abs(candidate.dcaZ()) > settingCutDeDCAzMin) - return false; - if (std::abs(tpcInnerParam) < settingCutPinMinDe) { return false; } @@ -657,6 +681,15 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("h2NsigmaNuTPC_preselecComp"), candidate.sign() * candidate.pt(), candidate.tpcNSigmaDe()); if (std::abs(candidate.pt()) < settingCutDeptMin || std::abs(candidate.pt()) > settingCutDeptMax) return false; + const float absPt = std::abs(candidate.pt()); + if (absPt <= 0.f) { + return false; + } + const float deDCAxyMax = 0.004f + 0.013f / absPt; + const float deDCAzMax = 0.004f + 0.013f / absPt; + if (std::abs(candidate.dcaXY()) > deDCAxyMax || std::abs(candidate.dcaZ()) > deDCAzMax) + return false; + if (candidate.hasTOF() && candidate.tpcInnerParam() > settingCutPinMinTOFITSDe) { auto tofNSigmaDe = candidate.tofNSigmaDe(); auto combNsigma = std::sqrt(tofNSigmaDe * tofNSigmaDe + tpcNSigmaDe * tpcNSigmaDe); @@ -908,7 +941,7 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); - if (!selectTrack(track0)) { + if (!selectTrackDe(track0)) { continue; } mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); @@ -985,7 +1018,7 @@ struct HadNucleiFemto { void pairTracksEventMixing(T& DeCands, T& hadCands) { for (const auto& DeCand : DeCands) { - if (!selectTrack(DeCand) || !selectionPIDDe(DeCand)) { + if (!selectTrackDe(DeCand) || !selectionPIDDe(DeCand)) { continue; } for (const auto& hadCand : hadCands) { @@ -1101,7 +1134,6 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("hdcazNu"), hadNucand.dcazNu); mQaRegistry.fill(HIST("hdcaxyHad"), hadNucand.dcaxyHad); mQaRegistry.fill(HIST("hdcazHad"), hadNucand.dcazHad); - mQaRegistry.fill(HIST("hdcazNu_min"), (std::abs(hadNucand.dcazNu) - settingCutDeDCAzMin)); mQaRegistry.fill(HIST("hNClsNuITS"), hadNucand.nClsItsNu); mQaRegistry.fill(HIST("hNClsHadITS"), hadNucand.nClsItsHad); mQaRegistry.fill(HIST("hisBkgEM"), hadNucand.isBkgEM); @@ -1364,21 +1396,27 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa trackTableThisCollision.bindExternalIndices(&tracks); for (const auto& track : trackTableThisCollision) { + const bool passTrackHad = selectTrack(track); + const bool passTrackDe = selectTrackDe(track); + mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); + if (passTrackHad) { + mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); + } - if (!selectTrack(track)) { - continue; + mQaRegistry.fill(HIST("hTrackSelDe"), Selections::kNoCuts); + if (passTrackDe) { + mQaRegistry.fill(HIST("hTrackSelDe"), Selections::kTrackCuts); } - mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); - if (settingHadPDGCode == PDG_t::kPiPlus) { + if (passTrackHad && settingHadPDGCode == PDG_t::kPiPlus) { const float tpcNSigmaHad = track.tpcNSigmaPi(); mQaRegistry.fill(HIST("purity/h2NsigmaHadTPC_preselection"), track.sign() * track.pt(), tpcNSigmaHad); - if (track.hasTOF() && track.tpcInnerParam() >= settingCutPinMinTOFHad) { + if (track.hasTOF() && std::abs(track.pt()) > settingCutPinMinTOFHad) { const float tofNSigmaHad = track.tofNSigmaPi(); mQaRegistry.fill(HIST("purity/h2NsigmaHadTOF_preselection"), track.sign() * track.pt(), tofNSigmaHad); } - } else if (settingHadPDGCode == PDG_t::kKPlus) { + } else if (passTrackHad && settingHadPDGCode == PDG_t::kKPlus) { const float tpcNSigmaHad = track.tpcNSigmaKa(); mQaRegistry.fill(HIST("purity/h2NsigmaHadTPC_preselection"), track.sign() * track.pt(), tpcNSigmaHad); if (track.hasTOF() && track.tpcInnerParam() >= settingCutPinMinTOFHad) { @@ -1387,29 +1425,32 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa } } - const float tpcNSigmaDe = settingUseBBcomputeDeNsigma ? computeNSigmaDe(track) : track.tpcNSigmaDe(); - mQaRegistry.fill(HIST("purity/h2NsigmaNuTPC_preselection"), track.sign() * track.pt(), tpcNSigmaDe); - mQaRegistry.fill(HIST("purity/h2NsigmaNuTPC_preselecComp"), track.sign() * track.pt(), track.tpcNSigmaDe()); - if (track.hasTOF() && track.tpcInnerParam() > settingCutPinMinTOFITSDe) { - const float tofNSigmaDe = track.tofNSigmaDe(); - mQaRegistry.fill(HIST("purity/h2NsigmaNuTOF_preselection"), track.sign() * track.pt(), tofNSigmaDe); - } else if (track.tpcInnerParam() <= settingCutPinMinTOFITSDe) { - const float itsNSigmaDe = itsResponse.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta()); - mQaRegistry.fill(HIST("purity/h2NSigmaNuITS_preselection"), track.sign() * track.pt(), itsNSigmaDe); + if (passTrackDe) { + const float tpcNSigmaDe = settingUseBBcomputeDeNsigma ? computeNSigmaDe(track) : track.tpcNSigmaDe(); + mQaRegistry.fill(HIST("purity/h2NsigmaNuTPC_preselection"), track.sign() * track.pt(), tpcNSigmaDe); + mQaRegistry.fill(HIST("purity/h2NsigmaNuTPC_preselecComp"), track.sign() * track.pt(), track.tpcNSigmaDe()); + if (track.hasTOF() && track.tpcInnerParam() > settingCutPinMinTOFITSDe) { + const float tofNSigmaDe = track.tofNSigmaDe(); + mQaRegistry.fill(HIST("purity/h2NsigmaNuTOF_preselection"), track.sign() * track.pt(), tofNSigmaDe); + } else if (track.tpcInnerParam() <= settingCutPinMinTOFITSDe) { + const float itsNSigmaDe = itsResponse.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta()); + mQaRegistry.fill(HIST("purity/h2NSigmaNuITS_preselection"), track.sign() * track.pt(), itsNSigmaDe); + } } - const bool isHadronSelected = selectionPIDHadron(track); - const bool isDeuteronSelected = selectionPIDDe(track); + const bool isHadronSelected = passTrackHad && selectionPIDHadron(track); + const bool isDeuteronSelected = passTrackDe && selectionPIDDe(track); if (!isHadronSelected && !isDeuteronSelected) { continue; } - mQaRegistry.fill(HIST("hTrackSel"), Selections::kPID); if (isHadronSelected) { + mQaRegistry.fill(HIST("hTrackSel"), Selections::kPID); mQaRegistry.fill(HIST("hSingleHadPt"), track.pt() * track.sign()); } if (isDeuteronSelected) { + mQaRegistry.fill(HIST("hTrackSelDe"), Selections::kPID); mQaRegistry.fill(HIST("hSingleNuPt"), track.pt() * track.sign()); mQaRegistry.fill(HIST("hSingleNuPin"), track.tpcInnerParam() * track.sign()); } From 67ce5ac846f9d066535e9f9dcbdb06ab72dc065c Mon Sep 17 00:00:00 2001 From: choich08365 <157435123+choich08365@users.noreply.github.com> Date: Tue, 12 May 2026 14:36:05 +0900 Subject: [PATCH 134/449] [PWGJE] Modified GNN b-jet analysis codes to utilise JE outlier rejector task (#16192) Co-authored-by: Changhwan Choi --- PWGJE/Tasks/bjetTaggingGnn.cxx | 421 ++++++++++++++++---------------- PWGJE/Tasks/bjetTreeCreator.cxx | 67 +++-- 2 files changed, 262 insertions(+), 226 deletions(-) diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 8a48eab4af5..e72fba2ccef 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -128,10 +128,6 @@ struct BjetTaggingGnn { Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable useEventWeight{"useEventWeight", true, "Flag whether to scale histograms with the event weight"}; - Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; - Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; - Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; - // track level configurables Configurable trackSelections{"trackSelections", "QualityTracks", "set track selections"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; @@ -254,7 +250,7 @@ struct BjetTaggingGnn { const AxisSpec axisDbFine{dbNbins, dbMin, dbMax, "#it{D}_{b}"}; const AxisSpec axisJetMass{200, 0., 50., "#it{m}_{jet} (GeV/#it{c}^{2})"}; const AxisSpec axisJetProb{200, 0., 40., "-ln(JP)"}; - const AxisSpec axisNTracks{42, 0, 42, "#it{n}_{tracks}"}; + const AxisSpec axisNTracks{42, 0, 42, "#it{N}_{tracks}"}; registry.add("h_jetpT", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetEta", "", {HistType::kTH1F, {axisJetEta}}, callSumw2); @@ -301,7 +297,8 @@ struct BjetTaggingGnn { registry.add("h_dcaXY_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, c hadron decay registry.add("h_dcaXY_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, others registry.add("h_dcaXY_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from mismatched collisions - registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // non-physical primary tracks (GenStatusCode=-1) + registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // non-physical primary tracks (GenStatusCode=-1) from matched collisions + registry.add("h_dcaXY_npp_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // non-physical primary tracks from mismatched collisions registry.add("h_dcaZ_coll_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); @@ -310,6 +307,7 @@ struct BjetTaggingGnn { registry.add("h_dcaZ_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_npp_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); } if (doprocessDataJetsSel || doprocessMCDJetsSel) { @@ -317,7 +315,6 @@ struct BjetTaggingGnn { registry.add("h_jetpT_selmc", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_tvx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_coll", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_inelgt0rec", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_sel8_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_selmc_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_tvx_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); @@ -372,7 +369,6 @@ struct BjetTaggingGnn { registry.add("h2_Response_DetjetpT_PartjetpT_b_tvx", "b-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h_jetpT_b_coll", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_b_coll_zvtx", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_b_inelgt0rec", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_inelgt0", "", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_b_inelgt0", "b-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); } @@ -388,31 +384,40 @@ struct BjetTaggingGnn { registry.add("h_jetpT_particle_lf", "particle lf-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_sel8", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_sel8", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_selmc", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_selmc", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_tvx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_tvx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_coll", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_coll", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_inel", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_sel8", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_selmc", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_tvx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_coll", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_b_inel", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_sel8", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_selmc", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_tvx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_coll", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_inel", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_sel8_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_sel8_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_selmc_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_selmc_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_tvx_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_tvx_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_coll_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_coll_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_inel_zvtx", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_sel8_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_selmc_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_tvx_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_b_coll_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_b_inel_zvtx", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_sel8_zvtx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_selmc_zvtx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_tvx_zvtx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_coll_zvtx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_inel_zvtx", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_inelgt0", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_b_inelgt0", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_inelgt0rec", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("h_jetpT_particle_b_inelgt0rec", "particle b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetpT_particle_c_inelgt0", "particle c-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); } if (doDataDriven) { @@ -446,28 +451,29 @@ struct BjetTaggingGnn { using FilteredCollisions = soa::Filtered; using AnalysisCollisionsTriggered = soa::Join; using FilteredCollisionsTriggered = soa::Filtered; - using OrigCollisions = soa::Join; + // using OrigCollisions = soa::Join; using DataJets = soa::Join; using FilteredDataJets = soa::Filtered; using AnalysisTracks = soa::Join; using FilteredTracks = soa::Filtered; - using OriginalTracks = soa::Join; + // using OriginalTracks = soa::Join; using MCDJets = soa::Join; using FilteredMCDJets = soa::Filtered; using AnalysisTracksMCD = soa::Join; using FilteredTracksMCD = soa::Filtered; - using AnalysisCollisionsMCD = soa::Join; + using AnalysisCollisionsMCD = soa::Join; using FilteredCollisionsMCD = soa::Filtered; Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; - using FilteredCollisionsMCP = soa::Filtered; + using AnalysisCollisionsMCP = soa::Join; + using FilteredCollisionsMCP = soa::Filtered; using MCPJets = soa::Join; using FilteredMCPJets = soa::Filtered; - template - int analyzeJetTrackInfo(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const /*origTracks*/ /*, int8_t jetFlavor = 0, double weight = 1.0*/) + template + int analyzeJetTrackInfo(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/ /*, int8_t jetFlavor = 0, double weight = 1.0*/) { int nTracks = 0; for (const auto& constituent : analysisJet.template tracks_as()) { @@ -477,21 +483,21 @@ struct BjetTaggingGnn { } int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); - auto origConstit = constituent.template track_as(); + // auto origConstit = constituent.template track_as(); registry.fill(HIST("h_gnnfeat_trackpT"), constituent.pt()); - registry.fill(HIST("h_gnnfeat_trackPhi"), origConstit.phi()); + registry.fill(HIST("h_gnnfeat_trackPhi"), constituent.phi()); registry.fill(HIST("h_gnnfeat_trackEta"), constituent.eta()); registry.fill(HIST("h_gnnfeat_trackCharge"), static_cast(constituent.sign())); registry.fill(HIST("h_gnnfeat_trackDCAxy"), std::abs(constituent.dcaXY()) * sign); registry.fill(HIST("h_gnnfeat_trackSigmaDCAxy"), constituent.sigmadcaXY()); registry.fill(HIST("h_gnnfeat_trackDCAz"), std::abs(constituent.dcaZ()) * sign); registry.fill(HIST("h_gnnfeat_trackSigmaDCAz"), constituent.sigmadcaZ()); - registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls())); - registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound())); - registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows())); - registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl()); - registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl()); + // registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls())); + // registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound())); + // registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows())); + // registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl()); + // registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl()); registry.fill(HIST("h_gnnfeat_tracksIPxy"), std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY()); registry.fill(HIST("h_gnnfeat_tracksIPz"), std::abs(constituent.dcaZ()) * sign / constituent.sigmadcaZ()); @@ -504,7 +510,6 @@ struct BjetTaggingGnn { template bool isAcceptedJet(AnalysisJet const& jet) { - if (jetAreaFractionMin > -98.0) { if (jet.area() < jetAreaFractionMin * M_PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { return false; @@ -537,10 +542,10 @@ struct BjetTaggingGnn { return true; } - template - void fillDataJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& allTracks, AnyOriginalTracks const& origTracks) + template + void fillDataJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& allTracks) { - int nTracks = analyzeJetTrackInfo(analysisJet, allTracks, origTracks); + int nTracks = analyzeJetTrackInfo(analysisJet, allTracks); registry.fill(HIST("h_jetpT"), analysisJet.pt()); registry.fill(HIST("h_jetPhi"), analysisJet.phi()); @@ -559,8 +564,8 @@ struct BjetTaggingGnn { } } - template - int8_t fillMCDJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, double weightEvt = 1.0) + template + int8_t fillMCDJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, double weightEvt = 1.0) { int8_t jetFlavor = analysisJet.origin(); @@ -575,24 +580,24 @@ struct BjetTaggingGnn { } int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); - auto origConstit = constituent.template track_as(); - - registry.fill(HIST("h_gnnfeat_trackpT"), constituent.pt()); - registry.fill(HIST("h_gnnfeat_trackPhi"), origConstit.phi()); - registry.fill(HIST("h_gnnfeat_trackEta"), constituent.eta()); - registry.fill(HIST("h_gnnfeat_trackCharge"), static_cast(constituent.sign())); - registry.fill(HIST("h_gnnfeat_trackDCAxy"), std::abs(constituent.dcaXY()) * sign); - registry.fill(HIST("h_gnnfeat_trackSigmaDCAxy"), constituent.sigmadcaXY()); - registry.fill(HIST("h_gnnfeat_trackDCAz"), std::abs(constituent.dcaZ()) * sign); - registry.fill(HIST("h_gnnfeat_trackSigmaDCAz"), constituent.sigmadcaZ()); - registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls())); - registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound())); - registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows())); - registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl()); - registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl()); - - registry.fill(HIST("h_gnnfeat_tracksIPxy"), std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY()); - registry.fill(HIST("h_gnnfeat_tracksIPz"), std::abs(constituent.dcaZ()) * sign / constituent.sigmadcaZ()); + // auto origConstit = constituent.template track_as(); + + registry.fill(HIST("h_gnnfeat_trackpT"), constituent.pt(), weightEvt); + registry.fill(HIST("h_gnnfeat_trackPhi"), constituent.phi(), weightEvt); + registry.fill(HIST("h_gnnfeat_trackEta"), constituent.eta(), weightEvt); + registry.fill(HIST("h_gnnfeat_trackCharge"), static_cast(constituent.sign()), weightEvt); + registry.fill(HIST("h_gnnfeat_trackDCAxy"), std::abs(constituent.dcaXY()) * sign, weightEvt); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAxy"), constituent.sigmadcaXY(), weightEvt); + registry.fill(HIST("h_gnnfeat_trackDCAz"), std::abs(constituent.dcaZ()) * sign, weightEvt); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAz"), constituent.sigmadcaZ(), weightEvt); + // registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls()), weightEvt); + // registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound()), weightEvt); + // registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows()), weightEvt); + // registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl(), weightEvt); + // registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl(), weightEvt); + + registry.fill(HIST("h_gnnfeat_tracksIPxy"), std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY(), weightEvt); + registry.fill(HIST("h_gnnfeat_tracksIPz"), std::abs(constituent.dcaZ()) * sign / constituent.sigmadcaZ(), weightEvt); ++nTracks; } @@ -725,10 +730,10 @@ struct BjetTaggingGnn { registry.fill(HIST("hCollCounter"), static_cast(EvtSel::Sel8), weightEvt); // Coll+TVX+NoTFB+NoITSROFB if (zvtx) { registry.fill(HIST("hCollCounter"), static_cast(EvtSel::Sel8Zvtx), weightEvt); // Coll+TVX+NoTFB+NoITSROFB+Zvtx - if (collision.template collision_as().isInelGt0()) { - evtselCode |= EvtSelFlag::kINELgt0rec; - registry.fill(HIST("hCollCounter"), static_cast(EvtSel::INELgt0rec), weightEvt); // INELgt0+Zvtx(rec) - } + // if (collision.template collision_as().isInelGt0()) { + // evtselCode |= EvtSelFlag::kINELgt0rec; + // registry.fill(HIST("hCollCounter"), static_cast(EvtSel::INELgt0rec), weightEvt); // INELgt0+Zvtx(rec) + // } } } } @@ -752,7 +757,7 @@ struct BjetTaggingGnn { } PROCESS_SWITCH(BjetTaggingGnn, processDummy, "Dummy process function turned on by default", true); - void processDataJets(FilteredCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, OriginalTracks const& origTracks) + void processDataJets(FilteredCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -766,12 +771,12 @@ struct BjetTaggingGnn { continue; } - fillDataJetHistograms(analysisJet, allTracks, origTracks); + fillDataJetHistograms(analysisJet, allTracks); } } PROCESS_SWITCH(BjetTaggingGnn, processDataJets, "jet information in Data", false); - void processDataJetsTrig(FilteredCollisionsTriggered::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, OriginalTracks const& origTracks, aod::JBCs const& /*bcInfo*/) + void processDataJetsTrig(FilteredCollisionsTriggered::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, aod::JBCs const& /*bcInfo*/) { // Get BC info associated with the collision before applying any event selections auto bc = collision.bc_as(); @@ -794,12 +799,12 @@ struct BjetTaggingGnn { continue; } - fillDataJetHistograms(analysisJet, allTracks, origTracks); + fillDataJetHistograms(analysisJet, allTracks); } } PROCESS_SWITCH(BjetTaggingGnn, processDataJetsTrig, "jet information in software triggered Data", false); - void processDataJetsSel(AnalysisCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& /*allTracks*/, OrigCollisions const& /*origCollisions*/) + void processDataJetsSel(AnalysisCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& /*allTracks*/) { EvtSelFlag evtselCode = fillCollCounter(collision); @@ -816,7 +821,6 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetpT_selmc_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx)); registry.fill(HIST("h_jetpT_sel8"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8)); registry.fill(HIST("h_jetpT_sel8_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx)); - registry.fill(HIST("h_jetpT_inelgt0rec"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0rec)); } } PROCESS_SWITCH(BjetTaggingGnn, processDataJetsSel, "jet information in Data (event selection)", false); @@ -842,11 +846,18 @@ struct BjetTaggingGnn { } PROCESS_SWITCH(BjetTaggingGnn, processDataTracks, "track information in Data", false); - void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, OriginalTracks const& origTracks, FilteredMCPJets const& /*MCPjets*/, aod::JetParticles const& /*mcParticles*/, FilteredCollisionsMCP const& /*mcCollisions*/) + void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, FilteredMCPJets const& /*MCPjets*/, aod::JetParticles const& /*mcParticles*/, FilteredCollisionsMCP const& /*mcCollisions*/) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } + // Reject outlier MC collisions + if (collision.isOutlier()) { + return; + } + if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + return; + } // Uses only collisionId % trainingDatasetRaioParam != 0 for evaluation dataset if (trainingDatasetRatioParam && collision.collisionId() % trainingDatasetRatioParam == 0) { return; @@ -864,21 +875,12 @@ struct BjetTaggingGnn { continue; } - float pTHat = 10. / (std::pow(weightEvt, 1.0 / pTHatExponent)); - if (useEventWeight && analysisJet.pt() > pTHatMaxMCD * pTHat) { - continue; - } - - int8_t jetFlavor = fillMCDJetHistograms(analysisJet, allTracks, origTracks, weightEvt); + int8_t jetFlavor = fillMCDJetHistograms(analysisJet, allTracks, weightEvt); if (!matchedMcColl) { continue; } for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { - if (mcpjet.pt() > pTHatMaxMCP * pTHat) { - continue; - } - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT"), analysisJet.pt(), mcpjet.pt(), weightEvt); registry.fill(HIST("h_jetpT_matched"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_jetpT_particle_matched"), mcpjet.pt(), weightEvt); @@ -896,34 +898,26 @@ struct BjetTaggingGnn { } PROCESS_SWITCH(BjetTaggingGnn, processMCDJets, "jet information in MC", false); - void processMCDJetsSel(AnalysisCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& /*allTracks*/, FilteredMCPJets const& /*MCPjets*/, OrigCollisions const& /*origCollisions*/, FilteredCollisionsMCP const& /*mcCollisions*/, aod::JetParticles const& mcParticles) + void processMCDJetsSel(AnalysisCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& /*allTracks*/, FilteredMCPJets const& /*MCPjets*/, FilteredCollisionsMCP const& /*mcCollisions*/) { + // Reject outlier MC collisions + if (collision.isOutlier()) { + return; + } + if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + return; + } + float weightEvt = useEventWeight ? collision.weight() : 1.f; EvtSelFlag evtselCode = fillCollCounter(collision, weightEvt); - bool isTrueINELgt0 = collision.has_mcCollision() && isTrueINEL0(collision.template mcCollision_as(), mcParticles); for (const auto& analysisJet : MCDjets) { if (!isAcceptedJet(analysisJet)) { continue; } - float pTHat = 10. / (std::pow(weightEvt, 1.0 / pTHatExponent)); - if (useEventWeight && analysisJet.pt() > pTHatMaxMCD * pTHat) { - continue; - } - int8_t jetFlavor = analysisJet.origin(); - // Get matched particle-level jet pT - double mcpjetpT = -1.0; - for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { - if (useEventWeight && mcpjet.pt() > pTHatMaxMCP * pTHat) { - continue; - } - mcpjetpT = mcpjet.pt(); - } - bool isMatched = mcpjetpT > 0.0; - registry.fill(HIST("h_jetpT_coll"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_coll_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_tvx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); @@ -932,12 +926,6 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetpT_selmc_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_sel8"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_sel8_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_inelgt0rec"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0rec) ? weightEvt : 0.0); - if (isMatched) { - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_selmc"), analysisJet.pt(), mcpjetpT, hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_sel8"), analysisJet.pt(), mcpjetpT, hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_inelgt0"), analysisJet.pt(), mcpjetpT, isTrueINELgt0 && (hasAll(evtselCode, EvtSelFlag::INELgt0rec)) ? weightEvt : 0.0); - } if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h_jetpT_b_coll"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_b_coll_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); @@ -947,142 +935,147 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetpT_b_selmc_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_b_sel8"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_b_sel8_zvtx"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_b_inelgt0rec"), analysisJet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0rec) ? weightEvt : 0.0); - if (isMatched) { - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_b_selmc"), analysisJet.pt(), mcpjetpT, hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_b_sel8"), analysisJet.pt(), mcpjetpT, hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_b_inelgt0"), analysisJet.pt(), mcpjetpT, isTrueINELgt0 && (hasAll(evtselCode, EvtSelFlag::INELgt0rec)) ? weightEvt : 0.0); - } } } } PROCESS_SWITCH(BjetTaggingGnn, processMCDJetsSel, "jet information in MC (event selection)", false); PresliceUnsorted collisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; - Preslice mcpjetsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; + Preslice mcpjetsPerMCPCollision = aod::jet::mcCollisionId; - void processMCPJets(aod::McCollisions::iterator const& mcCollision, FilteredMCPJets const& mcpjets, AnalysisCollisionsMCD const& collisions, OrigCollisions const& /*origCollisions*/, aod::JetParticles const& mcParticles) + void processMCPJets(AnalysisCollisionsMCP const& mcCollisions, FilteredMCPJets const& mcpjets, AnalysisCollisionsMCD const& collisions, aod::JetParticles const& mcParticles) { - float weightEvt = useEventWeight ? mcCollision.weight() : 1.f; - auto matchedCollisions = collisions.sliceBy(collisionsPerMCPCollision, mcCollision.globalIndex()); + // Subscribing AnalysisCollisionsMCP::iterator causes an issue related to unsorted JMcCollisionLbs index. + for (const auto& mcCollision : mcCollisions) { + if (mcCollision.isOutlier()) { + continue; + } + float weightEvt = useEventWeight ? mcCollision.weight() : 1.f; + auto matchedCollisions = collisions.sliceBy(collisionsPerMCPCollision, mcCollision.mcCollisionId()); - EvtSelFlag evtselCode = EvtSelFlag::INEL; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INEL), weightEvt); // INEL - registry.fill(HIST("h_vertexZ_truth"), mcCollision.posZ(), weightEvt); + EvtSelFlag evtselCode = EvtSelFlag::INEL; + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INEL), weightEvt); // INEL + registry.fill(HIST("h_vertexZ_truth"), mcCollision.posZ(), weightEvt); - bool zvtx = std::fabs(mcCollision.posZ()) < vertexZCut; - bool zvtxMatched = false; + bool zvtx = std::fabs(mcCollision.posZ()) < vertexZCut; + bool zvtxMatched = false; - bool isTrueINELgt0 = isTrueINEL0(mcCollision, mcParticles); - if (zvtx) { - evtselCode |= EvtSelFlag::kZvtx; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELZvtx), weightEvt); // INEL+Zvtx - if (isTrueINELgt0) { - evtselCode |= EvtSelFlag::kINELgt0; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELgt0), weightEvt); // INELgt0 + bool isTrueINELgt0 = isTrueINEL0(mcCollision, mcParticles); + if (zvtx) { + evtselCode |= EvtSelFlag::kZvtx; + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELZvtx), weightEvt); // INEL+Zvtx + if (isTrueINELgt0) { + evtselCode |= EvtSelFlag::kINELgt0; + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELgt0), weightEvt); // INELgt0 + } } - } - bool isMatchedToAnalysisSelection = false; + bool isMatchedToAnalysisSelection = false; - if (matchedCollisions.size() >= 1) { - zvtxMatched = std::fabs(matchedCollisions.begin().posZ()) < vertexZCut; - evtselCode |= EvtSelFlag::kColl; - registry.fill(HIST("h_vertexZ_truth_coll"), mcCollision.posZ(), weightEvt); - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Coll), weightEvt); // McColl(-> Coll) - if (zvtxMatched) { - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::CollZvtx), weightEvt); // McColl(-> Coll+Zvtx) - } - if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsTVX)) { - evtselCode |= EvtSelFlag::kTVX; - registry.fill(HIST("h_vertexZ_truth_tvx"), mcCollision.posZ(), weightEvt); - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::TVX), weightEvt); // McColl(-> Coll+TVX) + if (matchedCollisions.size() >= 1) { + zvtxMatched = std::fabs(matchedCollisions.begin().posZ()) < vertexZCut; + evtselCode |= EvtSelFlag::kColl; + registry.fill(HIST("h_vertexZ_truth_coll"), mcCollision.posZ(), weightEvt); + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Coll), weightEvt); // McColl(-> Coll) if (zvtxMatched) { - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::TVXZvtx), weightEvt); // McColl(-> Coll+TVX+Zvtx) + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::CollZvtx), weightEvt); // McColl(-> Coll+Zvtx) } - if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsSelMC)) { - evtselCode |= EvtSelFlag::kNoTFB; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::SelMC), weightEvt); // McColl(-> Coll+TVX+NoTFB) + if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsTVX)) { + evtselCode |= EvtSelFlag::kTVX; + registry.fill(HIST("h_vertexZ_truth_tvx"), mcCollision.posZ(), weightEvt); + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::TVX), weightEvt); // McColl(-> Coll+TVX) if (zvtxMatched) { - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::SelMCZvtx), weightEvt); // McColl(-> Coll+TVX+NoTFB+Zvtx) + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::TVXZvtx), weightEvt); // McColl(-> Coll+TVX+Zvtx) } - if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsSel8)) { - evtselCode |= EvtSelFlag::kNoITSROFB; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Sel8), weightEvt); // McColl(-> Coll+TVX+NoTFB+NoITSROFB) + if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsSelMC)) { + evtselCode |= EvtSelFlag::kNoTFB; + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::SelMC), weightEvt); // McColl(-> Coll+TVX+NoTFB) if (zvtxMatched) { - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Sel8Zvtx), weightEvt); // McColl(-> Coll+TVX+NoTFB+NoITSROFB+Zvtx) - if (matchedCollisions.begin().template collision_as().isInelGt0()) { - evtselCode |= EvtSelFlag::kINELgt0rec; - registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELgt0rec), weightEvt); // INELgt0+Zvtx(rec) + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::SelMCZvtx), weightEvt); // McColl(-> Coll+TVX+NoTFB+Zvtx) + } + if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBitsSel8)) { + evtselCode |= EvtSelFlag::kNoITSROFB; + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Sel8), weightEvt); // McColl(-> Coll+TVX+NoTFB+NoITSROFB) + if (zvtxMatched) { + registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::Sel8Zvtx), weightEvt); // McColl(-> Coll+TVX+NoTFB+NoITSROFB+Zvtx) + // if (matchedCollisions.begin().template collision_as().isInelGt0()) { + // evtselCode |= EvtSelFlag::kINELgt0rec; + // registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INELgt0rec), weightEvt); // INELgt0+Zvtx(rec) + // } } } } } - } - if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBits) && zvtxMatched) { - isMatchedToAnalysisSelection = true; - registry.fill(HIST("h_event_counter_mcp"), 0.0, weightEvt); - } - } - - auto mcpjetspermcpcollision = mcpjets.sliceBy(mcpjetsPerMCPCollision, mcCollision.globalIndex()); - for (const auto& mcpjet : mcpjetspermcpcollision) { - bool jetIncluded = false; - for (const auto& jetR : jetRadiiValues) { - if (mcpjet.r() == static_cast(jetR * 100)) { - jetIncluded = true; - break; + if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBits) && zvtxMatched) { + isMatchedToAnalysisSelection = true; + registry.fill(HIST("h_event_counter_mcp"), 0.0, weightEvt); } } - if (!jetIncluded) { - continue; - } - - float pTHat = 10. / (std::pow(weightEvt, 1.0 / pTHatExponent)); - if (useEventWeight && mcpjet.pt() > pTHatMaxMCP * pTHat) { - continue; - } - - int8_t jetFlavor = mcpjet.origin(); - - registry.fill(HIST("h_jetpT_particle_inel"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INEL) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_inel_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_coll"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_coll_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_tvx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_tvx_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVXZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_selmc"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMC) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_selmc_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_sel8"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_inelgt0rec"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0rec) ? weightEvt : 0.0); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_b_inel"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INEL) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_inel_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_coll"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_coll_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_tvx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_tvx_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVXZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_selmc"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMC) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_selmc_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_sel8"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); - registry.fill(HIST("h_jetpT_particle_b_inelgt0rec"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0rec) ? weightEvt : 0.0); - } + auto mcpjetspermcpcollision = mcpjets.sliceBy(mcpjetsPerMCPCollision, mcCollision.mcCollisionId()); + for (const auto& mcpjet : mcpjetspermcpcollision) { + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } - // Fill histograms for jets matched to the analysis event selection - if (isMatchedToAnalysisSelection) { - registry.fill(HIST("h_jetpT_particle"), mcpjet.pt(), weightEvt); + if (!jetIncluded) { + continue; + } + int8_t jetFlavor = mcpjet.origin(); + + registry.fill(HIST("h_jetpT_particle_inel"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INEL) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_inel_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_coll"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_coll_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_tvx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_tvx_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVXZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_selmc"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMC) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_selmc_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_sel8"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_b"), mcpjet.pt(), weightEvt); + registry.fill(HIST("h_jetpT_particle_b_inel"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INEL) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_inel_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_coll"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_coll_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_tvx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_tvx_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVXZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_selmc"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMC) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_selmc_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_sel8"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_b_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_c"), mcpjet.pt(), weightEvt); - } else { - registry.fill(HIST("h_jetpT_particle_lf"), mcpjet.pt(), weightEvt); + registry.fill(HIST("h_jetpT_particle_c_inel"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INEL) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_inel_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_coll"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Coll) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_coll_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::CollZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_tvx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVX) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_tvx_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::TVXZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_selmc"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMC) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_selmc_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::SelMCZvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_sel8"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); + registry.fill(HIST("h_jetpT_particle_c_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); + } + + // Fill histograms for jets matched to the analysis event selection + if (isMatchedToAnalysisSelection) { + registry.fill(HIST("h_jetpT_particle"), mcpjet.pt(), weightEvt); + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_b"), mcpjet.pt(), weightEvt); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_c"), mcpjet.pt(), weightEvt); + } else { + registry.fill(HIST("h_jetpT_particle_lf"), mcpjet.pt(), weightEvt); + } } } } @@ -1093,15 +1086,22 @@ struct BjetTaggingGnn { void processMCDTracks(FilteredCollisionsMCD::iterator const& collision, AnalysisTracksMCD const& tracks, FilteredCollisionsMCP const& /*mcCollisions*/, aod::JetParticles const& allParticles) { - float weightEvt = useEventWeight ? collision.weight() : 1.f; if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } + // Reject outlier MC collisions + if (collision.isOutlier()) { + return; + } + if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + return; + } // Uses only collisionId % trainingDatasetRaioParam != 0 for evaluation dataset if (trainingDatasetRatioParam && collision.collisionId() % trainingDatasetRatioParam == 0) { return; } + float weightEvt = useEventWeight ? collision.weight() : 1.f; bool matchedMcColl = collision.has_mcCollision() && std::fabs(collision.template mcCollision_as().posZ()) < vertexZCut; for (const auto& track : tracks) { @@ -1158,8 +1158,13 @@ struct BjetTaggingGnn { registry.fill(HIST("h_dcaZ_coll_mismatched"), std::fabs(track.dcaZ()), weightEvt); } } else { - registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); - registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); + if (particle.mcCollisionId() == collision.mcCollisionId()) { + registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); + } else { + registry.fill(HIST("h_dcaXY_npp_mismatched"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_npp_mismatched"), std::fabs(track.dcaZ()), weightEvt); + } } } } diff --git a/PWGJE/Tasks/bjetTreeCreator.cxx b/PWGJE/Tasks/bjetTreeCreator.cxx index a5c85560f26..4adb20dc780 100644 --- a/PWGJE/Tasks/bjetTreeCreator.cxx +++ b/PWGJE/Tasks/bjetTreeCreator.cxx @@ -136,6 +136,15 @@ DECLARE_SOA_TABLE(bjetTracksParams, "AOD", "BJETTRACKSPARAM", using bjetTracksParam = bjetTracksParams::iterator; DECLARE_SOA_TABLE(bjetTracksParamsExtra, "AOD", "BJETTRACKSEXTRA", + // o2::soa::Index<>, + trackInfo::TrackPhi, + trackInfo::TrackCharge, + trackInfo::TrackOrigin, + trackInfo::TrackVtxIndex); + +using bjetTracksParamExtra = bjetTracksParamsExtra::iterator; + +DECLARE_SOA_TABLE(bjetTracksParamsExtrb, "AOD", "BJETTRACKSEXTRB", // o2::soa::Index<>, trackInfo::TrackPhi, trackInfo::TrackCharge, @@ -147,7 +156,7 @@ DECLARE_SOA_TABLE(bjetTracksParamsExtra, "AOD", "BJETTRACKSEXTRA", trackInfo::TrackOrigin, trackInfo::TrackVtxIndex); -using bjetTracksParamExtra = bjetTracksParamsExtra::iterator; +using bjetTracksParamExtrb = bjetTracksParamsExtrb::iterator; namespace SVInfo { @@ -204,6 +213,7 @@ struct BJetTreeCreator { Produces bjetParamsExtraTable; Produces bjetTracksParamsTable; Produces bjetTracksExtraTable; + Produces bjetTracksExtrbTable; Produces bjetSVParamsTable; Produces bjetConstituentsTable; @@ -257,6 +267,7 @@ struct BJetTreeCreator { Configurable vtxRes{"vtxRes", 0.01, "Vertex position resolution (cluster size) for GNN vertex predictions (cm)"}; Configurable trainingDatasetRatioParam{"trainingDatasetRatioParam", 0, "Parameter for splitting training/evaluation datasets by collisionId"}; + Configurable produceExtrbTableGnn{"produceExtrbTableGnn", false, "Flag whether to produce the extra table with track quality variables for GNN training"}; std::vector eventSelectionBits; @@ -345,16 +356,18 @@ struct BJetTreeCreator { registry.add("h_trk_dcaz", "trk_dcaxyz;#it{DCA}_{z} (cm);Entries", {HistType::kTH1F, {{200, -0.1, 0.1}}}); registry.add("h_trk_sigmadcaxy", "trk_sigmadcaxy;#it{#sigma}_{#it{DCA}_{xy}} (cm);Entries", {HistType::kTH1F, {{200, 0., 0.1}}}); registry.add("h_trk_sigmadcaz", "trk_sigmadcaxyz;#it{#sigma}_{#it{DCA}_{z}} (cm);Entries", {HistType::kTH1F, {{200, 0., 0.1}}}); - registry.add("h_trk_itsncls", "trk_itsncls;ITS NCls;Entries", {HistType::kTH1F, {{10, 0., 10.}}}); - registry.add("h_trk_tpcncls", "trk_tpcncls;TPC NCls (Found);Entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_trk_tpcncrs", "trk_tpcncrs;TPC NCrossedRows;Entries", {HistType::kTH1F, {{200, 0., 200.}}}); - registry.add("h_trk_itschi2ncl", "trk_itschi2ncl;ITS #it{#chi}^{2}/ndf;Entries", {HistType::kTH1F, {{200, 0., 20.}}}); - registry.add("h_trk_tpcchi2ncl", "trk_tpcchi2ncl;TPC #it{#chi}^{2}/ndf;Entries", {HistType::kTH1F, {{200, 0., 10.}}}); - registry.add("h2_trk_jtrackpt_vs_origtrackpt", "JTracks::pt vs Tracks::pt", {HistType::kTH2F, {{200, 0., 100.}, {200, 0., 100.}}}); + if (produceExtrbTableGnn) { + registry.add("h_trk_itsncls", "trk_itsncls;ITS NCls;Entries", {HistType::kTH1F, {{10, 0., 10.}}}); + registry.add("h_trk_tpcncls", "trk_tpcncls;TPC NCls (Found);Entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_trk_tpcncrs", "trk_tpcncrs;TPC NCrossedRows;Entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_trk_itschi2ncl", "trk_itschi2ncl;ITS #it{#chi}^{2}/ndf;Entries", {HistType::kTH1F, {{200, 0., 20.}}}); + registry.add("h_trk_tpcchi2ncl", "trk_tpcchi2ncl;TPC #it{#chi}^{2}/ndf;Entries", {HistType::kTH1F, {{200, 0., 10.}}}); + registry.add("h2_trk_jtrackpt_vs_origtrackpt", "JTracks::pt vs Tracks::pt", {HistType::kTH2F, {{200, 0., 100.}, {200, 0., 100.}}}); + } registry.add("h_trk_vtx_index", "trk_vtx_index;Vertex index;Entries", {HistType::kTH1F, {{20, 0., 20.}}}); registry.add("h_trk_origin", "trk_origin;Track origin;Entries", {HistType::kTH1F, {{5, 0., 5.}}}); auto hTrackOrigin = registry.get(HIST("h_trk_origin")); - hTrackOrigin->GetXaxis()->SetBinLabel(1, "NotPhysPrim"); + hTrackOrigin->GetXaxis()->SetBinLabel(1, "Background"); hTrackOrigin->GetXaxis()->SetBinLabel(2, "Charm"); hTrackOrigin->GetXaxis()->SetBinLabel(3, "Beauty"); hTrackOrigin->GetXaxis()->SetBinLabel(4, "Primary"); @@ -577,23 +590,29 @@ struct BJetTreeCreator { //+trk registry.fill(HIST("h_trk_pt"), constituent.pt(), eventweight); registry.fill(HIST("h_trk_eta"), constituent.eta(), eventweight); - registry.fill(HIST("h_trk_phi"), origConstit.phi(), eventweight); + registry.fill(HIST("h_trk_phi"), constituent.phi(), eventweight); registry.fill(HIST("h_trk_charge"), constituent.sign(), eventweight); registry.fill(HIST("h_trk_dcaxy"), std::abs(constituent.dcaXY()) * sign, eventweight); registry.fill(HIST("h_trk_dcaz"), std::abs(constituent.dcaZ()) * sign, eventweight); registry.fill(HIST("h_trk_sigmadcaxy"), constituent.sigmadcaXY(), eventweight); registry.fill(HIST("h_trk_sigmadcaz"), constituent.sigmadcaZ(), eventweight); - registry.fill(HIST("h_trk_itsncls"), origConstit.itsNCls(), eventweight); - registry.fill(HIST("h_trk_tpcncls"), origConstit.tpcNClsFound(), eventweight); - registry.fill(HIST("h_trk_tpcncrs"), origConstit.tpcNClsCrossedRows(), eventweight); - registry.fill(HIST("h_trk_itschi2ncl"), origConstit.itsChi2NCl(), eventweight); - registry.fill(HIST("h_trk_tpcchi2ncl"), origConstit.tpcChi2NCl(), eventweight); - registry.fill(HIST("h2_trk_jtrackpt_vs_origtrackpt"), constituent.pt(), origConstit.pt(), eventweight); // jtrack & new extra table are well joined (linear correlation) + if (produceExtrbTableGnn) { + registry.fill(HIST("h_trk_itsncls"), origConstit.itsNCls(), eventweight); + registry.fill(HIST("h_trk_tpcncls"), origConstit.tpcNClsFound(), eventweight); + registry.fill(HIST("h_trk_tpcncrs"), origConstit.tpcNClsCrossedRows(), eventweight); + registry.fill(HIST("h_trk_itschi2ncl"), origConstit.itsChi2NCl(), eventweight); + registry.fill(HIST("h_trk_tpcchi2ncl"), origConstit.tpcChi2NCl(), eventweight); + registry.fill(HIST("h2_trk_jtrackpt_vs_origtrackpt"), constituent.pt(), origConstit.pt(), eventweight); // jtrack & new extra table are well joined (linear correlation) + } registry.fill(HIST("h_trk_vtx_index"), trkVtxIndex); registry.fill(HIST("h_trk_origin"), trkOrigin); if (produceTree) { - bjetTracksExtraTable(/*bjetParamsTable.lastIndex() + 1, */ origConstit.phi(), constituent.sign(), origConstit.itsChi2NCl(), origConstit.tpcChi2NCl(), origConstit.itsNCls(), origConstit.tpcNClsFound(), origConstit.tpcNClsCrossedRows(), trkOrigin, trkVtxIndex); //+ + if (produceExtrbTableGnn) { + bjetTracksExtrbTable(/*bjetParamsTable.lastIndex() + 1, */ constituent.phi(), constituent.sign(), origConstit.itsChi2NCl(), origConstit.tpcChi2NCl(), origConstit.itsNCls(), origConstit.tpcNClsFound(), origConstit.tpcNClsCrossedRows(), trkOrigin, trkVtxIndex); //+ + } else { + bjetTracksExtraTable(/*bjetParamsTable.lastIndex() + 1, */ constituent.phi(), constituent.sign(), trkOrigin, trkVtxIndex); //+ + } } } @@ -762,10 +781,13 @@ struct BJetTreeCreator { } PROCESS_SWITCH(BJetTreeCreator, processMCJets, "jet information in MC", false); + using FilteredCollisionMCDOutlier = soa::Filtered>; using MCDJetTableNoSV = soa::Filtered>; + using AnalysisCollisionsMCPOutlier = soa::Join; using JetParticleswID = soa::Join; - void processMCJetsForGNN(FilteredCollisionMCD::iterator const& collision, aod::JMcCollisions const&, MCDJetTableNoSV const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, JetParticleswID const& MCParticles, OriginalTracks const& origTracks, aod::McParticles const& origParticles) + // aod::McParticles::vx(), vy(), vz() are necessary for jettaggingutilities::vertexClustering() + void processMCJetsForGNN(FilteredCollisionMCDOutlier::iterator const& collision, MCDJetTableNoSV const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, JetParticleswID const& MCParticles, AnalysisCollisionsMCPOutlier const&, OriginalTracks const& origTracks, aod::McParticles const& origParticles) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || (static_cast(std::rand()) / RAND_MAX < eventReductionFactor)) { return; @@ -776,6 +798,14 @@ struct BJetTreeCreator { return; } + // Reject outlier MC collisions + if (collision.isOutlier()) { + return; + } + if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + return; + } + float eventWeight = collision.weight(); registry.fill(HIST("h_vertexZ"), collision.posZ(), eventWeight); @@ -799,7 +829,7 @@ struct BJetTreeCreator { //+ TrackLabelMap trkLabels{{"trkVtxIndex", {}}, {"trkOrigin", {}}}; - int nVertices = jettaggingutilities::vertexClustering(collision.template mcCollision_as(), analysisJet, allTracks, MCParticles, origParticles, trkLabels, true, vtxRes, trackPtMin); + int nVertices = jettaggingutilities::vertexClustering(collision.template mcCollision_as(), analysisJet, allTracks, MCParticles, origParticles, trkLabels, true, vtxRes, trackPtMin); analyzeJetTrackInfoForGNN(collision, analysisJet, allTracks, origTracks, indicesTracks, jetFlavor, eventWeight, &trkLabels); registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass(), eventWeight); @@ -828,6 +858,7 @@ struct BJetTreeCreator { if (produceTree) { bjetConstituentsTable(bjetParamsTable.lastIndex() + 1, indicesTracks, indicesSVs); bjetParamsTable(analysisJet.pt(), analysisJet.eta(), analysisJet.phi(), indicesTracks.size(), nVertices, analysisJet.mass(), jetFlavor, analysisJet.r()); + bjetParamsExtraTable(eventWeight); } } } From fade470a438cca2e6ca7ff9645ec7733df86a401 Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Tue, 12 May 2026 16:10:55 +0800 Subject: [PATCH 135/449] [PWGUD] flowCorrelationsUpc: use truegapside producer instead of calculating it in the test (#16189) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 158 +++++++++++++--------------- 1 file changed, 72 insertions(+), 86 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 64bae3adc4c..a7ee9ea3dfb 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -18,6 +18,7 @@ #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/DataModel/UDTruegapsideTables.h" #include "Common/Core/RecoDecay.h" @@ -50,17 +51,17 @@ #include #include -namespace o2::aod -{ -namespace flowcorrupc -{ -DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); -DECLARE_SOA_COLUMN(Truegapside, truegapside, int); -} // namespace flowcorrupc -DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", - flowcorrupc::Multiplicity); -DECLARE_SOA_TABLE(Truegapside, "AOD", "TRUEGAPSIDE", flowcorrupc::Truegapside); -} // namespace o2::aod +// namespace o2::aod +// { +// namespace flowcorrupc +// { +// DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); +// DECLARE_SOA_COLUMN(Truegapside, truegapside, int); +// } // namespace flowcorrupc +// DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", +// flowcorrupc::Multiplicity); +// DECLARE_SOA_TABLE(Truegapside, "AOD", "TRUEGAPSIDE", flowcorrupc::Truegapside); +// } // namespace o2::aod using namespace o2; using namespace o2::framework; @@ -70,57 +71,57 @@ using namespace o2::constants::math; // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; -struct CalcNchUpc { - O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") - O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") - - // Added UPC Cuts - SGSelector sgSelector; - Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; - Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; - Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; - Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; - - // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); - - using UdTracks = soa::Join; - using UdTracksFull = soa::Join; - using UDCollisionsFull = soa::Join; - - Produces multiplicityNch; - Produces truegapside; - - HistogramRegistry registry{"registry"}; - - void init(InitContext&) - { - AxisSpec axisNch = {100, 0, 100}; - AxisSpec axisVrtx = {10, -10, 10}; - // AxisSpec axisgap = {12, -6, 6}; - // std::vector trueGapBins = {-2, -1, 0, 1, 2, 3}; - // AxisSpec axisgap = {trueGapBins, "true gap side"}; - - std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; - AxisSpec axisgap = {binEdges, "true gap side"}; - registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); - - registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); - registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); - registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); - // registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); - } - - void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) - { - multiplicityNch(tracks.size()); - truegapside(sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); - // LOG(info) << "truegapside=" << sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - registry.fill(HIST("Ncharge"), tracks.size()); - registry.fill(HIST("zVtx_all"), collision.posZ()); - } -}; +// struct CalcNchUpc { +// O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") +// O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") +// O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") +// O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") + +// // Added UPC Cuts +// SGSelector sgSelector; +// Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; +// Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; +// Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; +// Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; + +// // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + +// using UdTracks = soa::Join; +// using UdTracksFull = soa::Join; +// using UDCollisionsFull = soa::Join; + +// Produces multiplicityNch; +// Produces truegapside; + +// HistogramRegistry registry{"registry"}; + +// void init(InitContext&) +// { +// AxisSpec axisNch = {100, 0, 100}; +// AxisSpec axisVrtx = {10, -10, 10}; +// // AxisSpec axisgap = {12, -6, 6}; +// // std::vector trueGapBins = {-2, -1, 0, 1, 2, 3}; +// // AxisSpec axisgap = {trueGapBins, "true gap side"}; + +// std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; +// AxisSpec axisgap = {binEdges, "true gap side"}; +// registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); + +// registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); +// registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); +// registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); +// // registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); +// } + +// void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) +// { +// multiplicityNch(tracks.size()); +// truegapside(sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); +// // LOG(info) << "truegapside=" << sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); +// registry.fill(HIST("Ncharge"), tracks.size()); +// registry.fill(HIST("zVtx_all"), collision.posZ()); +// } +// }; struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") @@ -141,9 +142,8 @@ struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgDcaz, bool, false, "choose dcaz") O2_DEFINE_CONFIGURABLE(cfgDcazCut, float, 10.0, "dcaz cut") O2_DEFINE_CONFIGURABLE(cfgMaxTPCChi2NCl, int, 4, "tpcchi2") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancy, bool, true, "Occupancy cut") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 1000, "High cut on TPC occupancy") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 1, "choose one side 0:A; 1:C") + O2_DEFINE_CONFIGURABLE(cfgGapSideMerge, bool, true, "merge A and C side") O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum number of crossed TPC Rows") O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum number of found TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum number of ITS clusters") @@ -184,7 +184,11 @@ struct FlowCorrelationsUpc { // make the filters and cuts. Filter trackFilter = (aod::udtrack::isPVContributor == true); - Filter collisionFilter = ((aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (!cfgCutOccupancy || (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh)) && (aod::flowcorrupc::truegapside == 1 || aod::flowcorrupc::truegapside == 0)); + Filter collisionFilter = (cfgGapSideMerge == true) + ? ((aod::udcollision::gapSide == (uint8_t)0 || aod::udcollision::gapSide == (uint8_t)1) && + (aod::upcservice::truegapside == 0 || aod::upcservice::truegapside == 1)) + : ((aod::udcollision::gapSide == (uint8_t)cfgGapSide) && + (aod::upcservice::truegapside == cfgGapSide)); // Connect to ccdb Service ccdb; @@ -200,7 +204,7 @@ struct FlowCorrelationsUpc { using UdTracks = soa::Filtered>; using UdTracksFull = soa::Filtered>; - using UDCollisionsFull = soa::Filtered>; + using UDCollisionsFull = soa::Filtered>; // Define the outputs OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; @@ -358,21 +362,6 @@ struct FlowCorrelationsUpc { weight_nue = 1. / eff; return true; } - - bool setCurrentParticleWeights(float& weight_nue, float& weight_nua, float pt) - { - float eff = 1.; - if (mEfficiency) - eff = mEfficiency->GetBinContent(mEfficiency->FindBin(pt)); - else - eff = 1.0; - if (eff == 0) - return false; - weight_nue = 1. / eff; - weight_nua = 1.; // Set to 1 as NUA weight is not being used - return true; - } - // fill multiple histograms template void fillYield(TCollision collision, TTracks tracks, float vtxz) // function to fill the yield and etaphi histograms. @@ -430,9 +419,6 @@ struct FlowCorrelationsUpc { // 计算track1的权重 float weff1 = 1., wacc1 = 1.; - if (!setCurrentParticleWeights(weff1, wacc1, pt1)) - continue; - if (system == SameEvent) { registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, independent, pt1, eventWeight * weff1 * wacc1); } @@ -621,7 +607,7 @@ struct FlowCorrelationsUpc { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), + // adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), }; } From 193ab88125d60a3300425807015196157091ec2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Tue, 12 May 2026 12:45:53 +0200 Subject: [PATCH 136/449] [PWGDQ] Extended PromptNonPromptSeparation and fixed pointing angle (#16202) --- PWGDQ/Core/VarManager.cxx | 20 ++++ PWGDQ/Core/VarManager.h | 96 ++++++++++++------- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 19 +++- PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 48 ++++++---- PWGDQ/Tasks/tableReader_withAssoc.cxx | 28 +++++- PWGDQ/Tasks/tableReader_withAssoc_direct.cxx | 20 +++- 6 files changed, 167 insertions(+), 64 deletions(-) diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index fa081babced..c7f9955f949 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -931,6 +931,14 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTrackDCAxy] = "cm"; fgVariableNames[kTrackDCAz] = "DCA_{z}"; fgVariableUnits[kTrackDCAz] = "cm"; + fgVariableNames[kDCAxy1] = "DCA_{xy}"; + fgVariableUnits[kDCAxy1] = "cm"; + fgVariableNames[kDCAz1] = "DCA_{z}"; + fgVariableUnits[kDCAz1] = "cm"; + fgVariableNames[kDCAxy2] = "DCA_{xy}"; + fgVariableUnits[kDCAxy2] = "cm"; + fgVariableNames[kDCAz2] = "DCA_{z}"; + fgVariableUnits[kDCAz2] = "cm"; fgVariableNames[kTPCnSigmaEl] = "n #sigma_{e}^{TPC}"; fgVariableUnits[kTPCnSigmaEl] = ""; fgVariableNames[kTPCnSigmaEl_Corr] = "n #sigma_{e}^{TPC} Corr."; @@ -943,6 +951,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTPCnSigmaPi_Corr] = ""; fgVariableNames[kTPCnSigmaKa] = "n #sigma_{K}^{TPC}"; fgVariableUnits[kTPCnSigmaKa] = ""; + fgVariableNames[kTPCnSigmaEl1] = "n #sigma_{el}^{TPC}"; + fgVariableUnits[kTPCnSigmaEl1] = ""; + fgVariableNames[kTPCnSigmaEl2] = "n #sigma_{el}^{TPC}"; + fgVariableUnits[kTPCnSigmaEl2] = ""; fgVariableNames[kTPCnSigmaKa_leg1] = "n #sigma_{K}^{TPC}"; fgVariableUnits[kTPCnSigmaKa_leg1] = ""; fgVariableNames[kTPCnSigmaKa_Corr] = "n #sigma_{K}^{TPC} Corr."; @@ -2131,12 +2143,20 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kEta1"] = kEta1; fgVarNamesMap["kPhi1"] = kPhi1; fgVarNamesMap["kCharge1"] = kCharge1; + fgVarNamesMap["kDCAxy1"] = kDCAxy1; + fgVarNamesMap["kDCAz1"] = kDCAz1; + fgVarNamesMap["kITSclusterMap1"] = kITSclusterMap1; + fgVarNamesMap["kTPCnSigmaEl1"] = kTPCnSigmaEl1; fgVarNamesMap["kPin_leg1"] = kPin_leg1; fgVarNamesMap["kTPCnSigmaKa_leg1"] = kTPCnSigmaKa_leg1; fgVarNamesMap["kPt2"] = kPt2; fgVarNamesMap["kEta2"] = kEta2; fgVarNamesMap["kPhi2"] = kPhi2; fgVarNamesMap["kCharge2"] = kCharge2; + fgVarNamesMap["kDCAxy2"] = kDCAxy2; + fgVarNamesMap["kDCAz2"] = kDCAz2; + fgVarNamesMap["kITSclusterMap2"] = kITSclusterMap2; + fgVarNamesMap["kTPCnSigmaEl2"] = kTPCnSigmaEl2; fgVarNamesMap["kPin"] = kPin; fgVarNamesMap["kSignedPin"] = kSignedPin; fgVarNamesMap["kTOFExpMom"] = kTOFExpMom; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 37e0523cd91..31dad1859b3 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -532,12 +532,20 @@ class VarManager : public TObject kEta1, kPhi1, kCharge1, + kDCAxy1, + kDCAz1, + kITSclusterMap1, + kTPCnSigmaEl1, kPin_leg1, kTPCnSigmaKa_leg1, kPt2, kEta2, kPhi2, kCharge2, + kDCAxy2, + kDCAz2, + kITSclusterMap2, + kTPCnSigmaEl2, // Barrel track variables kPin, @@ -3690,37 +3698,55 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) } } - if constexpr ((pairType == kDecayToEE) && ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { + if constexpr ((pairType == kDecayToEE)) { + if constexpr ((fillMap & ReducedTrackBarrel) > 0) { + values[kITSclusterMap1] = t1.itsClusterMap(); + values[kITSclusterMap2] = t2.itsClusterMap(); + } - if (fgUsedVars[kQuadDCAabsXY] || fgUsedVars[kQuadDCAsigXY] || fgUsedVars[kQuadDCAabsZ] || fgUsedVars[kQuadDCAsigZ] || fgUsedVars[kQuadDCAsigXYZ] || fgUsedVars[kSignQuadDCAsigXY]) { - // Quantities based on the barrel tables + if constexpr ((fillMap & ReducedTrackBarrelPID) > 0) { + values[kTPCnSigmaEl1] = t1.tpcNSigmaEl(); + values[kTPCnSigmaEl2] = t2.tpcNSigmaEl(); + } + + if constexpr (((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { double dca1XY = t1.dcaXY(); double dca2XY = t2.dcaXY(); double dca1Z = t1.dcaZ(); double dca2Z = t2.dcaZ(); - double dca1sigXY = dca1XY / std::sqrt(t1.cYY()); - double dca2sigXY = dca2XY / std::sqrt(t2.cYY()); - double dca1sigZ = dca1Z / std::sqrt(t1.cZZ()); - double dca2sigZ = dca2Z / std::sqrt(t2.cZZ()); - - values[kQuadDCAabsXY] = std::sqrt((dca1XY * dca1XY + dca2XY * dca2XY) / 2); - values[kQuadDCAsigXY] = std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); - values[kQuadDCAabsZ] = std::sqrt((dca1Z * dca1Z + dca2Z * dca2Z) / 2); - values[kQuadDCAsigZ] = std::sqrt((dca1sigZ * dca1sigZ + dca2sigZ * dca2sigZ) / 2); - values[kSignQuadDCAsigXY] = t1.sign() * t2.sign() * TMath::Sign(1., dca1sigXY) * TMath::Sign(1., dca2sigXY) * std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); - double det1 = t1.cYY() * t1.cZZ() - t1.cZY() * t1.cZY(); - double det2 = t2.cYY() * t2.cZZ() - t2.cZY() * t2.cZY(); - if ((det1 < 0) || (det2 < 0)) { - values[kQuadDCAsigXYZ] = -999; - } else { - double chi2t1 = (dca1XY * dca1XY * t1.cZZ() + dca1Z * dca1Z * t1.cYY() - 2. * dca1XY * dca1Z * t1.cZY()) / det1; - double chi2t2 = (dca2XY * dca2XY * t2.cZZ() + dca2Z * dca2Z * t2.cYY() - 2. * dca2XY * dca2Z * t2.cZY()) / det2; + values[kDCAxy1] = dca1XY; + values[kDCAz1] = dca1Z; + values[kDCAxy2] = dca2XY; + values[kDCAz2] = dca2Z; + + if (fgUsedVars[kQuadDCAabsXY] || fgUsedVars[kQuadDCAsigXY] || fgUsedVars[kQuadDCAabsZ] || fgUsedVars[kQuadDCAsigZ] || fgUsedVars[kQuadDCAsigXYZ] || fgUsedVars[kSignQuadDCAsigXY]) { + // Quantities based on the barrel tables + + double dca1sigXY = dca1XY / std::sqrt(t1.cYY()); + double dca2sigXY = dca2XY / std::sqrt(t2.cYY()); + double dca1sigZ = dca1Z / std::sqrt(t1.cZZ()); + double dca2sigZ = dca2Z / std::sqrt(t2.cZZ()); + + values[kQuadDCAabsXY] = std::sqrt((dca1XY * dca1XY + dca2XY * dca2XY) / 2); + values[kQuadDCAsigXY] = std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + values[kQuadDCAabsZ] = std::sqrt((dca1Z * dca1Z + dca2Z * dca2Z) / 2); + values[kQuadDCAsigZ] = std::sqrt((dca1sigZ * dca1sigZ + dca2sigZ * dca2sigZ) / 2); + values[kSignQuadDCAsigXY] = t1.sign() * t2.sign() * TMath::Sign(1., dca1sigXY) * TMath::Sign(1., dca2sigXY) * std::sqrt((dca1sigXY * dca1sigXY + dca2sigXY * dca2sigXY) / 2); + + double det1 = t1.cYY() * t1.cZZ() - t1.cZY() * t1.cZY(); + double det2 = t2.cYY() * t2.cZZ() - t2.cZY() * t2.cZY(); + if ((det1 < 0) || (det2 < 0)) { + values[kQuadDCAsigXYZ] = -999; + } else { + double chi2t1 = (dca1XY * dca1XY * t1.cZZ() + dca1Z * dca1Z * t1.cYY() - 2. * dca1XY * dca1Z * t1.cZY()) / det1; + double chi2t2 = (dca2XY * dca2XY * t2.cZZ() + dca2Z * dca2Z * t2.cYY() - 2. * dca2XY * dca2Z * t2.cZY()) / det2; - double dca1sigXYZ = std::sqrt(std::abs(chi2t1) / 2.); - double dca2sigXYZ = std::sqrt(std::abs(chi2t2) / 2.); + double dca1sigXYZ = std::sqrt(std::abs(chi2t1) / 2.); + double dca2sigXYZ = std::sqrt(std::abs(chi2t2) / 2.); - values[kQuadDCAsigXYZ] = std::sqrt((dca1sigXYZ * dca1sigXYZ + dca2sigXYZ * dca2sigXYZ) / 2); + values[kQuadDCAsigXYZ] = std::sqrt((dca1sigXYZ * dca1sigXYZ + dca2sigXYZ * dca2sigXYZ) / 2); + } } } } @@ -4577,9 +4603,9 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, values[kVertexingTauzErr] = values[kVertexingLzErr] * v12.M() / (TMath::Abs(v12.Pz()) * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v12.M() / (v12.Pt() * o2::constants::physics::LightSpeedCm2NS); - values[kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v12.Px() + - (collision.posY() - secondaryVertex[1]) * v12.Py() + - (collision.posZ() - secondaryVertex[2]) * v12.Pz()) / + values[kCosPointingAngle] = ((secondaryVertex[0] - collision.posX()) * v12.Px() + + (secondaryVertex[1] - collision.posY()) * v12.Py() + + (secondaryVertex[2] - collision.posZ()) * v12.Pz()) / (v12.P() * values[VarManager::kVertexingLxyz]); // Decay length defined as in Run 2 values[kVertexingLzProjected] = ((secondaryVertex[2] - collision.posZ()) * v12.Pz()) / TMath::Sqrt(v12.Pz() * v12.Pz()); @@ -4995,9 +5021,9 @@ void VarManager::FillTripletVertexing(C const& collision, T const& t1, T const& values[kVertexingTauzErr] = values[kVertexingLzErr] * v123.M() / (TMath::Abs(v123.Pz()) * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v123.M() / (v123.Pt() * o2::constants::physics::LightSpeedCm2NS); - values[kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v123.Px() + - (collision.posY() - secondaryVertex[1]) * v123.Py() + - (collision.posZ() - secondaryVertex[2]) * v123.Pz()) / + values[kCosPointingAngle] = ((secondaryVertex[0] - collision.posX()) * v123.Px() + + (secondaryVertex[1] - collision.posY()) * v123.Py() + + (secondaryVertex[2] - collision.posZ()) * v123.Pz()) / (v123.P() * values[VarManager::kVertexingLxyz]); // run 2 definitions: Decay length projected onto the momentum vector of the candidate values[kVertexingLzProjected] = (secondaryVertex[2] - collision.posZ()) * v123.Pz(); @@ -5256,9 +5282,9 @@ void VarManager::FillDileptonTrackVertexing(C const& collision, T1 const& lepton values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v123.M() / (v123.Pt() * o2::constants::physics::LightSpeedCm2NS); if (fgUsedVars[kCosPointingAngle] && fgUsedVars[kVertexingLxyz]) { - values[VarManager::kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v123.Px() + - (collision.posY() - secondaryVertex[1]) * v123.Py() + - (collision.posZ() - secondaryVertex[2]) * v123.Pz()) / + values[VarManager::kCosPointingAngle] = ((secondaryVertex[0] - collision.posX()) * v123.Px() + + (secondaryVertex[1] - collision.posY()) * v123.Py() + + (secondaryVertex[2] - collision.posZ()) * v123.Pz()) / (v123.P() * values[VarManager::kVertexingLxyz]); } // run 2 definitions: Lxy projected onto the momentum vector of the candidate @@ -6283,9 +6309,9 @@ void VarManager::FillDileptonTrackTrackVertexing(C const& collision, T1 const& l values[kVertexingTauzErr] = values[kVertexingLzErr] * v1234.M() / (TMath::Abs(v1234.Pz()) * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v1234.M() / (v1234.Pt() * o2::constants::physics::LightSpeedCm2NS); - values[kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v1234.Px() + - (collision.posY() - secondaryVertex[1]) * v1234.Py() + - (collision.posZ() - secondaryVertex[2]) * v1234.Pz()) / + values[kCosPointingAngle] = ((secondaryVertex[0] - collision.posX()) * v1234.Px() + + (secondaryVertex[1] - collision.posY()) * v1234.Py() + + (secondaryVertex[2] - collision.posZ()) * v1234.Pz()) / (v1234.P() * values[VarManager::kVertexingLxyz]); // // run 2 definitions: Decay length projected onto the momentum vector of the candidate values[kVertexingLzProjected] = (secondaryVertex[2] - collision.posZ()) * v1234.Pz(); diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index df76d33e777..8c33763ce96 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -170,6 +170,14 @@ DECLARE_SOA_COLUMN(Ptee, ptee, float); DECLARE_SOA_COLUMN(Lxyee, lxyee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); DECLARE_SOA_COLUMN(Lzee, lzee, float); +DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); +DECLARE_SOA_COLUMN(Vx, vx, float); +DECLARE_SOA_COLUMN(Vy, vy, float); +DECLARE_SOA_COLUMN(Vz, vz, float); +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); @@ -218,7 +226,11 @@ DECLARE_SOA_TABLE(JPsiMuonCandidates, "AOD", "DQJPSIMUONA", dqanalysisflags::MassDileptonCandidate, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Phiassoc, dqanalysisflags::Ptleg1, dqanalysisflags::Etaleg1, dqanalysisflags::Phileg1, dqanalysisflags::Ptleg2, dqanalysisflags::Etaleg2, dqanalysisflags::Phileg2, dqanalysisflags::McFlag); -DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", + dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, + dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, + dqanalysisflags::Vx, dqanalysisflags::Vy, dqanalysisflags::Vz, dqanalysisflags::DcaXY1, dqanalysisflags::DcaZ1, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::DcaXY2, dqanalysisflags::DcaZ2, dqanalysisflags::ITSClusterMapleg2, dqanalysisflags::TPCnsigmaElleg2, + dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); DECLARE_SOA_TABLE(OniaMCTruth, "AOD", "MCTRUTHONIA", dqanalysisflags::OniaPt, dqanalysisflags::OniaEta, dqanalysisflags::OniaY, dqanalysisflags::OniaPhi, dqanalysisflags::OniaVz, dqanalysisflags::OniaVtxZ, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); } // namespace o2::aod @@ -2085,7 +2097,10 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); // reconstructed, unmatched for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals if (mcDecision & (static_cast(1) << isig)) { - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], + VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], + VarManager::fgValues[VarManager::kVtxX], VarManager::fgValues[VarManager::kVtxY], VarManager::fgValues[VarManager::kVtxZ], VarManager::fgValues[VarManager::kDCAxy1], VarManager::fgValues[VarManager::kDCAz1], VarManager::fgValues[VarManager::kITSclusterMap1], VarManager::fgValues[VarManager::kTPCnSigmaEl1], VarManager::fgValues[VarManager::kDCAxy2], VarManager::fgValues[VarManager::kDCAz2], VarManager::fgValues[VarManager::kITSclusterMap2], VarManager::fgValues[VarManager::kTPCnSigmaEl2], + isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal if (useMiniTree.fConfigMiniTree) { if constexpr (TPairType == VarManager::kDecayToMuMu) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index bebfe8ac6a0..3113e45f191 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -181,6 +181,13 @@ DECLARE_SOA_COLUMN(Lxyee, lxyee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); DECLARE_SOA_COLUMN(Lzee, lzee, float); DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); +DECLARE_SOA_COLUMN(Vx, vx, float); +DECLARE_SOA_COLUMN(Vy, vy, float); +DECLARE_SOA_COLUMN(Vz, vz, float); +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); @@ -201,7 +208,11 @@ DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelec DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); //! joinable to ReducedBarrelTracks DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedTracksAssoc -DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", + dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, + dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, + dqanalysisflags::Vx, dqanalysisflags::Vy, dqanalysisflags::Vz, dqanalysisflags::DcaXY1, dqanalysisflags::DcaZ1, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::DcaXY2, dqanalysisflags::DcaZ2, dqanalysisflags::ITSClusterMapleg2, dqanalysisflags::TPCnsigmaElleg2, + dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); DECLARE_SOA_TABLE(OniaMCTruth, "AOD", "MCTRUTHONIA", dqanalysisflags::OniaPt, dqanalysisflags::OniaEta, dqanalysisflags::OniaY, dqanalysisflags::OniaPhi, dqanalysisflags::OniaVz, dqanalysisflags::OniaVtxZ, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); /*DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuonSelected); //! joinable to ReducedMuonsAssoc @@ -1894,7 +1905,10 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); // reconstructed, unmatched for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals if (mcDecision & (static_cast(1) << isig)) { - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], + VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], + VarManager::fgValues[VarManager::kVtxX], VarManager::fgValues[VarManager::kVtxY], VarManager::fgValues[VarManager::kVtxZ], VarManager::fgValues[VarManager::kDCAxy1], VarManager::fgValues[VarManager::kDCAz1], VarManager::fgValues[VarManager::kITSclusterMap1], VarManager::fgValues[VarManager::kTPCnSigmaEl1], VarManager::fgValues[VarManager::kDCAxy2], VarManager::fgValues[VarManager::kDCAz2], VarManager::fgValues[VarManager::kITSclusterMap2], VarManager::fgValues[VarManager::kTPCnSigmaEl2], + isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal /*if (fConfigOptions.fConfigMiniTree) { if constexpr (TPairType == VarManager::kDecayToMuMu) { @@ -2382,9 +2396,9 @@ struct AnalysisDileptonTrack { string cfgTrackSelection_TrackCuts; if (isBarrel /*|| isBarrelAsymmetric*/) { getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", cfgTrackSelection_TrackCuts, false); - } /* else { - getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCuts", cfgTrackSelection_TrackCuts, false); - }*/ + } // else { + // getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCuts", cfgTrackSelection_TrackCuts, false); + //} TObjArray* cfgTrackSelection_objArrayTrackCuts = nullptr; if (!cfgTrackSelection_TrackCuts.empty()) { cfgTrackSelection_objArrayTrackCuts = TString(cfgTrackSelection_TrackCuts).Tokenize(","); @@ -2392,9 +2406,9 @@ struct AnalysisDileptonTrack { // get also the list of cuts specified via the JSON parameters if (isBarrel /*|| isBarrelAsymmetric*/) { getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", cfgTrackSelection_TrackCuts, false); - } /*else { - getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCutsJSON", cfgTrackSelection_TrackCuts, false); - }*/ + } // else { + // getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCutsJSON", cfgTrackSelection_TrackCuts, false); + //} if (!cfgTrackSelection_TrackCuts.empty()) { if (cfgTrackSelection_objArrayTrackCuts == nullptr) { cfgTrackSelection_objArrayTrackCuts = new TObjArray(); @@ -2446,15 +2460,15 @@ struct AnalysisDileptonTrack { if (isBarrel) { getTaskOptionValue(context, "analysis-same-event-pairing", "cfgTrackCuts", cfgPairing_TrackCuts, false); getTaskOptionValue(context, "analysis-same-event-pairing", "cfgPairCuts", cfgPairing_PairCuts, false); - } /* else if (isMuon) { - getTaskOptionValue(context, "analysis-same-event-pairing", "cfgMuonCuts", cfgPairing_TrackCuts, false); - getTaskOptionValue(context, "analysis-same-event-pairing", "cfgPairCuts", cfgPairing_PairCuts, false); - }*/ - /* else if (isBarrelAsymmetric) { - getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgLegCuts", cfgPairing_TrackCuts, false); - getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgPairCuts", cfgPairing_PairCuts, false); - getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgCommonTrackCuts", cfgPairing_CommonTrackCuts, false); - }*/ + } // else if (isMuon) { + // getTaskOptionValue(context, "analysis-same-event-pairing", "cfgMuonCuts", cfgPairing_TrackCuts, false); + // getTaskOptionValue(context, "analysis-same-event-pairing", "cfgPairCuts", cfgPairing_PairCuts, false); + //} + // else if (isBarrelAsymmetric) { + // getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgLegCuts", cfgPairing_TrackCuts, false); + // getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgPairCuts", cfgPairing_PairCuts, false); + // getTaskOptionValue(context, "analysis-asymmetric-pairing", "cfgCommonTrackCuts", cfgPairing_CommonTrackCuts, false); + //} if (cfgPairing_TrackCuts.empty()) { LOG(fatal) << "There are no dilepton cuts specified in the upstream in the same-event-pairing or asymmetric-pairing"; } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index d5bcfc56797..c23ad65ac0e 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -157,12 +157,23 @@ DECLARE_SOA_COLUMN(TPCChi2leg1, tpcChi2leg1, float); DECLARE_SOA_COLUMN(TPCChi2leg2, tpcChi2leg2, float); DECLARE_SOA_BITMAP_COLUMN(IsJpsiFromBSelected, isJpsiFromBSelected, 32); // Candidate columns for prompt-non-prompt JPsi separation -DECLARE_SOA_COLUMN(Massee, massJPsi2ee, float); -DECLARE_SOA_COLUMN(Ptee, ptJPsi2ee, float); +DECLARE_SOA_COLUMN(Massee, massee, float); +DECLARE_SOA_COLUMN(Etaee, etaee, float); +DECLARE_SOA_COLUMN(Rapee, rapee, float); +DECLARE_SOA_COLUMN(Phiee, phiee, float); +DECLARE_SOA_COLUMN(Ptee, ptee, float); DECLARE_SOA_COLUMN(Lxyee, lxyJPsi2ee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyJPsi2eePoleMass, float); DECLARE_SOA_COLUMN(LRecalxyeePoleMass, lRecalxyeePoleMass, float); -DECLARE_SOA_COLUMN(Lzee, lzJPsi2ee, float); +DECLARE_SOA_COLUMN(Lzee, lzee, float); +DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); +DECLARE_SOA_COLUMN(Vx, vx, float); +DECLARE_SOA_COLUMN(Vy, vy, float); +DECLARE_SOA_COLUMN(Vz, vz, float); +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); DECLARE_SOA_COLUMN(AmbiguousInBunchPairs, AmbiguousJpsiPairsInBunch, bool); DECLARE_SOA_COLUMN(AmbiguousOutOfBunchPairs, AmbiguousJpsiPairsOutOfBunch, bool); DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); @@ -201,7 +212,11 @@ DECLARE_SOA_TABLE(JPsiMuonCandidates, "AOD", "DQJPSIMUONA", dqanalysisflags::DeltaEta, dqanalysisflags::DeltaPhi, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Phiassoc, dqanalysisflags::Ptleg1, dqanalysisflags::Etaleg1, dqanalysisflags::Phileg1, dqanalysisflags::Ptleg2, dqanalysisflags::Etaleg2, dqanalysisflags::Phileg2); -DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LRecalxyeePoleMass, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", + dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, + dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, + dqanalysisflags::Vx, dqanalysisflags::Vy, dqanalysisflags::Vz, dqanalysisflags::DcaXY1, dqanalysisflags::DcaZ1, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::DcaXY2, dqanalysisflags::DcaZ2, dqanalysisflags::ITSClusterMapleg2, dqanalysisflags::TPCnsigmaElleg2, + dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); } // namespace o2::aod // Declarations of various short names @@ -2060,7 +2075,10 @@ struct AnalysisSameEventPairing { } } if (sign1 * sign2 < 0) { - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], + VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], + VarManager::fgValues[VarManager::kVtxX], VarManager::fgValues[VarManager::kVtxY], VarManager::fgValues[VarManager::kVtxZ], VarManager::fgValues[VarManager::kDCAxy1], VarManager::fgValues[VarManager::kDCAz1], VarManager::fgValues[VarManager::kITSclusterMap1], VarManager::fgValues[VarManager::kTPCnSigmaEl1], VarManager::fgValues[VarManager::kDCAxy2], VarManager::fgValues[VarManager::kDCAz2], VarManager::fgValues[VarManager::kITSclusterMap2], VarManager::fgValues[VarManager::kTPCnSigmaEl2], + isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); if constexpr (TPairType == VarManager::kDecayToMuMu) { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); if (fConfigAmbiguousMuonHistograms) { diff --git a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx index c8002425a33..39814f73fa8 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx @@ -168,6 +168,13 @@ DECLARE_SOA_COLUMN(Lxyee, lxyee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); DECLARE_SOA_COLUMN(Lzee, lzee, float); DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); +DECLARE_SOA_COLUMN(Vx, vx, float); +DECLARE_SOA_COLUMN(Vy, vy, float); +DECLARE_SOA_COLUMN(Vz, vz, float); +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); @@ -189,10 +196,10 @@ DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuon DECLARE_SOA_TABLE(MuonAmbiguities, "AOD", "DQMUONAMB", dqanalysisflags::MuonAmbiguityInBunch, dqanalysisflags::MuonAmbiguityOutOfBunch); //! joinable to FwdTracks DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", - dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, - dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, - dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, - dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); + dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, + dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, + dqanalysisflags::Vx, dqanalysisflags::Vy, dqanalysisflags::Vz, dqanalysisflags::DcaXY1, dqanalysisflags::DcaZ1, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::DcaXY2, dqanalysisflags::DcaZ2, dqanalysisflags::ITSClusterMapleg2, dqanalysisflags::TPCnsigmaElleg2, + dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::RunNumber, dqanalysisflags::EventIdx, dqanalysisflags::EventTimestamp, @@ -1746,7 +1753,10 @@ struct AnalysisSameEventPairing { if (twoTrackFilter & (static_cast(1) << icut)) { if (sign1 * sign2 < 0) { // opposite sign pairs fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], + VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], + VarManager::fgValues[VarManager::kVtxX], VarManager::fgValues[VarManager::kVtxY], VarManager::fgValues[VarManager::kVtxZ], VarManager::fgValues[VarManager::kDCAxy1], VarManager::fgValues[VarManager::kDCAz1], VarManager::fgValues[VarManager::kITSclusterMap1], VarManager::fgValues[VarManager::kTPCnSigmaEl1], VarManager::fgValues[VarManager::kDCAxy2], VarManager::fgValues[VarManager::kDCAz2], VarManager::fgValues[VarManager::kITSclusterMap2], VarManager::fgValues[VarManager::kTPCnSigmaEl2], + isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); if (fConfigOptions.fConfigQA) { if (isAmbiInBunch) { fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); From ab3937d1b44ea837587cc370187c35eb02750064 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Tue, 12 May 2026 13:41:32 +0200 Subject: [PATCH 137/449] [PWGDQ] add efficiency weight method (#16203) --- PWGDQ/Core/VarManager.cxx | 57 +++++++++++++++++++++++++++ PWGDQ/Core/VarManager.h | 14 +++++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 12 ++++++ 3 files changed, 83 insertions(+) diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index c7f9955f949..1d5bd30e476 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -74,6 +74,8 @@ std::map VarManager::fgCalibs; bool VarManager::fgRunTPCPostCalibration[4] = {false, false, false, false}; int VarManager::fgCalibrationType = 0; // 0 - no calibration, 1 - calibration vs (TPCncls,pIN,eta) typically for pp, 2 - calibration vs (eta,nPV,nLong,tLong) typically for PbPb bool VarManager::fgUseInterpolatedCalibration = true; // use interpolated calibration histograms (default: true) +int VarManager::fgEfficiencyType = 0; // type of efficiency to be applied, default is no efficiency +TObject* VarManager::fgEfficiencyHist = nullptr; // histogram for efficiency //__________________________________________________________________ VarManager::VarManager() : TObject() @@ -380,6 +382,58 @@ double VarManager::ComputePIDcalibration(int species, double nSigmaValue) } } +//__________________________________________________________________ +void VarManager::SetEfficiencyObject(int efficiencyType, TObject* obj) +{ + // check the type of the efficiency object and set it accordingly + if (efficiencyType >= kNEfficiencyTypes || efficiencyType < 0) { + LOG(warning) << "SetEfficiencyObject: unknown efficiency type " << efficiencyType; + return; + } + + // set the efficiency type + fgEfficiencyType = efficiencyType; + // set the efficiency object + fgEfficiencyHist = obj; +} + +void VarManager::FillEfficiency(float* values) +{ + // depending on the efficiency type, we use different types of efficiency histograms and different variables to get the efficiency value + if (!values) { + values = fgValues; + } + + if (fgEfficiencyType == kNone) { + values[kPairEfficiency] = 1.0; // if no efficiency is to be applied, set the efficiency value to 1 + values[kPairWeight] = 1.0; // set the weight to 1 + } else if (fgEfficiencyType == kPairPtCentFT0cCosThetaStarFT0c) { + if (!fgEfficiencyHist) { + LOG(fatal) << "efficiency histogram not set"; + return; + } + TH3F* efficiencyHist = reinterpret_cast(fgEfficiencyHist); + // Get the bin indices for the efficiency histogram + int binPt = efficiencyHist->GetXaxis()->FindBin(values[kPairPt]); + binPt = (binPt == 0 ? 1 : binPt); + binPt = (binPt > efficiencyHist->GetXaxis()->GetNbins() ? efficiencyHist->GetXaxis()->GetNbins() : binPt); + int binCent = efficiencyHist->GetYaxis()->FindBin(values[kCentFT0C]); + binCent = (binCent == 0 ? 1 : binCent); + binCent = (binCent > efficiencyHist->GetYaxis()->GetNbins() ? efficiencyHist->GetYaxis()->GetNbins() : binCent); + int binCosThetaStarFT0c = efficiencyHist->GetZaxis()->FindBin(values[kCosThetaStarFT0C]); + binCosThetaStarFT0c = (binCosThetaStarFT0c == 0 ? 1 : binCosThetaStarFT0c); + binCosThetaStarFT0c = (binCosThetaStarFT0c > efficiencyHist->GetZaxis()->GetNbins() ? efficiencyHist->GetZaxis()->GetNbins() : binCosThetaStarFT0c); + + // get the efficiency value from the histogram + values[kPairEfficiency] = efficiencyHist->GetBinContent(binPt, binCent, binCosThetaStarFT0c); + values[kPairWeight] = 1.0 / (values[kPairEfficiency] > 0 ? values[kPairEfficiency] : 1.0); // set the weight as the inverse of the efficiency, but avoid division by zero + } else { + LOG(warning) << "FillEfficiency: unknown efficiency type " << fgEfficiencyType << ", using default efficiency = 1"; + values[kPairEfficiency] = 1; + values[kPairWeight] = 1; + } +} + //__________________________________________________________________ std::tuple VarManager::BimodalityCoefficientUnbinned(const std::vector& data) { @@ -1547,6 +1601,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCos2ThetaStarRandom] = ""; fgVariableNames[kMCCosThetaStar] = "cos#it{#theta}^{*}_{MC}"; fgVariableUnits[kMCCosThetaStar] = ""; + fgVariableNames[kPairWeight] = "weight"; + fgVariableUnits[kPairWeight] = ""; fgVariableNames[kCosPhiVP] = "cos#it{#varphi}_{VP}"; fgVariableUnits[kCosPhiVP] = ""; fgVariableNames[kPhiVP] = "#varphi_{VP} - #Psi_{2}"; @@ -2384,6 +2440,7 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kCosThetaStarRandom"] = kCosThetaStarRandom; fgVarNamesMap["kCos2ThetaStarRandom"] = kCos2ThetaStarRandom; fgVarNamesMap["kMCCosThetaStar"] = kMCCosThetaStar; + fgVarNamesMap["kPairWeight"] = kPairWeight; fgVarNamesMap["kCosPhiVP"] = kCosPhiVP; fgVarNamesMap["kPhiVP"] = kPhiVP; fgVarNamesMap["kDeltaPhiPair2"] = kDeltaPhiPair2; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 31dad1859b3..91759494f18 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -936,6 +936,8 @@ class VarManager : public TObject kS12, kS13, kS23, + kPairEfficiency, + kPairWeight, kNPairVariables, // Candidate-track correlation variables @@ -1121,6 +1123,13 @@ class VarManager : public TObject kNCalibObjects }; + enum EfficiencyType { + kNone = 0, + kPairPtCentFT0cCosThetaStarFT0c, + // Add more efficiency types as needed + kNEfficiencyTypes + }; + enum DileptonCharmHadronTypes { kJPsi = 0, kD0ToPiK, @@ -1472,6 +1481,8 @@ class VarManager : public TObject } static double ComputePIDcalibration(int species, double nSigmaValue); + static void SetEfficiencyObject(int type, TObject* obj); + static void FillEfficiency(float* values = nullptr); static TObject* GetCalibrationObject(CalibObjects calib) { auto obj = fgCalibs.find(calib); @@ -1555,6 +1566,9 @@ class VarManager : public TObject static int fgCalibrationType; // 0 - no calibration, 1 - calibration vs (TPCncls,pIN,eta) typically for pp, 2 - calibration vs (eta,nPV,nLong,tLong) typically for PbPb static bool fgUseInterpolatedCalibration; // use interpolated calibration histograms (default: true) + static int fgEfficiencyType; // type of efficiency correction to apply + static TObject* fgEfficiencyHist; // histogram for efficiency correction + VarManager& operator=(const VarManager& c); VarManager(const VarManager& c); diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index c23ad65ac0e..d0f0a223ea6 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1317,6 +1317,7 @@ struct AnalysisSameEventPairing { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable GrpLhcIfPath{"grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; + Configurable efficiencyPath{"effHistPath", "Users/z/zhxiong/efficiency", "Path on the CCDB for the efficiency histograms"}; } fConfigCCDB; struct : ConfigurableGroup { @@ -1333,6 +1334,8 @@ struct AnalysisSameEventPairing { Configurable centerMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; Configurable propTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; Configurable useRemoteCollisionInfo{"cfgUseRemoteCollisionInfo", false, "Use remote collision information from CCDB"}; + Configurable useEfficiencyWeighting{"cfgUseEfficiencyWeighting", false, "Apply efficiency weighting to the pairs from CCDB"}; + Configurable efficiencyType{"cfgEfficiencyType", 0, "Type of efficiency to apply from CCDB: 0 no efficiency, 1 pt-cent-costhetastar"}; } fConfigOptions; struct : ConfigurableGroup { Configurable applyBDT{"applyBDT", false, "Flag to apply ML selections"}; @@ -1746,6 +1749,11 @@ struct AnalysisSameEventPairing { o2::parameters::GRPLHCIFData* grpo = fCCDB->getForTimeStamp(fConfigCCDB.GrpLhcIfPath, timestamp); VarManager::SetCollisionSystem(grpo); } + + if (fConfigOptions.useEfficiencyWeighting) { + auto effList = fCCDB->getForTimeStamp(fConfigCCDB.efficiencyPath.value, timestamp); + VarManager::SetEfficiencyObject(fConfigOptions.efficiencyType.value, effList->FindObject("efficiency")); + } } // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) @@ -1868,6 +1876,10 @@ struct AnalysisSameEventPairing { VarManager::FillPairVn(t1, t2); } + if (fConfigOptions.useEfficiencyWeighting) { + VarManager::FillEfficiency(); + } + dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), twoTrackFilter, 0); From 95467c2d41e2c6955200a007326be0015c76798b Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Tue, 12 May 2026 13:42:13 +0200 Subject: [PATCH 138/449] [PWGEM,PWGEM-36] PM/taskFlowReso: Add auto correlation histograms (#16213) --- PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx index fc14a7a7fe0..c14add8b083 100644 --- a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx @@ -174,6 +174,12 @@ struct TaskFlowReso { registry.add("spReso/hSpResoFV0aTPCpos", "hSpResoFV0aTPCpos; centrality; Q_{FV0a} #bullet Q_{TPCpos}", HistType::kTProfile, {thnAxisCent}); registry.add("spReso/hSpResoFV0aTPCneg", "hSpResoFV0aTPCneg; centrality; Q_{FV0a} #bullet Q_{TPCneg}", HistType::kTProfile, {thnAxisCent}); registry.add("spReso/hSpResoFV0aTPCtot", "hSpResoFV0aTPCtot; centrality; Q_{FV0a} #bullet Q_{TPCtot}", HistType::kTProfile, {thnAxisCent}); + + // auto correlations + registry.add("spReso/hSpResoFT0cFT0c", "hSpResoFT0cFT0c; centrality; Q_{FT0c} #bullet Q_{FT0c}", HistType::kTProfile, {thnAxisCent}); + registry.add("spReso/hSpResoFT0aFT0a", "hSpResoFT0aFT0a; centrality; Q_{FT0a} #bullet Q_{FT0a}", HistType::kTProfile, {thnAxisCent}); + registry.add("spReso/hSpResoFT0mFT0m", "hSpResoFT0mFT0m; centrality; Q_{FT0m} #bullet Q_{FT0m}", HistType::kTProfile, {thnAxisCent}); + registry.add("spReso/hSpResoFV0aFV0a", "hSpResoFV0aFV0a; centrality; Q_{FV0a} #bullet Q_{FV0a}", HistType::kTProfile, {thnAxisCent}); } if (saveEpResoHisto.value) { @@ -456,6 +462,11 @@ struct TaskFlowReso { registry.fill(HIST("spReso/hSpResoFV0aTPCpos"), centrality, xQVecFV0a * xQVecBPos + yQVecFV0a * yQVecBPos); registry.fill(HIST("spReso/hSpResoFV0aTPCneg"), centrality, xQVecFV0a * xQVecBNeg + yQVecFV0a * yQVecBNeg); registry.fill(HIST("spReso/hSpResoFV0aTPCtot"), centrality, xQVecFV0a * xQVecBTot + yQVecFV0a * yQVecBTot); + // auto-correlations for forward detectors, this is needed for combining subevents! + registry.fill(HIST("spReso/hSpResoFT0cFT0c"), centrality, xQVecFT0c * xQVecFT0c + yQVecFT0c * yQVecFT0c); + registry.fill(HIST("spReso/hSpResoFT0aFT0a"), centrality, xQVecFT0a * xQVecFT0a + yQVecFT0a * yQVecFT0a); + registry.fill(HIST("spReso/hSpResoFT0mFT0m"), centrality, xQVecFT0m * xQVecFT0m + yQVecFT0m * yQVecFT0m); + registry.fill(HIST("spReso/hSpResoFV0aFV0a"), centrality, xQVecFV0a * xQVecFV0a + yQVecFV0a * yQVecFV0a); } if (saveEpResoHisto) { From ab588277c34e309fbdf388824ea446d48de910eb Mon Sep 17 00:00:00 2001 From: ldellost <47105254+DelloStritto@users.noreply.github.com> Date: Tue, 12 May 2026 14:08:19 +0200 Subject: [PATCH 139/449] [PWGHF] Add more bins for the Lc in pk0s channel (#16214) Co-authored-by: Luigi Dello Stritto --- PWGHF/Core/SelectorCuts.h | 49 +++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 764fd0cc0c6..f48f1158109 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -554,32 +554,42 @@ static const std::vector labelsCutKfVar = {"kfChi2PrimPr", "kfChi2P namespace hf_cuts_lc_to_k0s_p { -static constexpr int NBinsPt = 8; +static constexpr int NBinsPt = 13; static constexpr int NCutVars = 9; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array constexpr double BinsPt[NBinsPt + 1] = { - 1., - 2., - 3., - 4., - 5., - 6., - 8., - 12., - 24.}; + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 7.0, + 8.0, + 10.0, + 12.0, + 16.0, + 24.0, + 36.0}; const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; // default values for the cuts // mLc(GeV) mK0s(GeV) mLambdas(GeV) mGammas(GeV) ptp ptK0sdau ptK0s d0p d0K0 -constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.008, 0.005, 0.1, 0.5, 0.3, 0.6, 0.05, 999999.}, // 1 < pt < 2 +constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.008, 0.005, 0.1, 0.5, 0.3, 0.6, 0.05, 999999.}, // 0 < pt < 1 + {0.4, 0.008, 0.005, 0.1, 0.5, 0.3, 0.6, 0.05, 999999.}, // 1 < pt < 2 {0.4, 0.008, 0.005, 0.1, 0.5, 0.4, 1.3, 0.05, 999999.}, // 2 < pt < 3 {0.4, 0.009, 0.005, 0.1, 0.6, 0.4, 1.3, 0.05, 999999.}, // 3 < pt < 4 - {0.4, 0.011, 0.005, 0.1, 0.6, 0.4, 1.4, 0.05, 999999.}, // 4 < pt < 5 - {0.4, 0.013, 0.005, 0.1, 0.6, 0.4, 1.4, 0.06, 999999.}, // 5 < pt < 6 - {0.4, 0.013, 0.005, 0.1, 0.9, 0.4, 1.6, 0.09, 999999.}, // 6 < pt < 8 - {0.4, 0.016, 0.005, 0.1, 0.9, 0.4, 1.7, 0.10, 999999.}, // 8 < pt < 12 - {0.4, 0.019, 0.005, 0.1, 1.0, 0.4, 1.9, 0.20, 999999.}}; // 12 < pt < 24 + {0.4, 0.009, 0.005, 0.1, 0.6, 0.4, 1.3, 0.05, 999999.}, // 4 < pt < 5 + {0.4, 0.011, 0.005, 0.1, 0.6, 0.4, 1.4, 0.05, 999999.}, // 5 < pt < 6 + {0.4, 0.013, 0.005, 0.1, 0.6, 0.4, 1.4, 0.06, 999999.}, // 6 < pt < 7 + {0.4, 0.013, 0.005, 0.1, 0.6, 0.4, 1.4, 0.06, 999999.}, // 7 < pt < 8 + {0.4, 0.013, 0.005, 0.1, 0.6, 0.4, 1.4, 0.06, 999999.}, // 8 < pt < 10 + {0.4, 0.013, 0.005, 0.1, 0.9, 0.4, 1.6, 0.09, 999999.}, // 10 < pt < 12 + {0.4, 0.016, 0.005, 0.1, 0.9, 0.4, 1.7, 0.10, 999999.}, // 12 < pt < 16 + {0.4, 0.016, 0.005, 0.1, 0.9, 0.4, 1.7, 0.10, 999999.}, // 16 < pt < 24 + {0.4, 0.019, 0.005, 0.1, 1.0, 0.4, 1.9, 0.20, 999999.}}; // 24 < pt < 36 // row labels static const std::vector labelsPt = { @@ -590,7 +600,12 @@ static const std::vector labelsPt = { "pT bin 4", "pT bin 5", "pT bin 6", - "pT bin 7"}; + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12"}; // column labels static const std::vector labelsCutVar = {"mLc", "mK0s", "mLambda", "mGamma", "ptBach", "ptV0Dau", "ptV0", "d0Bach", "d0V0"}; From c8156661fb107e7d497f5e8a1ac67cb3457c8b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Jos=C3=A9?= <52935244+lucasjsilva@users.noreply.github.com> Date: Tue, 12 May 2026 14:18:18 +0200 Subject: [PATCH 140/449] [PWGLF] Corrections for systematic uncertainties (#16212) --- .../Tasks/GlobalEventProperties/studyPnch.cxx | 99 +++++++------------ 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx index 0d56f859b1f..43e1d5dcce9 100644 --- a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx @@ -15,6 +15,8 @@ /// \author Abhi Modak (abhi.modak@cern.ch), Lucas José (lucas.jose.franco.da.silva@cern.ch) /// \since September 10, 2025 +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" @@ -35,7 +37,6 @@ #include #include -#include #include #include @@ -75,7 +76,7 @@ AxisSpec axisEta{40, -2, 2, "#eta", "EtaAxis"}; AxisSpec axisPhi{629, 0, o2::constants::math::TwoPI, "#phi"}; AxisSpec axisCollSel{5, 0.5, 5.5, "#Event", "CollSelAxis"}; auto static constexpr kMinCharge = 3.f; -auto static constexpr kMinPtCut = 0.1f; +auto static constexpr pTminCut = 0.1f; struct StudyPnch { @@ -110,8 +111,8 @@ struct StudyPnch { Configurable isApplyPhiSelection{"isApplyPhiSelection", false, "Select tracks in specific phi range"}; Configurable minPhi{"minPhi", 0.f, "Minimum phi value for track selection"}; Configurable maxPhi{"maxPhi", 6.283185f, "Maximum phi value for track selection"}; - Configurable ispTincrease{"ispTincrease", false, "Varies low pT particles by a conservative amount of +100%"}; - Configurable ispTdecrease{"ispTdecrease", false, "Varies low pT particles by a conservative amount of -50%"}; + Configurable isPtincrease{"isPtincrease", false, "Varies low pT particles by a conservative amount of +100%"}; + Configurable isPtdecrease{"isPtdecrease", false, "Varies low pT particles by a conservative amount of -50%"}; Configurable isApplyStrangenessSysUncert{"isApplyStrangenessSysUncert", false, "Enable the evaluation of systematics due to strange particle contribution"}; void init(InitContext const&) @@ -122,7 +123,6 @@ struct StudyPnch { AxisSpec axisFt0aMult = {ft0aMultHistBin, "ft0a", "FT0AMultAxis"}; AxisSpec axisFt0cMult = {ft0cMultHistBin, "ft0c", "FT0CMultAxis"}; AxisSpec axisPt = {ptHistBin, "pT", "pTAxis"}; - AxisSpec axisCountNumberTracks = {countNumberTracks, "Count", "CountAxis"}; AxisSpec dcaAxis = {binsDCA, "DCA vs PV"}; histos.add("EventHist", "EventHist", kTH1D, {axisEvent}, false); @@ -138,13 +138,6 @@ struct StudyPnch { x->SetBinLabel(6, "INEL > 0"); x->SetBinLabel(7, "|vz| < 10"); - histos.add("SelCollsHist", "SelCollsHist", kTH1D, {axisCollSel}, false); - auto hstat_colls = histos.get(HIST("SelCollsHist")); - auto* xColls = hstat_colls->GetXaxis(); - xColls->SetBinLabel(1, "All collisions"); - xColls->SetBinLabel(2, "Best Collision Selection"); - xColls->SetBinLabel(3, "Has MC Collision Selection"); - if (doprocessData || doprocessCorrelation || doprocessMonteCarlo) { histos.add("PhiVsEtaHist", "PhiVsEtaHist", kTH2F, {axisPhi, axisEta}, false); histos.add("EtaHist", "EtaHist", kTH1D, {axisEta}, false); @@ -169,17 +162,12 @@ struct StudyPnch { histos.add("hMultiplicityMCrec", "hMultiplicityMCrec", kTH1F, {axisMult}, true); histos.add("hMultiplicityMCgen", "hMultiplicityMCgen", kTH1F, {axisMult}, true); histos.add("hResponseMatrix", "hResponseMatrix", kTH2F, {axisMult, axisMult}, true); - histos.add("hCountNTracks", "hCountNTracks", kTH1F, {axisCountNumberTracks}, true); - } - if (ispTincrease || ispTdecrease) { histos.add("hMultiplicityMCgenPtCut", "hMultiplicityMCgenPtCut", kTH1F, {axisMult}, true); histos.add("hResponseMatrixPtCut", "hResponseMatrixPtCut", kTH2F, {axisMult, axisMult}, true); } if (isApplyStrangenessSysUncert) { - histos.add("hMultiplicityMCStangeDecay", "hMultiplicityMCStangeDecay", kTH1F, {axisMult}, true); - histos.add("hMultiplicityMCSubtractionSDecay", "hMultiplicityMCSubtractionSDecay", kTH1F, {axisMult}, true); - histos.add("hResponseMatrixStrangeDecay", "hResponseMatrixStrangeDecay", kTH2F, {axisMult, axisMult}, true); - histos.add("hResponseMatrixSubtractionSDecay", "hResponseMatrixSubtractionSDecay", kTH2F, {axisMult, axisMult}, true); + histos.add("hMultiplicityMCSubStrDecay", "hMultiplicityMCSubStrDecay", kTH1F, {axisMult}, true); + histos.add("hResponseMatrixSubStrDecay", "hResponseMatrixSubStrDecay", kTH2F, {axisMult, axisMult}, true); } if (doprocessEvtLossSigLossMC) { histos.add("MCEventHist", "MCEventHist", kTH1F, {axisEvent}, false); @@ -339,7 +327,8 @@ struct StudyPnch { template int countStrangeTracksMcCol(countTrk const& tracks, McColType const& McCol) { - auto nTrk_strange = 0; + auto nTrkStrange = 0; + auto nTrk = 0; std::vector mcRecIDs; for (const auto& track : tracks) { if (!isTrackSelected(track)) { @@ -357,20 +346,19 @@ struct StudyPnch { if (particle.has_mothers()) { auto mcMother = particle.template mothers_as().front(); if (mcMother.pdgCode() == PDG_t::kK0Short || std::abs(mcMother.pdgCode()) == PDG_t::kLambda0) { - nTrk_strange++; + nTrkStrange++; } } + nTrk++; } } - return nTrk_strange; + return nTrk - nTrkStrange; } template - int countTracksPtCut(countTrk const& tracks, McColType const& McCol) + float countTracksPtCut(countTrk const& tracks, McColType const& McCol) { - auto nTrk_lowpT = 0; - auto nTrk_highpT = 0; - auto nTrk = 0; + float nTrk = 0.0; for (const auto& track : tracks) { if (!isGenTrackSelected(track)) { continue; @@ -378,20 +366,14 @@ struct StudyPnch { if (track.mcCollisionId() != McCol.mcCollisionId()) { continue; } - // Evaluate low pT extrapolation - if (track.pt() < kMinPtCut) { - // nTrk_lowpT++; - if (ispTincrease) { - nTrk_lowpT += 2 - 10 * track.pt(); - } - if (ispTdecrease) { - nTrk_lowpT += 0.5 + 5 * track.pt(); - } + if (track.pt() > pTminCut) + continue; + if (isPtincrease) { + nTrk += 2 - 10 * track.pt(); } else { - nTrk_highpT++; + nTrk += 0.5 + 5 * track.pt(); } } - nTrk = nTrk_lowpT + nTrk_highpT; return nTrk; } @@ -426,48 +408,37 @@ struct StudyPnch { histos.fill(HIST("NPVtracks_vs_GlobalMult"), cols.multNTracksPV(), mult); } - void processMonteCarlo(soa::Join::iterator const& mcCollision, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + void processMonteCarlo(soa::Join::iterator const& mcCollision, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { + if (isApplyInelgt0 && !mcCollision.isInelGt0()) { + return; + } + for (const auto& RecCol : RecCols) { if (!isEventSelected(RecCol)) { continue; } - histos.fill(HIST("SelCollsHist"), 1); // Evaluation of reconstructed collisions with more than 1 contributor if (RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { continue; } - histos.fill(HIST("SelCollsHist"), 2); if (!RecCol.has_mcCollision()) { continue; } - histos.fill(HIST("SelCollsHist"), 3); auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex()); auto multrec = countNTracksMcCol(recTracksPart, RecCol); - if (multrec > 0) { - histos.fill(HIST("hMultiplicityMCrec"), multrec); - } - auto multgen = countGenTracks(GenParticles, RecCol); - if (multgen > 0 && multrec > 0) { - histos.fill(HIST("hMultiplicityMCgen"), multgen); - histos.fill(HIST("hResponseMatrix"), multrec, multgen); - } - if (ispTincrease || ispTdecrease) { - auto nTrkPtCut = countTracksPtCut(GenParticles, RecCol); - if (nTrkPtCut > 0) { - histos.fill(HIST("hMultiplicityMCgenPtCut"), nTrkPtCut); - histos.fill(HIST("hResponseMatrixPtCut"), multrec, nTrkPtCut); - } - } + histos.fill(HIST("hMultiplicityMCrec"), multrec); + float multgen = countGenTracks(GenParticles, RecCol); + histos.fill(HIST("hMultiplicityMCgen"), multgen); + histos.fill(HIST("hResponseMatrix"), multrec, multgen); + float nTrkPtCut = countTracksPtCut(GenParticles, RecCol); + nTrkPtCut = multgen + nTrkPtCut; + histos.fill(HIST("hMultiplicityMCgenPtCut"), nTrkPtCut); + histos.fill(HIST("hResponseMatrixPtCut"), multrec, nTrkPtCut); if (isApplyStrangenessSysUncert) { - auto nTrk_strange = countStrangeTracksMcCol(recTracksPart, RecCol); - auto nSubtract_strange = multrec - nTrk_strange; - if (multrec > 0) { - histos.fill(HIST("hMultiplicityMCStangeDecay"), nTrk_strange); - histos.fill(HIST("hMultiplicityMCSubtractionSDecay"), nSubtract_strange); - histos.fill(HIST("hResponseMatrixStrangeDecay"), nTrk_strange, multgen); - histos.fill(HIST("hResponseMatrixSubtractionSDecay"), nSubtract_strange, multgen); - } + auto nSubtractStrange = countStrangeTracksMcCol(recTracksPart, RecCol); + histos.fill(HIST("hMultiplicityMCSubStrDecay"), nSubtractStrange); + histos.fill(HIST("hResponseMatrixSubStrDecay"), nSubtractStrange, multgen); } } } From 230c187a7010bdce3f199fc99c70e51d0bf7a251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 12 May 2026 14:31:36 +0200 Subject: [PATCH 141/449] [DPG] Fix includes (#16087) --- DPG/Tasks/AOTTrack/qaEventTrack.cxx | 2 -- DPG/Tasks/AOTTrack/qaEventTrackLite.cxx | 3 ++- DPG/Tasks/AOTTrack/{qaEventTrack.h => qaEventTrackLite.h} | 8 ++++---- DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) rename DPG/Tasks/AOTTrack/{qaEventTrack.h => qaEventTrackLite.h} (98%) diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.cxx b/DPG/Tasks/AOTTrack/qaEventTrack.cxx index b4baddb2685..57e901ee54f 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrack.cxx @@ -21,8 +21,6 @@ /// \brief Task to produce QA objects for the track and the event properties in the AOD. /// -#include "qaEventTrack.h" - #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/MetadataHelper.h" #include "Common/DataModel/EventSelection.h" diff --git a/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx b/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx index 61938e1d348..34373a3e1ad 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx @@ -18,7 +18,7 @@ /// This task runs on prefiltered data /// -#include "qaEventTrack.h" +#include "qaEventTrackLite.h" #include #include @@ -41,6 +41,7 @@ #include #include #include +#include #include #include diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.h b/DPG/Tasks/AOTTrack/qaEventTrackLite.h similarity index 98% rename from DPG/Tasks/AOTTrack/qaEventTrack.h rename to DPG/Tasks/AOTTrack/qaEventTrackLite.h index edd9512c5ec..3af51e15d65 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.h +++ b/DPG/Tasks/AOTTrack/qaEventTrackLite.h @@ -10,15 +10,15 @@ // or submit itself to any jurisdiction. /// -/// \file qaEventTrack.h +/// \file qaEventTrackLite.h /// \author Mario Krüger /// \author Mattia Faggin /// \author Nicolò Jacazio /// \brief Header file for QA tasks for the track and the event properties. /// -#ifndef DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ -#define DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ +#ifndef DPG_TASKS_AOTTRACK_QAEVENTTRACKLITE_H_ +#define DPG_TASKS_AOTTRACK_QAEVENTTRACKLITE_H_ #include "Common/DataModel/TrackSelectionTables.h" @@ -170,4 +170,4 @@ DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the mcparticle::Vx, mcparticle::Vy, mcparticle::Vz); } // namespace o2::aod -#endif // DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ +#endif // DPG_TASKS_AOTTRACK_QAEVENTTRACKLITE_H_ diff --git a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx index 8e41e7a24cc..9c5285ca358 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx @@ -17,7 +17,7 @@ /// \brief Task to produce a table with reduced information used for correlation studies for track selection, ideally used with qaEventTrackite /// -#include "qaEventTrack.h" +#include "qaEventTrackLite.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" From 50ffd30514ac13be11c14f05132228e4e55b1d90 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Tue, 12 May 2026 21:21:07 +0800 Subject: [PATCH 142/449] [PWGCF] jEPFlowAnalysis.cxx: define a new configurable axis of pseudorapidity and add one more dimension to the scalar product histograms (#16187) --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 45 ++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 0038553d347..ed05872fee3 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -35,11 +35,12 @@ #include #include #include +#include #include #include -#include #include +#include #include #include @@ -60,7 +61,9 @@ using MyTracks = soa::Join; using MyTracksMC = soa::Join; -struct jEPFlowAnalysis { +struct JEPFlowAnalysis { + + Service pdg; HistogramRegistry epFlowHistograms{"EPFlow", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; EventPlaneHelper helperEP; @@ -70,9 +73,9 @@ struct jEPFlowAnalysis { o2::ccdb::CcdbApi ccdbApi; struct : ConfigurableGroup { - Configurable cfgURL{"cfgURL", + Configurable cfgUrl{"cfgUrl", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; - Configurable nolaterthan{"ccdb-no-later-than", + Configurable nolaterthan{"nolaterthan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; } cfgCcdbParam; @@ -114,6 +117,7 @@ struct jEPFlowAnalysis { ConfigurableAxis cfgAxisCent{"cfgAxisCent", {100, 0, 100}, ""}; ConfigurableAxis cfgAxisPt{"cfgAxisPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0, 15.0, 30.0, 50.0, 70.0, 100.0}, ""}; + ConfigurableAxis cfgAxisEta{"cfgAxisEta", {20, -1, 1}, ""}; ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {200, -5.0, 5.0}, ""}; @@ -135,6 +139,8 @@ struct jEPFlowAnalysis { float cent; + float minQvecAmp = 1e-5; + float minChg = 0.1; std::vector shiftprofile{}; std::string fullCCDBShiftCorrPath; @@ -307,8 +313,8 @@ struct jEPFlowAnalysis { epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn, weight); epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin, weight); - epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); - epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), track.eta(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); } } } @@ -326,7 +332,7 @@ struct jEPFlowAnalysis { void init(InitContext const&) { - ccdb->setURL(cfgCcdbParam.cfgURL); + ccdb->setURL(cfgCcdbParam.cfgUrl); ccdbApi.init("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -342,6 +348,7 @@ struct jEPFlowAnalysis { AxisSpec axisCent{cfgAxisCent, "cent"}; AxisSpec axisPt{cfgAxisPt, "pT"}; + AxisSpec axisEta{cfgAxisEta, "eta"}; AxisSpec axisCos{cfgAxisCos, "cos"}; AxisSpec axisQvec{cfgAxisQvec, "Qvec"}; @@ -369,8 +376,8 @@ struct jEPFlowAnalysis { epFlowHistograms.add("EpResQvecRefARefBxx", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); epFlowHistograms.add("EpResQvecRefARefBxy", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); - epFlowHistograms.add("SPvnxx", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisQvec}}); - epFlowHistograms.add("SPvnxy", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisQvec}}); + epFlowHistograms.add("SPvnxx", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); + epFlowHistograms.add("SPvnxy", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); epFlowHistograms.add("hCentrality", "", {HistType::kTH1F, {axisCent}}); epFlowHistograms.add("hVertex", "", {HistType::kTH1F, {axisVertex}}); @@ -416,12 +423,12 @@ struct jEPFlowAnalysis { } } - if (coll.qvecAmp()[detId] < 1e-5 || coll.qvecAmp()[refAId] < 1e-5 || coll.qvecAmp()[refBId] < 1e-5) + if (coll.qvecAmp()[detId] < minQvecAmp || coll.qvecAmp()[refAId] < minQvecAmp || coll.qvecAmp()[refBId] < minQvecAmp) return; fillvn(coll, tracks); } - PROCESS_SWITCH(jEPFlowAnalysis, processDefault, "default process", true); + PROCESS_SWITCH(JEPFlowAnalysis, processDefault, "default process", true); void processMCRec(MyCollisionsMC::iterator const& coll, MyTracksMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) { @@ -445,7 +452,7 @@ struct jEPFlowAnalysis { } } - for (auto trk : tracks) { + for (const auto& trk : tracks) { if (!trk.has_mcParticle()) { continue; } @@ -461,7 +468,7 @@ struct jEPFlowAnalysis { } } } - PROCESS_SWITCH(jEPFlowAnalysis, processMCRec, "process for MC", false); + PROCESS_SWITCH(JEPFlowAnalysis, processMCRec, "process for MC", false); void processMCGen(MyCollisionsMC::iterator const& coll, aod::McParticles const& mcParticles, aod::McCollisions const&) { @@ -477,13 +484,13 @@ struct jEPFlowAnalysis { float cent = coll.centFT0C(); - for (auto& mcParticle : mcParticles) { + for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.eta()) > cfgTrackCuts.cfgEtaMax) continue; - auto* p = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); - if (p) { - if (std::abs(p->Charge()) < 1e-1) { + auto p = pdg->GetParticle(mcParticle.pdgCode()); + if (p != nullptr) { + if (std::abs(p->Charge()) < minChg) { continue; } } @@ -494,11 +501,11 @@ struct jEPFlowAnalysis { epFlowHistograms.fill(HIST("MC/hPartGen"), cent, mcColl.posZ(), mcParticle.eta(), mcParticle.phi(), mcParticle.pt()); } } - PROCESS_SWITCH(jEPFlowAnalysis, processMCGen, "process for MC", false); + PROCESS_SWITCH(JEPFlowAnalysis, processMCGen, "process for MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } From 96c4e9ab44648877b82dd73fbe226cfeb3883e67 Mon Sep 17 00:00:00 2001 From: hfribert Date: Tue, 12 May 2026 15:54:28 +0200 Subject: [PATCH 143/449] [PWGLF] Fix mult. mixing bins (#16215) Co-authored-by: Henrik Fribert --- PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index 20777c211c3..db2f50c8e29 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -42,7 +42,6 @@ #include #include -#include #include #include #include @@ -631,14 +630,12 @@ struct sigmaHadCorrTask { SliceCache cache; using BinningTypeNumContrib = ColumnBinningPolicy; using BinningTypeMultNTracksPV = ColumnBinningPolicy; - BinningTypeNumContrib colBinningNumContrib{{CfgVtxBins, CfgMultBins}, true}; - BinningTypeMultNTracksPV colBinningPVMult{{CfgVtxBins, CfgMultBins}, true}; void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) { if (useMultNTracksPV.value) { for (auto const& [collision1, collision2] : - selfCombinations(colBinningPVMult, nEvtMixingBkg, -1, collisions, collisions)) { + selfCombinations(BinningTypeMultNTracksPV{{CfgVtxBins, CfgMultBins}, true}, nEvtMixingBkg, -1, collisions, collisions)) { if (collision1.index() == collision2.index()) continue; sigmaHadCandidates.clear(); @@ -661,7 +658,7 @@ struct sigmaHadCorrTask { } } else { for (auto const& [collision1, collision2] : - selfCombinations(colBinningNumContrib, nEvtMixingBkg, -1, collisions, collisions)) { + selfCombinations(BinningTypeNumContrib{{CfgVtxBins, CfgMultBins}, true}, nEvtMixingBkg, -1, collisions, collisions)) { if (collision1.index() == collision2.index()) continue; sigmaHadCandidates.clear(); @@ -772,7 +769,7 @@ struct sigmaHadCorrTask { { if (useMultNTracksPV.value) { for (auto const& [collision1, collision2] : - selfCombinations(colBinningPVMult, nEvtMixingBkg, -1, collisions, collisions)) { + selfCombinations(BinningTypeMultNTracksPV{{CfgVtxBins, CfgMultBins}, true}, nEvtMixingBkg, -1, collisions, collisions)) { if (collision1.index() == collision2.index()) continue; sigmaHadCandidates.clear(); @@ -821,7 +818,7 @@ struct sigmaHadCorrTask { } } else { for (auto const& [collision1, collision2] : - selfCombinations(colBinningNumContrib, nEvtMixingBkg, -1, collisions, collisions)) { + selfCombinations(BinningTypeNumContrib{{CfgVtxBins, CfgMultBins}, true}, nEvtMixingBkg, -1, collisions, collisions)) { if (collision1.index() == collision2.index()) continue; sigmaHadCandidates.clear(); From 9a1b87e05747973feafd42af8e38466800ffc818 Mon Sep 17 00:00:00 2001 From: Oussama3030 <59825001+Oussama3030@users.noreply.github.com> Date: Tue, 12 May 2026 15:55:35 +0200 Subject: [PATCH 144/449] [PWGLF] small fixes (#16217) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFSigmaTables.h | 8 ++++++-- PWGLF/TableProducer/Strangeness/sigma0builder.cxx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/PWGLF/DataModel/LFSigmaTables.h b/PWGLF/DataModel/LFSigmaTables.h index 56140e5fdfd..69ff56bcc5f 100644 --- a/PWGLF/DataModel/LFSigmaTables.h +++ b/PWGLF/DataModel/LFSigmaTables.h @@ -195,6 +195,9 @@ DECLARE_SOA_TABLE(Sigma0Cores, "AOD", "SIGMA0CORES", // KSTAR core info namespace kstarCore { +DECLARE_SOA_COLUMN(PhotonV0ID, photonV0ID, int); +DECLARE_SOA_COLUMN(KShortV0ID, kshortV0ID, int); + DECLARE_SOA_COLUMN(X, x, float); DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Z, z, float); @@ -312,6 +315,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(KShortPhi, kshortPhi, //! Phi in the range [0, 2pi) } // namespace kstarCore DECLARE_SOA_TABLE(KStarCores, "AOD", "KSTARCORES", + kstarCore::PhotonV0ID, kstarCore::KShortV0ID, kstarCore::X, kstarCore::Y, kstarCore::Z, kstarCore::DCADaughters, kstarCore::PhotonPx, kstarCore::PhotonPy, kstarCore::PhotonPz, kstarCore::PhotonMass, kstarCore::KShortPx, kstarCore::KShortPy, kstarCore::KShortPz, kstarCore::KShortMass, @@ -796,8 +800,8 @@ DECLARE_SOA_COLUMN(KShortPDGCode, kshortPDGCode, int); DECLARE_SOA_COLUMN(KShortPDGCodeMother, kshortPDGCodeMother, int); DECLARE_SOA_COLUMN(KShortIsCorrectlyAssoc, kshortIsCorrectlyAssoc, bool); -DECLARE_SOA_DYNAMIC_COLUMN(IsKStar, isKStar, //! IsSigma0 - [](int pdgCode) -> bool { return pdgCode == o2::constants::physics::Pdg::kK0Star892; }); // 313 +DECLARE_SOA_DYNAMIC_COLUMN(IsKStar, isKStar, //! IsSigma0 + [](int pdgCode) -> bool { return std::abs(pdgCode) == o2::constants::physics::Pdg::kK0Star892; }); // 313 DECLARE_SOA_DYNAMIC_COLUMN(MCPx, mcpx, //! Sigma0 px [](float photonMCPx, float kshortMCPx) -> float { return photonMCPx + kshortMCPx; }); diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx index a9aa9520624..3888e00f8e5 100644 --- a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -2546,7 +2546,7 @@ struct sigma0builder { auto kstarTopoInfo = propagateV0PairToDCA(gamma, kshort); - kstarcores(kstarTopoInfo.X, kstarTopoInfo.Y, kstarTopoInfo.Z, kstarTopoInfo.DCADau, + kstarcores(gamma.globalIndex(), kshort.globalIndex(), kstarTopoInfo.X, kstarTopoInfo.Y, kstarTopoInfo.Z, kstarTopoInfo.DCADau, gamma.px(), gamma.py(), gamma.pz(), gamma.mGamma(), kshort.px(), kshort.py(), kshort.pz(), kshort.mK0Short()); // MC properties From 90e270a0e46237ad96ca9db5bb02b07355b74a9e Mon Sep 17 00:00:00 2001 From: Kai Cui <129373281+kcui1@users.noreply.github.com> Date: Tue, 12 May 2026 16:34:30 +0200 Subject: [PATCH 145/449] [PWGLF] Bug Fix in hStrangeCorrelation.cxx (#16218) --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index f5f41d16af4..00ec57541a0 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -1218,6 +1218,9 @@ struct HStrangeCorrelation { static_for<0, 3>([&](auto i) { constexpr int Index = i.value; + if ((Index == IndexOmegaMinus || Index == IndexOmegaPlus) && assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && std::abs(assocCandidate.invMassNSigma(Index - 2)) < massWindowConfigurations.nSigmaNearXiMassCenter) { + return; + } float efficiency = 1.0f; float totalEffUncert = 0.0; float efficiencyError = 0.0f; From 9b566fa25d4ed3e9c9a4549cdfd76f201167968e Mon Sep 17 00:00:00 2001 From: nepeivodaRS <94179174+nepeivodaRS@users.noreply.github.com> Date: Tue, 12 May 2026 16:52:34 +0200 Subject: [PATCH 146/449] [PWGLF] use reconstructed eventType in cascade analysis (#16208) --- .../Strangeness/cascqaanalysis.cxx | 102 ++++++++++++------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index 452d1c45e92..6ca9c40082b 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -44,11 +44,14 @@ #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -74,6 +77,19 @@ struct Cascqaanalysis { HistogramRegistry registry{"registry"}; + enum EventTypeBin { + kINEL = 0, + kINELgt0, + kINELgt1, + kNEventTypeBins + }; + + static constexpr std::array, kNEventTypeBins> EventTypeBinLabels{{ + {kINEL, "INEL"}, + {kINELgt0, "INEL>0"}, + {kINELgt1, "INEL>1"}, + }}; + // Axes ConfigurableAxis ptAxis{"ptAxis", {200, 0.0f, 10.0f}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis rapidityAxis{"rapidityAxis", {200, -2.0f, 2.0f}, "y"}; @@ -83,7 +99,7 @@ struct Cascqaanalysis { ConfigurableAxis centFV0AAxis{"centFV0AAxis", {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 105.5}, "FV0A (%)"}; - ConfigurableAxis eventTypeAxis{"eventTypeAxis", {3, -0.5f, 2.5f}, "Event Type"}; + ConfigurableAxis eventTypeAxis{"eventTypeAxis", {kNEventTypeBins, -0.5f, static_cast(kNEventTypeBins) - 0.5f}, "Event Type"}; ConfigurableAxis nAssocCollAxis{"nAssocCollAxis", {5, -0.5f, 4.5f}, "N_{assoc.}"}; ConfigurableAxis nChargedFT0MGenAxis{"nChargedFT0MGenAxis", {300, 0, 300}, "N_{FT0M, gen.}"}; @@ -194,6 +210,14 @@ struct Cascqaanalysis { o2::constants::physics::MassOmegaMinus * decayLength * invMomentum}; } + template + static void setEventTypeAxisLabels(TAxisType* axis) + { + for (const auto& [bin, label] : EventTypeBinLabels) { + axis->SetBinLabel(static_cast(bin) + 1, label); + } + } + void init(InitContext const&) { TString hCandidateCounterLabels[4] = {"All candidates", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; @@ -220,15 +244,25 @@ struct Cascqaanalysis { registry.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); } registry.add("hZCollisionGen", "hZCollisionGen", {HistType::kTH1D, {{200, -20.f, 20.f}}}); + registry.add("hZCollisionRecVsGen", "hZCollisionRecVsGen", {HistType::kTH2D, {{100, -10.f, 10.f, "z_{vtx}^{rec} (cm)"}, {100, -10.f, 10.f, "z_{vtx}^{gen} (cm)"}}}); + registry.add("hEventTypeRecVsGen", "hEventTypeRecVsGen", {HistType::kTH2D, {eventTypeAxis, eventTypeAxis}}); registry.add("hNchFT0MNAssocMCCollisions", "hNchFT0MNAssocMCCollisions", {HistType::kTH3D, {nChargedFT0MGenAxis, nAssocCollAxis, eventTypeAxis}}); registry.add("hNchFT0MNAssocMCCollisionsSameType", "hNchFT0MNAssocMCCollisionsSameType", {HistType::kTH3D, {nChargedFT0MGenAxis, nAssocCollAxis, eventTypeAxis}}); registry.add("hNContributorsCorrelation", "hNContributorsCorrelation", {HistType::kTH2F, {{250, -0.5f, 249.5f, "Secondary Contributor"}, {250, -0.5f, 249.5f, "Main Contributor"}}}); registry.add("hNchFT0MGenEvType", "hNchFT0MGenEvType", {HistType::kTH2D, {nChargedFT0MGenAxis, eventTypeAxis}}); registry.add("hNchFV0AGenEvType", "hNchFV0AGenEvType", {HistType::kTH2D, {nChargedFV0AGenAxis, eventTypeAxis}}); registry.add("hCentFT0M_genMC", "hCentFT0M_genMC", {HistType::kTH2D, {centFT0MAxis, eventTypeAxis}}); + setEventTypeAxisLabels(registry.get(HIST("hEventTypeRecVsGen"))->GetXaxis()); + setEventTypeAxisLabels(registry.get(HIST("hEventTypeRecVsGen"))->GetYaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFT0MNAssocMCCollisions"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFT0MNAssocMCCollisionsSameType"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFT0MGenEvType"))->GetYaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFV0AGenEvType"))->GetYaxis()); + setEventTypeAxisLabels(registry.get(HIST("hCentFT0M_genMC"))->GetYaxis()); } registry.add("hCentFT0M_rec", "hCentFT0M_rec", {HistType::kTH2D, {centFT0MAxis, eventTypeAxis}}); + setEventTypeAxisLabels(registry.get(HIST("hCentFT0M_rec"))->GetYaxis()); if (candidateQA) { registry.add("hNcandidates", "hNcandidates", {HistType::kTH3D, {nCandidates, centFT0MAxis, {2, -0.5f, 1.5f}}}); @@ -242,6 +276,9 @@ struct Cascqaanalysis { registry.add("hNchFT0Mglobal", "hNchFT0Mglobal", {HistType::kTH3D, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); registry.add("hNchFT0MPVContr", "hNchFT0MPVContr", {HistType::kTH3D, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); registry.add("hNchFV0APVContr", "hNchFV0APVContr", {HistType::kTH3D, {nChargedFV0AGenAxis, multNTracksAxis, eventTypeAxis}}); + setEventTypeAxisLabels(registry.get(HIST("hNchFT0Mglobal"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFT0MPVContr"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hNchFV0APVContr"))->GetZaxis()); } registry.add("hFT0MpvContr", "hFT0MpvContr", {HistType::kTH3D, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); registry.add("hFV0ApvContr", "hFV0ApvContr", {HistType::kTH3D, {centFV0AAxis, multNTracksAxis, eventTypeAxis}}); @@ -249,6 +286,11 @@ struct Cascqaanalysis { registry.add("hFV0AFT0M", "hFV0AFT0M", {HistType::kTH3D, {centFV0AAxis, centFT0MAxis, eventTypeAxis}}); registry.add("hFT0MFV0Asignal", "hFT0MFV0Asignal", {HistType::kTH2D, {signalFT0MAxis, signalFV0AAxis}}); registry.add("hFT0MsignalPVContr", "hFT0MsignalPVContr", {HistType::kTH3D, {signalFT0MAxis, multNTracksAxis, eventTypeAxis}}); + setEventTypeAxisLabels(registry.get(HIST("hFT0MpvContr"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hFV0ApvContr"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hFT0Mglobal"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hFV0AFT0M"))->GetZaxis()); + setEventTypeAxisLabels(registry.get(HIST("hFT0MsignalPVContr"))->GetZaxis()); } rctChecker.init(cfgEvtRCTFlagCheckerLabel, cfgEvtRCTFlagCheckerZDCCheck, cfgEvtRCTFlagCheckerLimitAcceptAsBad); @@ -334,20 +376,19 @@ struct Cascqaanalysis { } template - int getEventTypeFlag(TCollision const& collision) + EventTypeBin getEventTypeBin(TCollision const& collision) { - // 0 - INEL, 1 - INEL>0, 2 - INEL>1 - int evFlag = 0; + EventTypeBin evTypeBin = kINEL; registry.fill(HIST("hNEvents"), 11.5); // INEL if (collision.isInelGt0()) { - evFlag += 1; + evTypeBin = kINELgt0; registry.fill(HIST("hNEvents"), 12.5); // INEL>0 } if (collision.isInelGt1()) { - evFlag += 1; + evTypeBin = kINELgt1; registry.fill(HIST("hNEvents"), 13.5); // INEL>1 } - return evFlag; + return evTypeBin; } template @@ -451,7 +492,7 @@ struct Cascqaanalysis { return; } - int evType = getEventTypeFlag(collision); + EventTypeBin evType = getEventTypeBin(collision); auto tracksGroupedPVcontr = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); int nTracksPVcontr = tracksGroupedPVcontr.size(); @@ -549,31 +590,30 @@ struct Cascqaanalysis { uint16_t nchFT0 = getGenNchInFT0Mregion(mcPartSlice); uint16_t nchFV0 = getGenNchInFV0Aregion(mcPartSlice); - int evType = 0; - registry.fill(HIST("hNEvents"), 11.5); // INEL - // Rec. collision associated with INEL>0 gen. one + EventTypeBin genEvType = kINEL; if (pwglf::isINELgtNmc(mcPartSlice, 0, pdgDB)) { - registry.fill(HIST("hNEvents"), 12.5); // INEL - evType++; + genEvType = kINELgt0; } - // Rec. collision associated with INEL>1 gen. one if (pwglf::isINELgtNmc(mcPartSlice, 1, pdgDB)) { - registry.fill(HIST("hNEvents"), 13.5); // INEL - evType++; + genEvType = kINELgt1; } - registry.fill(HIST("hCentFT0M_rec"), mcCollision.centFT0M(), evType); + const EventTypeBin recoEvType = getEventTypeBin(collision); + + registry.fill(HIST("hCentFT0M_rec"), mcCollision.centFT0M(), recoEvType); + registry.fill(HIST("hZCollisionRecVsGen"), collision.posZ(), mcCollision.posZ()); + registry.fill(HIST("hEventTypeRecVsGen"), recoEvType, genEvType); if (multQA) { - registry.fill(HIST("hNchFT0MPVContr"), nchFT0, nTracksPVcontr, evType); - registry.fill(HIST("hNchFV0APVContr"), nchFV0, nTracksPVcontr, evType); - registry.fill(HIST("hFT0MpvContr"), mcCollision.centFT0M(), nTracksPVcontr, evType); - registry.fill(HIST("hFV0ApvContr"), 0, nTracksPVcontr, evType); // mcCollision.centFV0A() to be added - registry.fill(HIST("hFT0Mglobal"), mcCollision.centFT0M(), nTracksGlobal, evType); - registry.fill(HIST("hFV0AFT0M"), 0, mcCollision.centFT0M(), evType); // mcCollision.centFV0A() to be added - registry.fill(HIST("hNchFT0Mglobal"), nchFT0, nTracksGlobal, evType); + registry.fill(HIST("hNchFT0MPVContr"), nchFT0, nTracksPVcontr, recoEvType); + registry.fill(HIST("hNchFV0APVContr"), nchFV0, nTracksPVcontr, recoEvType); + registry.fill(HIST("hFT0MpvContr"), mcCollision.centFT0M(), nTracksPVcontr, recoEvType); + registry.fill(HIST("hFV0ApvContr"), 0, nTracksPVcontr, recoEvType); // mcCollision.centFV0A() to be added + registry.fill(HIST("hFT0Mglobal"), mcCollision.centFT0M(), nTracksGlobal, recoEvType); + registry.fill(HIST("hFV0AFT0M"), 0, mcCollision.centFT0M(), recoEvType); // mcCollision.centFV0A() to be added + registry.fill(HIST("hNchFT0Mglobal"), nchFT0, nTracksGlobal, recoEvType); registry.fill(HIST("hFT0MFV0Asignal"), collision.multFT0A() + collision.multFT0C(), collision.multFV0A()); - registry.fill(HIST("hFT0MsignalPVContr"), collision.multFT0A() + collision.multFT0C(), nTracksPVcontr, evType); + registry.fill(HIST("hFT0MsignalPVContr"), collision.multFT0A() + collision.multFT0C(), nTracksPVcontr, recoEvType); } float lEventScale = scalefactor; @@ -654,20 +694,20 @@ struct Cascqaanalysis { registry.fill(HIST("hNEventsMC"), 1.5); // Define the type of generated MC collision - int evType = 0; + EventTypeBin evType = kINEL; uint8_t flagsGen = 0; flagsGen |= o2::aod::myMCcascades::EvFlags::EvINEL; registry.fill(HIST("hNEventsMC"), 2.5); // Generated collision is INEL>0 if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt0; - evType++; + evType = kINELgt0; registry.fill(HIST("hNEventsMC"), 3.5); } // Generated collision is INEL>1 if (pwglf::isINELgtNmc(mcParticles, 1, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt1; - evType++; + evType = kINELgt1; registry.fill(HIST("hNEventsMC"), 4.5); } @@ -723,15 +763,15 @@ struct Cascqaanalysis { const auto evtReconstructedAndINELgt1 = std::count_if(selectedEvents.begin(), selectedEvents.end(), isAssocToINELgt1); switch (evType) { - case 0: { + case kINEL: { registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINEL, evType); break; } - case 1: { + case kINELgt0: { registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINELgt0, evType); break; } - case 2: { + case kINELgt1: { registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINELgt1, evType); break; } From 41d4ee059771b6929f7dda108cacabe8be6d1c4d Mon Sep 17 00:00:00 2001 From: Chiara Pinto <48326672+chiarapinto@users.noreply.github.com> Date: Tue, 12 May 2026 17:02:35 +0200 Subject: [PATCH 147/449] [PWGLF] Add custom nsigma calculations for helium-3 (#16219) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 56872bad8ed..c03452e1684 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -374,6 +374,8 @@ struct AntinucleiInJets { registryData.add("tpcsignal_data", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); registryData.add("antihelium3_jet_tpc_custom", "antihelium3_jet_tpc_custom", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC} custom"}}); registryData.add("antihelium3_ue_tpc_custom", "antihelium3_ue_tpc_custom", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC} custom"}}); + registryData.add("helium3_jet_tpc_custom", "helium3_jet_tpc_custom", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC} custom"}}); + registryData.add("helium3_ue_tpc_custom", "helium3_ue_tpc_custom", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC} custom"}}); } // Generated antiproton spectra in jets and UE from MC truth @@ -1401,6 +1403,11 @@ struct AntinucleiInJets { } if (passedItsPidHel) { registryData.fill(HIST("helium3_jet_tpc"), 2.0 * pt, nsigmaTPCHe); + // custom nsigma He3 based on bethe bloch fit of TPC signal + double tpcSignal = track.tpcSignal(); + double expectedSignalHe3 = common::BetheBlochAleph(static_cast(track.tpcInnerParam() * 2. / o2::constants::physics::MassHelium3), cfgBetheBlochParams.value[0], cfgBetheBlochParams.value[1], cfgBetheBlochParams.value[2], cfgBetheBlochParams.value[3], cfgBetheBlochParams.value[4]); + double nSigmaTPCHe3Custom = ((tpcSignal / expectedSignalHe3) - 1.) / 0.045; + registryData.fill(HIST("helium3_jet_tpc_custom"), 2.0 * pt, nSigmaTPCHe3Custom); } } } @@ -1496,6 +1503,11 @@ struct AntinucleiInJets { } if (passedItsPidHel) { registryData.fill(HIST("helium3_ue_tpc"), 2.0 * pt, nsigmaTPCHe); + // custom nsigma He3 based on bethe bloch fit of TPC signal + double tpcSignal = track.tpcSignal(); + double expectedSignalHe3 = common::BetheBlochAleph(static_cast(track.tpcInnerParam() * 2. / o2::constants::physics::MassHelium3), cfgBetheBlochParams.value[0], cfgBetheBlochParams.value[1], cfgBetheBlochParams.value[2], cfgBetheBlochParams.value[3], cfgBetheBlochParams.value[4]); + double nSigmaTPCHe3Custom = ((tpcSignal / expectedSignalHe3) - 1.) / 0.045; + registryData.fill(HIST("helium3_ue_tpc_custom"), 2.0 * pt, nSigmaTPCHe3Custom); } } } From 7363e15488a4d74addb67aab13228c3c006a654e Mon Sep 17 00:00:00 2001 From: navneetkumar231295 <71565461+navneetkumar231295@users.noreply.github.com> Date: Tue, 12 May 2026 21:42:30 +0530 Subject: [PATCH 148/449] [PWGLF] [PWG:LF] To remove the unused function and add the KShot selection (#16211) Co-authored-by: Navneet --- .../Tasks/Resonances/chargedkstaranalysis.cxx | 107 +++--------------- 1 file changed, 18 insertions(+), 89 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx index fa36132eb6d..e494d017558 100644 --- a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx @@ -344,7 +344,6 @@ struct Chargedkstaranalysis { AxisSpec thnAxisPhi = {axisCfgs.configThnAxisPhi, "Configurabel phi axis"}; // 0 to 2pi // THnSparse AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; - if (!doprocessMC) { histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); auto hCutFlow = histos.get(HIST("hEvtSelInfo")); @@ -403,7 +402,6 @@ struct Chargedkstaranalysis { histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); histos.add("QA/before/CentDist1", "Centrality distribution", HistType::kTH1F, {{110, 0, 110}}); - histos.add("QA/trkbpionTPCPIDME", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); // Bachelor pion @@ -744,88 +742,7 @@ struct Chargedkstaranalysis { return returnFlag; } - template - bool isTrueKstar(const TrackTemplate& bTrack, const V0Template& K0scand) - { - if (std::abs(bTrack.PDGCode()) != kPiPlus) // Are you pion? - return false; - if (std::abs(K0scand.PDGCode()) != kPDGK0s) // Are you K0s? - return false; - - auto motherbTrack = bTrack.template mothers_as(); - auto motherkV0 = K0scand.template mothers_as(); - - // Check bTrack first - if (std::abs(motherbTrack.pdgCode()) != kKstarPlus) // Are you charged Kstar's daughter? - return false; // Apply first since it's more restrictive - - if (std::abs(motherkV0.pdgCode()) != kPDGK0) // Is it K0s? - return false; - // Check if K0s's mother is K0 (311) - auto motherK0 = motherkV0.template mothers_as(); - if (std::abs(motherK0.pdgCode()) != kPDGK0) - return false; - - // Check if K0's mother is Kstar (323) - auto motherKstar = motherK0.template mothers_as(); - if (std::abs(motherKstar.pdgCode()) != kKstarPlus) - return false; - - // Check if bTrack and K0 have the same mother (global index) - if (motherbTrack.globalIndex() != motherK0.globalIndex()) - return false; - - return true; - } - int count = 0; - template - bool matchRecoToTruthKstar(V0T const& v0, TrkT const& trk) - { - if (!v0.has_mcParticle() || !trk.has_mcParticle()) - return false; - - auto mcK0s = v0.template mcParticle_as(); - auto mcPi = trk.template mcParticle_as(); - - if (std::abs(mcK0s.pdgCode()) != kPDGK0s) - return false; - if (std::abs(mcPi.pdgCode()) != kPiPlus) - return false; - - MCTrueTrackCandidates::iterator kstarFromPi; - bool havePiKstar = false; - for (const auto& m1 : mcPi.template mothers_as()) { - if (std::abs(m1.pdgCode()) == kKstarPlus) { - kstarFromPi = m1; - havePiKstar = true; - break; - } - } - if (!havePiKstar) { - return false; - } - - bool shareSameKstar = false; - for (const auto& m1 : mcK0s.template mothers_as()) { - if (std::abs(m1.pdgCode()) == kPDGK0) { - for (const auto& m2 : m1.template mothers_as()) { - if (m2.globalIndex() == kstarFromPi.globalIndex()) { - shareSameKstar = true; - break; - } - } - if (shareSameKstar) - break; - } - } - if (!shareSameKstar) { - return false; - } - - return true; - } // matchRecoToTruthKstar - template void fillKstarHist(bool isRot, float multiplicity, const T& mother, double cosTheta) { @@ -1313,7 +1230,6 @@ struct Chargedkstaranalysis { histos.fill(HIST("QA/MC/QACent_woCut"), lCentrality); histos.fill(HIST("QA/MC/QAvtxz_woCut"), coll.posZ()); } - if (!colCuts.isSelected(coll)) continue; if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(coll)) @@ -1408,9 +1324,7 @@ struct Chargedkstaranalysis { if (!coll.has_mcCollision()) continue; - const auto mcid = coll.mcCollisionId(); - if (allowedMcIds.count(mcid) == 0) continue; // To check the event is allowed or not @@ -1427,7 +1341,6 @@ struct Chargedkstaranalysis { } if (!selectionK0s(coll, v0)) continue; - auto trks = tracks.sliceBy(perCollision, v0.collisionId()); // Grouping the tracks with the v0s, means only those tracks that belong to the same collision as v0 for (const auto& bTrack : trks) { if (bTrack.collisionId() != v0.collisionId()) @@ -1436,7 +1349,6 @@ struct Chargedkstaranalysis { continue; if (!selectionPIDPion(bTrack)) continue; - LorentzVectorSetXYZM lResoSecondary, lDecayDaughter_bach, lResoKstar, lDaughterRot; lResoSecondary = LorentzVectorSetXYZM(v0.px(), v0.py(), v0.pz(), MassK0Short); @@ -1447,7 +1359,6 @@ struct Chargedkstaranalysis { const double yreco = lResoKstar.Rapidity(); if (std::abs(yreco) > kstarCutCfgs.cKstarMaxRap) continue; - // Since we are doing the MC study and we know about the PDG code of each particle let's try to check the things which we have if (!v0.has_mcParticle() || !bTrack.has_mcParticle()) continue; @@ -1470,6 +1381,24 @@ struct Chargedkstaranalysis { if (!havePiKstar) { continue; } + // Loops over all the mother's of K0s and check if this K0s comming from a kstar and also share the smae mother as of the pion + bool shareSameKstar = false; + for (const auto& m1 : mcK0s.template mothers_as()) { + if (std::abs(m1.pdgCode()) == kPDGK0) { + for (const auto& m2 : m1.template mothers_as()) { + if (m2.globalIndex() == kstarFromPi.globalIndex()) { + shareSameKstar = true; + break; + } + } + if (shareSameKstar) + break; + } + } + if (!shareSameKstar) { + continue; + } + histos.fill(HIST("EffKstar/recoKstar"), ptreco, lCentrality); if (helicityCfgs.cBoostKShot) { fillInvMass(lResoKstar, lCentrality, lResoSecondary, lDecayDaughter_bach, eventCutCfgs.confIsMix); From 9fd9a0ef82b63306d6c7d9e8d042a62357a02c6b Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Tue, 12 May 2026 18:21:45 +0200 Subject: [PATCH 149/449] [PWGLF] Fix event selection in MC table for spin correlation and add new process function for high mass resonance ananlysis (#16220) --- .../Strangeness/lambdaspincorrelation.cxx | 65 +++- PWGLF/Tasks/Resonances/doublephimeson.cxx | 350 +++++++++++++++++- .../Strangeness/lambdaspincorrderived.cxx | 19 + 3 files changed, 416 insertions(+), 18 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx index f20460f7171..33561ee14cd 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -114,7 +114,7 @@ struct lambdaspincorrelation { { rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); AxisSpec thnAxisInvMass{iMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; - histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); histos.add("hLambdaMass", "hLambdaMass", kTH1F, {thnAxisInvMass}); histos.add("hV0Info", "hV0Info", kTH1F, {{5, 0, 5.0}}); } @@ -234,6 +234,46 @@ struct lambdaspincorrelation { return {lambdaTag, aLambdaTag, true}; // Valid candidate } + std::tuple getLambdaTagsMC(const auto& v0, const auto& collision) + { + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + int lambdaTag = 0; + int aLambdaTag = 0; + + const auto signpos = postrack.sign(); + const auto signneg = negtrack.sign(); + + if (signpos < 0 || signneg > 0) { + return {0, 0, false}; + } + + if (isSelectedV0Daughter(v0, postrack, 0) && + isSelectedV0Daughter(v0, negtrack, 1) && + v0.mLambda() > lbinIM && + v0.mLambda() < hbinIM) { + lambdaTag = 1; + } + + if (isSelectedV0Daughter(v0, negtrack, 0) && + isSelectedV0Daughter(v0, postrack, 1) && + v0.mAntiLambda() > lbinIM && + v0.mAntiLambda() < hbinIM) { + aLambdaTag = 1; + } + + if (!lambdaTag && !aLambdaTag) { + return {0, 0, false}; + } + + if (!selectionV0(collision, v0)) { + return {0, 0, false}; + } + + return {lambdaTag, aLambdaTag, true}; + } + ROOT::Math::PxPyPzMVector lambda, antiLambda, proton, pion, antiProton, antiPion; ROOT::Math::PxPyPzMVector lambdaDummy, pionDummy, protonDummy; @@ -474,6 +514,7 @@ struct lambdaspincorrelation { ResoV0s const& V0s, aod::McParticles const&) { + histos.fill(HIST("hEvtSelInfo"), 0.5); if (collisions.size() == 1) { for (const auto& collision : collisions) { @@ -498,7 +539,7 @@ struct lambdaspincorrelation { auto vz = collision.posZ(); int occupancy = collision.trackOccupancyInTimeRange(); - histos.fill(HIST("hEvtSelInfo"), 0.5); + histos.fill(HIST("hEvtSelInfo"), 1.5); if (std::abs(collision.posZ()) < cfgCutVertex && (!rctCut.requireRCTFlagChecker || rctChecker(collision)) && @@ -513,29 +554,27 @@ struct lambdaspincorrelation { (!useGoodITSLayersAll || collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) && occupancy < cfgCutOccupancy) { - histos.fill(HIST("hEvtSelInfo"), 1.5); + histos.fill(HIST("hEvtSelInfo"), 2.5); for (const auto& v0 : V0s) { - - auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); + histos.fill(HIST("hEvtSelInfo"), 3.5); // all V0s seen + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTagsMC(v0, collision); if (isValid) { - + histos.fill(HIST("hEvtSelInfo"), 4.5); // passed getLambdaTagsMC auto postrack1 = v0.template posTrack_as(); auto negtrack1 = v0.template negTrack_as(); // Reject candidates whose reconstructed daughters are not MC-labelled. if (!postrack1.has_mcParticle() || !negtrack1.has_mcParticle()) { + histos.fill(HIST("hEvtSelInfo"), 5.5); // rejected: no MC label continue; } - auto mcPos = postrack1.mcParticle(); - auto mcNeg = negtrack1.mcParticle(); + // auto mcPos = postrack1.mcParticle(); + // auto mcNeg = negtrack1.mcParticle(); - // Reject gap/background-event daughters. - if (mcPos.fromBackgroundEvent() || mcNeg.fromBackgroundEvent()) { - continue; - } + histos.fill(HIST("hEvtSelInfo"), 6.5); // rejected: no MC label if (lambdaTag) { histos.fill(HIST("hV0Info"), 0.5); @@ -626,7 +665,7 @@ struct lambdaspincorrelation { } if (numbV0 > 1 && v0Cospa.size() > 1) { - histos.fill(HIST("hEvtSelInfo"), 2.5); + histos.fill(HIST("hEvtSelInfo"), 7.5); lambdaEventmc(centrality, vz); auto indexEvent = lambdaEventmc.lastIndex(); diff --git a/PWGLF/Tasks/Resonances/doublephimeson.cxx b/PWGLF/Tasks/Resonances/doublephimeson.cxx index bab19207680..61b181646cf 100644 --- a/PWGLF/Tasks/Resonances/doublephimeson.cxx +++ b/PWGLF/Tasks/Resonances/doublephimeson.cxx @@ -15,6 +15,7 @@ #include "PWGLF/DataModel/ReducedDoublePhiTables.h" +#include #include #include #include @@ -91,6 +92,7 @@ struct doublephimeson { ConfigurableAxis configThnAxisDeltaRPhi{"configThnAxisDeltaRPhi", {120, 0.0, 6.0}, "ΔR(φ,φ)"}; ConfigurableAxis configThnAxisZ{"configThnAxisZ", {100, 0.0, 1.0}, "z"}; ConfigurableAxis configThnAxisA{"configThnAxisA", {100, 0.0, 1.0}, "A"}; + // Initialize the ananlysis task void init(o2::framework::InitContext&) { @@ -126,6 +128,15 @@ struct doublephimeson { // --- NEW THnSparse storing (ΔRphi, z, A) WITHOUT applying cuts --- histos.add("SEMassUnlike_DeltaRZA", "SEMassUnlike_DeltaRZA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisDeltaRPhi, thnAxisZ, thnAxisA, thnAxisInvMassDeltaPhi}); histos.add("MEMassUnlike_DeltaRZA", "MEMassUnlike_DeltaRZA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisDeltaRPhi, thnAxisZ, thnAxisA, thnAxisInvMassDeltaPhi}); + histos.add("SEMassUnlike_AllVars", "SEMassUnlike_AllVars", HistType::kTHnSparseF, + {thnAxisInvMass, // M(phi-phi) + thnAxisPt, // pT(phi-phi) + thnAxisDeltaRPhi, // DeltaR(phi,phi) + thnAxisDeltaR, // min DeltaR(K,K) + thnAxisZ, // z = pT1 / (pT1 + pT2) + thnAxisA, // A = |pT1 - pT2| / (pT1 + pT2) + thnAxisInvMassDeltaPhi, // DeltaM(phi1,phi2) + thnAxisPtCorr}); // pT correlation variable } // get kstar @@ -200,6 +211,99 @@ struct doublephimeson { bool selectionPID(float nsigmaTPC, float nsigmaTOF, int TOFHit, int PIDStrategy, float ptcand) { + if (PIDStrategy == 1000) { + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.5) { + return true; + } else if (TOFHit != 1 && std::abs(nsigmaTPC) < 2.0) { + return true; + } + } + + if (PIDStrategy == 1001) { + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.0) { + return true; + } else if (TOFHit != 1 && ptcand < 2.5 && std::abs(nsigmaTPC) < 2.0) { + return true; + } else if (TOFHit != 1 && ptcand >= 2.5 && nsigmaTPC > -2.0 && nsigmaTPC < 1.0) { + return true; + } + } + + if (PIDStrategy == 1002) { + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.0) { + return true; + } else if (TOFHit != 1 && std::abs(nsigmaTPC) < 2.0) { + return true; + } + } + + if (PIDStrategy == 1003) { + if (ptcand < 0.5 && nsigmaTPC > -2.0 && nsigmaTPC < 3.0) { + return true; + } + if (ptcand >= 0.5) { + if (TOFHit != 1 && nsigmaTPC > -2.0 && nsigmaTPC < 2.0) { + return true; + } + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.5) { + return true; + } + } + } + + if (PIDStrategy == 1005) { + // low pT: TPC-only + if (ptcand < 0.5 && nsigmaTPC > -2.0 && nsigmaTPC < 3.0) { + return true; + } + + // intermediate pT: require TOF + beta cut + combined TPC-TOF nsigma + if (ptcand >= 0.5 && ptcand < 5.0) { + if (TOFHit == 1 && std::sqrt(nsigmaTPC * nsigmaTPC + nsigmaTOF * nsigmaTOF) < 2.5) { + return true; + } + } + // high pT: TPC-only + if (ptcand >= 5.0 && nsigmaTPC > -2.0 && nsigmaTPC < 2.0) { + return true; + } + } + + if (PIDStrategy == 1004) { + if (ptcand < 1.2) { + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.5) { + return true; + } else if (TOFHit != 1) { + if (ptcand < 0.5 && nsigmaTPC > -2.0 && nsigmaTPC < 2.5) { + return true; + } + if (ptcand >= 0.5 && ptcand < 0.6 && nsigmaTPC > -1.5 && nsigmaTPC < 2.5) { + return true; + } + if (ptcand >= 0.6 && ptcand < 0.7 && nsigmaTPC > -1.0 && nsigmaTPC < 2.0) { + return true; + } + if (ptcand >= 0.7 && ptcand < 0.8 && nsigmaTPC > -0.4 && nsigmaTPC < 2.0) { + return true; + } + if (ptcand >= 0.8 && ptcand < 1.0 && nsigmaTPC > 0.0 && nsigmaTPC < 2.0) { + return true; + } + if (ptcand >= 1.0 && ptcand < 1.2 && nsigmaTPC > -2.5 && nsigmaTPC < 0.5) { + return true; + } + } + } else { + if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.5) { + return true; + } else if (TOFHit != 1 && ptcand < 2.0 && nsigmaTPC > -2.5 && nsigmaTPC < 2.0) { + return true; + } else if (TOFHit != 1 && ptcand > 2.0 && nsigmaTPC > -2.5 && nsigmaTPC < 1.0) { + return true; + } + } + } + if (PIDStrategy == 100) { if (ptcand < 1.2) { if (TOFHit == 1 && std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.5) { @@ -451,7 +555,7 @@ struct doublephimeson { if (!selectionPID(phitrackd1.phid1TPC(), phitrackd1.phid1TOF(), phitrackd1.phid1TOFHit(), strategyPID1, kaonplusd1pt)) { continue; } - if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID1, kaonminusd1pt)) { + if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID2, kaonminusd1pt)) { continue; } histos.fill(HIST("hnsigmaTPCTOFKaon"), phitrackd1.phid1TPC(), phitrackd1.phid1TOF(), kaonplusd1pt); @@ -570,7 +674,7 @@ struct doublephimeson { if (!selectionPID(phitrackd1.phid1TPC(), phitrackd1.phid1TOF(), phitrackd1.phid1TOFHit(), strategyPID1, kaonplusd1pt)) { continue; } - if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID1, kaonminusd1pt)) { + if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID2, kaonminusd1pt)) { continue; } phimult = phimult + 1; @@ -592,7 +696,7 @@ struct doublephimeson { if (!selectionPID(phitrackd1.phid1TPC(), phitrackd1.phid1TOF(), phitrackd1.phid1TOFHit(), strategyPID1, kaonplusd1pt)) { continue; } - if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID1, kaonminusd1pt)) { + if (!selectionPID(phitrackd1.phid2TPC(), phitrackd1.phid2TOF(), phitrackd1.phid2TOFHit(), strategyPID2, kaonminusd1pt)) { continue; } histos.fill(HIST("hnsigmaTPCTOFKaon"), phitrackd1.phid1TPC(), phitrackd1.phid1TOF(), kaonplusd1pt); @@ -974,8 +1078,8 @@ struct doublephimeson { return; // --- helpers --- - constexpr double mPhiPDG = 1.019461; // GeV/c^2 - constexpr double mKPDG = 0.493677; // GeV/c^2 + constexpr double mPhiPDG = o2::constants::physics::MassPhi; // GeV/c^2 + constexpr double mKPDG = o2::constants::physics::MassKPlus; // GeV/c^2 const auto deltaMPhi = [=](double m1, double m2) { const double d1 = m1 - mPhiPDG, d2 = m2 - mPhiPDG; @@ -1157,6 +1261,242 @@ struct doublephimeson { } PROCESS_SWITCH(doublephimeson, processopti4, "Process Optimized same event", true); + void processopti5(aod::RedPhiEvents::iterator const& collision, aod::PhiTracks const& phitracks) + { + if (additionalEvsel && (collision.numPos() < 2 || collision.numNeg() < 2)) { + return; + } + + // --- phi multiplicity with PID --- + int phimult = 0; + for (auto const& t : phitracks) { + const double kpluspt = std::hypot(t.phid1Px(), t.phid1Py()); + const double kminuspt = std::hypot(t.phid2Px(), t.phid2Py()); + + histos.fill(HIST("hnsigmaTPCTOFKaonBefore"), t.phid1TPC(), t.phid1TOF(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonPlusBefore"), t.phid1TPC(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonMinusBefore"), t.phid2TPC(), kminuspt); + + if (t.phiMass() < minPhiMass1 || t.phiMass() > maxPhiMass1) { + continue; + } + if (kpluspt > maxKaonPt || kminuspt > maxKaonPt) { + continue; + } + if (!selectionPID(t.phid1TPC(), t.phid1TOF(), t.phid1TOFHit(), strategyPID1, kpluspt)) { + continue; + } + if (!selectionPID(t.phid2TPC(), t.phid2TOF(), t.phid2TOFHit(), strategyPID2, kminuspt)) { + continue; + } + + histos.fill(HIST("hnsigmaTPCTOFKaon"), t.phid1TPC(), t.phid1TOF(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonPlus"), t.phid1TPC(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonMinus"), t.phid2TPC(), kminuspt); + + ++phimult; + } + + if (phimult < 2) { + return; + } + + constexpr double mPhiPDG = o2::constants::physics::MassPhi; // GeV/c^2 + constexpr double mKPDG = o2::constants::physics::MassKPlus; // GeV/c^2 + + const auto deltaMPhi = [=](double m1, double m2) { + const double d1 = m1 - mPhiPDG; + const double d2 = m2 - mPhiPDG; + return std::sqrt(d1 * d1 + d2 * d2); + }; + const auto deltaR = [](double phi1, double eta1, double phi2, double eta2) { + const double dphi = std::abs(TVector2::Phi_mpi_pi(phi1 - phi2)); + const double deta = eta1 - eta2; + return std::sqrt(dphi * dphi + deta * deta); + }; + const auto minKaonDeltaR = [&](const ROOT::Math::PtEtaPhiMVector& kplus1, + const ROOT::Math::PtEtaPhiMVector& kminus1, + const ROOT::Math::PtEtaPhiMVector& kplus2, + const ROOT::Math::PtEtaPhiMVector& kminus2) { + const double dRkplus = deltaR(kplus1.Phi(), kplus1.Eta(), kplus2.Phi(), kplus2.Eta()); + const double dRkminus = deltaR(kminus1.Phi(), kminus1.Eta(), kminus2.Phi(), kminus2.Eta()); + + histos.fill(HIST("hDeltaRkaonplus"), dRkplus); + histos.fill(HIST("hDeltaRkaonminus"), dRkminus); + + double minDR = dRkplus; + minDR = std::min(minDR, dRkminus); + minDR = std::min(minDR, deltaR(kplus1.Phi(), kplus1.Eta(), kminus1.Phi(), kminus1.Eta())); + minDR = std::min(minDR, deltaR(kplus1.Phi(), kplus1.Eta(), kminus2.Phi(), kminus2.Eta())); + minDR = std::min(minDR, deltaR(kplus2.Phi(), kplus2.Eta(), kminus1.Phi(), kminus1.Eta())); + minDR = std::min(minDR, deltaR(kplus2.Phi(), kplus2.Eta(), kminus2.Phi(), kminus2.Eta())); + + return minDR; + }; + + std::vector pairV; + std::vector phi1V; + std::vector phi2V; + std::vector minDRV; + + for (auto const& t1 : phitracks) { + const double kplus1pt = std::hypot(t1.phid1Px(), t1.phid1Py()); + const double kminus1pt = std::hypot(t1.phid2Px(), t1.phid2Py()); + + if (kplus1pt > maxKaonPt || kminus1pt > maxKaonPt) { + continue; + } + if (!selectionPID(t1.phid1TPC(), t1.phid1TOF(), t1.phid1TOFHit(), strategyPID1, kplus1pt)) { + continue; + } + if (!selectionPID(t1.phid2TPC(), t1.phid2TOF(), t1.phid2TOFHit(), strategyPID2, kminus1pt)) { + continue; + } + + TLorentzVector phi1; + TLorentzVector k1p; + TLorentzVector k1m; + + phi1.SetXYZM(t1.phiPx(), t1.phiPy(), t1.phiPz(), t1.phiMass()); + k1p.SetXYZM(t1.phid1Px(), t1.phid1Py(), t1.phid1Pz(), mKPDG); + k1m.SetXYZM(t1.phid2Px(), t1.phid2Py(), t1.phid2Pz(), mKPDG); + + if (t1.phiMass() < minPhiMass1 || t1.phiMass() > maxPhiMass1) { + continue; + } + if (phi1.Pt() < minPhiPt || phi1.Pt() > maxPhiPt) { + continue; + } + + const auto id1 = t1.index(); + + for (auto const& t2 : phitracks) { + const auto id2 = t2.index(); + if (id2 <= id1) { + continue; + } + + const double kplus2pt = std::hypot(t2.phid1Px(), t2.phid1Py()); + const double kminus2pt = std::hypot(t2.phid2Px(), t2.phid2Py()); + + if (kplus2pt > maxKaonPt || kminus2pt > maxKaonPt) { + continue; + } + if (!selectionPID(t2.phid1TPC(), t2.phid1TOF(), t2.phid1TOFHit(), strategyPID1, kplus2pt)) { + continue; + } + if (!selectionPID(t2.phid2TPC(), t2.phid2TOF(), t2.phid2TOFHit(), strategyPID2, kminus2pt)) { + continue; + } + + // reject any shared daughter between the two phi candidates + if (t1.phid1Index() == t2.phid1Index() || + t1.phid1Index() == t2.phid2Index() || + t1.phid2Index() == t2.phid1Index() || + t1.phid2Index() == t2.phid2Index()) { + continue; + } + + TLorentzVector phi2; + TLorentzVector k2p; + TLorentzVector k2m; + + phi2.SetXYZM(t2.phiPx(), t2.phiPy(), t2.phiPz(), t2.phiMass()); + k2p.SetXYZM(t2.phid1Px(), t2.phid1Py(), t2.phid1Pz(), mKPDG); + k2m.SetXYZM(t2.phid2Px(), t2.phid2Py(), t2.phid2Pz(), mKPDG); + + if (t2.phiMass() < minPhiMass2 || t2.phiMass() > maxPhiMass2) { + continue; + } + if (phi2.Pt() < minPhiPt || phi2.Pt() > maxPhiPt) { + continue; + } + + const double dM = deltaMPhi(phi1.M(), phi2.M()); + if (dM > maxDeltaMPhi) { + continue; + } + + TLorentzVector pair = phi1 + phi2; + if (pair.M() < minExoticMass || pair.M() > maxExoticMass) { + continue; + } + + histos.fill(HIST("hPhiMass"), phi1.M(), phi2.M(), pair.Pt()); + + ROOT::Math::PtEtaPhiMVector k1pV(k1p.Pt(), k1p.Eta(), k1p.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k1mV(k1m.Pt(), k1m.Eta(), k1m.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k2pV(k2p.Pt(), k2p.Eta(), k2p.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k2mV(k2m.Pt(), k2m.Eta(), k2m.Phi(), mKPDG); + + const double minDR = minKaonDeltaR(k1pV, k1mV, k2pV, k2mV); + + pairV.emplace_back(pair.Pt(), pair.Eta(), pair.Phi(), pair.M()); + phi1V.emplace_back(phi1.Pt(), phi1.Eta(), phi1.Phi(), phi1.M()); + phi2V.emplace_back(phi2.Pt(), phi2.Eta(), phi2.Phi(), phi2.M()); + minDRV.emplace_back(minDR); + } + } + + if (pairV.empty()) { + return; + } + + for (size_t i = 0; i < pairV.size(); ++i) { + TLorentzVector p1; + TLorentzVector p2; + TLorentzVector pair; + + p1.SetPtEtaPhiM(phi1V[i].Pt(), phi1V[i].Eta(), phi1V[i].Phi(), phi1V[i].M()); + p2.SetPtEtaPhiM(phi2V[i].Pt(), phi2V[i].Eta(), phi2V[i].Phi(), phi2V[i].M()); + pair.SetPtEtaPhiM(pairV[i].Pt(), pairV[i].Eta(), pairV[i].Phi(), pairV[i].M()); + + const double M = pair.M(); + const double pairPt = pair.Pt(); + const double dRphi = deltaR(p1.Phi(), p1.Eta(), p2.Phi(), p2.Eta()); + const double minDR = minDRV[i]; + const double dM = deltaMPhi(p1.M(), p2.M()); + + const double denom = pairPt - p1.Pt(); + if (std::abs(denom) < 1e-9) { + continue; + } + + const double ptcorr = p1.Pt() / denom; + + const double pt1 = p1.Pt(); + const double pt2 = p2.Pt(); + const double ptsum = pt1 + pt2; + if (ptsum <= 0.0) { + continue; + } + + const double z = pt1 / ptsum; + const double A = std::abs(pt1 - pt2) / ptsum; + + histos.fill(HIST("hPtCorrelation"), pairPt, ptcorr); + + histos.fill(HIST("SEMassUnlike"), + M, + minDR, + pairPt, + dRphi, + dM, + ptcorr); + + histos.fill(HIST("SEMassUnlike_AllVars"), + M, + pairPt, + dRphi, + minDR, + z, + A, + dM, + ptcorr); + } + } + PROCESS_SWITCH(doublephimeson, processopti5, "Process Optimized same event with all variables", true); + SliceCache cache; using BinningTypeVertexContributor = ColumnBinningPolicy; diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 742c8b639ac..012685039f0 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -1336,6 +1336,7 @@ struct lambdaspincorrderived { { return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); } + // symmetric neighbors for phi: no wrap at edge static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) { @@ -1350,6 +1351,7 @@ struct lambdaspincorrderived { std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); } + static inline void collectNeighborBinsClamp(int b, int nBins, int nNeighbor, std::vector& out) { out.clear(); @@ -1361,6 +1363,22 @@ struct lambdaspincorrderived { } } } + static inline void collectNeighborBinsMass(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb >= 0 && bb < nBins) { + out.push_back(bb); + } + } + + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } + static inline int getMassRegionFromEdges(float m, const std::vector& edges) { if (edges.size() != 4) { @@ -1818,6 +1836,7 @@ struct lambdaspincorrderived { } } PROCESS_SWITCH(lambdaspincorrderived, processMEV6, "Process data ME v6 with radius buffer", false); + void processMCMEV6(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) { MixBinnerR mb{ From 90e552a08dfbd4c7de82e2b37bc5f60f6fe6d830 Mon Sep 17 00:00:00 2001 From: creetz16 <79141119+creetz16@users.noreply.github.com> Date: Tue, 12 May 2026 18:39:04 +0200 Subject: [PATCH 150/449] [Trigger,PWGHF] Add Xic ct QA histogram to HFFilter task (#16224) --- EventFiltering/PWGHF/HFFilter.cxx | 7 ++++--- EventFiltering/PWGHF/HFFilterHelpers.h | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 15e6fc87ba8..bec34ce57e4 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -249,7 +249,7 @@ struct HfFilter { // Main struct for HF triggers std::array, kNCharmParticles> hBDTScorePrompt{}; std::array, kNCharmParticles> hBDTScoreNonPrompt{}; std::array, kNV0> hArmPod{}; - std::shared_ptr hV0Selected; + std::shared_ptr hV0Selected, hMassVsCtCharmBaryonToXiPiPi; std::array, 2> hMassXi{}; // not tracked and tracked std::array, kNBeautyParticles> hCpaVsPtB{}; std::array, kNBeautyParticles> hDecayLengthVsPtB{}; @@ -390,6 +390,7 @@ struct HfFilter { // Main struct for HF triggers hMassVsPtC[kNCharmParticles + 15] = registry.add("fMassVsPtCharmBaryonToXiPi", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+#pi candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 15]}); hMassVsPtC[kNCharmParticles + 16] = registry.add("fMassVsPtCharmBaryonToXiKa", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+K candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 16]}); hMassVsPtC[kNCharmParticles + 17] = registry.add("fMassVsPtCharmBaryonToXiPiPi", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+#pi+#pi candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 17]}); + hMassVsCtCharmBaryonToXiPiPi = registry.add("fMassVsCtCharmBaryonToXiPiPi", "#it{M} vs. ct distribution of triggered #Xi+#pi+#pi candidates;ct (cm);#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ctAxis, massAxisC[kNCharmParticles + 17]}); // JPsi hMassVsPtC[kNCharmParticles + 18] = registry.add("fMassVsPtJPsiToMuMu", "#it{M} vs. #it{p}_{T} distribution of triggered J/#psi to #mu#mu candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 18]}); // Lc resonances @@ -1991,10 +1992,10 @@ struct HfFilter { // Main struct for HF triggers bool isSelXiBachBach{false}; if (requireStrangenessTracking->get(0u, 1u) > 0) { if (hasStrangeTrack) { - isSelXiBachBach = helper.isSelectedXiBachBach<3>(trackParCascTrack, {trackParBachelor, trackParBachelorSecond}, collision, dfStrangeness3, activateQA, hMassVsPtC[kNCharmParticles + 17]); + isSelXiBachBach = helper.isSelectedXiBachBach<3>(trackParCascTrack, {trackParBachelor, trackParBachelorSecond}, collision, dfStrangeness3, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXiPiPi); } } else { // vertex with only the two bachelors - isSelXiBachBach = helper.isSelectedXiBachBach<2>(trackParCasc, {trackParBachelor, trackParBachelorSecond}, collision, df2, activateQA, hMassVsPtC[kNCharmParticles + 17]); + isSelXiBachBach = helper.isSelectedXiBachBach<2>(trackParCasc, {trackParBachelor, trackParBachelorSecond}, collision, df2, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXiPiPi); } if (isSelXiBachBach) { keepEvent[kCharmBarToXi2Bach] = true; diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index d215fb0df8d..d36f0f7cdeb 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -288,6 +288,7 @@ constexpr float massJPsi = o2::constants::physics::MassJPsi; static const o2::framework::AxisSpec ptAxis{50, 0.f, 50.f}; static const o2::framework::AxisSpec pAxis{50, 0.f, 10.f}; +static const o2::framework::AxisSpec ctAxis{300, 0.f, 0.3f}; static const o2::framework::AxisSpec kstarAxis{200, 0.f, 2.f}; static const o2::framework::AxisSpec etaAxis{30, -1.5f, 1.5f}; static const o2::framework::AxisSpec nSigmaAxis{100, -10.f, 10.f}; @@ -718,7 +719,7 @@ class HfFilterHelper template bool isSelectedXiBach(T const& trackParCasc, T const& trackParBachelor, int8_t isSelBachelor, C const& collision, o2::vertexing::DCAFitterN<2>& dcaFitter, const int& activateQA, H2 hMassVsPtXiPi, H2 hMassVsPtXiKa); template - bool isSelectedXiBachBach(T const& trackParCasc, std::array const& trackParBachelor, C const& collision, o2::vertexing::DCAFitterN& dcaFitter, const int& activateQA, H2 hMassVsPtXiPiPi); + bool isSelectedXiBachBach(T const& trackParCasc, std::array const& trackParBachelor, C const& collision, o2::vertexing::DCAFitterN& dcaFitter, const int& activateQA, H2 hMassVsPtXiPiPi, H2 hMassVsCtXiPiPi); template bool isSelectedProtonFromLcResoOrThetaC(const T& track); // helpers @@ -2506,8 +2507,9 @@ inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& tra /// \param dcaFitter is the DCAFitter /// \param activateQA is the flag to activate the QA /// \param hMassVsPtXiPiPi is the 2D histogram with pT vs mass(XiPiPi) +/// \param hMassVsCtXiPiPi is the 2D histogram with ct vs mass(XiPiPi) template -inline bool HfFilterHelper::isSelectedXiBachBach(T const& trackParCasc, std::array const& trackParBachelor, C const& collision, o2::vertexing::DCAFitterN& dcaFitter, const int& activateQA, H2 hMassVsPtXiPiPi) +inline bool HfFilterHelper::isSelectedXiBachBach(T const& trackParCasc, std::array const& trackParBachelor, C const& collision, o2::vertexing::DCAFitterN& dcaFitter, const int& activateQA, H2 hMassVsPtXiPiPi, H2 hMassVsCtXiPiPi) { // compute pT std::array pVecBachelorFirst{}, pVecBachelorSecond{}, pVecCascade{}; @@ -2570,13 +2572,15 @@ inline bool HfFilterHelper::isSelectedXiBachBach(T const& trackParCasc, std::arr if (RecoDecay::cpa(primVtx, std::array{vtx[0], vtx[1], vtx[2]}, momXiBachBach) < mCosPaMinXiBach[1]) { return false; } - - if (RecoDecay::distance(primVtx, vtx) < mDecLenMinXiBach[1]) { + auto decLenXiBachBach = RecoDecay::distance(primVtx, vtx); + if (decLenXiBachBach < mDecLenMinXiBach[1]) { return false; } + auto ctXiBachBach = RecoDecay::ct(momXiBachBach, decLenXiBachBach, massXic); if (activateQA) { hMassVsPtXiPiPi->Fill(ptXiBachBach, massXiPiPi); + hMassVsCtXiPiPi->Fill(ctXiBachBach, massXiPiPi); } } From dc2065fb47d3f7a7ee01bfa14a8a0ca7a23364f0 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Tue, 12 May 2026 18:39:58 +0200 Subject: [PATCH 151/449] [PWGCF] Update Flow Event Plane Changed the rapidity axis in Lambda (#16223) --- PWGCF/Flow/Tasks/flowEventPlane.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index 5253f04a7ab..aae66f85825 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -823,7 +823,6 @@ struct FlowEventPlane { const AxisSpec axisTrackdEdx{360, 20, 200, "#frac{dE}{dx}"}; const AxisSpec axisTrackNSigma{161, -4.025, 4.025, {"n#sigma"}}; - const AxisSpec axisTrackRap{cNRapBins, -0.5, 0.5, "y"}; const AxisSpec axisPhiInvMass{cPhiInvMassBins, 0.99, 1.12, "M_{KK} (GeV/#it{c}^{2}"}; const AxisSpec axisKStarInvMass{cKStarInvMassBins, 0.8, 1.2, "M_{#piK} (GeV/#it{c}^{2}"}; const AxisSpec axisMomPID(80, 0, 4, "p_{T} (GeV/#it{c})"); @@ -903,13 +902,13 @@ struct FlowEventPlane { histos.add("V0/Lambda/QA/hNegNsigPiVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); histos.addClone("V0/Lambda/", "V0/K0Short/"); histos.add("V0/Lambda/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisLambdaInvMass, axisTrackEta}); - histos.add("V0/Lambda/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); - histos.add("V0/Lambda/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); + histos.add("V0/Lambda/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackEta, axisLambdaInvMass}); + histos.add("V0/Lambda/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackEta, axisLambdaInvMass}); histos.addClone("V0/Lambda/", "V0/AntiLambda/"); histos.addClone("V0/Lambda/", "V0/LambdaAntiLambda/"); histos.add("V0/K0Short/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisK0ShortInvMass, axisTrackEta}); - histos.add("V0/K0Short/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); - histos.add("V0/K0Short/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); + histos.add("V0/K0Short/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackEta, axisK0ShortInvMass}); + histos.add("V0/K0Short/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackEta, axisK0ShortInvMass}); } } From f689d47a0d082aff2592f2456306162627f11833 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 12 May 2026 19:58:36 +0200 Subject: [PATCH 152/449] [Trigger,PWGHF] Add mass vs ct histogram also for Xic0 (#16226) --- EventFiltering/PWGHF/HFFilter.cxx | 14 ++++++++------ EventFiltering/PWGHF/HFFilterHelpers.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index bec34ce57e4..158a358d4ef 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -249,7 +249,8 @@ struct HfFilter { // Main struct for HF triggers std::array, kNCharmParticles> hBDTScorePrompt{}; std::array, kNCharmParticles> hBDTScoreNonPrompt{}; std::array, kNV0> hArmPod{}; - std::shared_ptr hV0Selected, hMassVsCtCharmBaryonToXiPiPi; + std::shared_ptr hV0Selected; + std::array, 2> hMassVsCtCharmBaryonToXi{}; std::array, 2> hMassXi{}; // not tracked and tracked std::array, kNBeautyParticles> hCpaVsPtB{}; std::array, kNBeautyParticles> hDecayLengthVsPtB{}; @@ -390,7 +391,8 @@ struct HfFilter { // Main struct for HF triggers hMassVsPtC[kNCharmParticles + 15] = registry.add("fMassVsPtCharmBaryonToXiPi", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+#pi candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 15]}); hMassVsPtC[kNCharmParticles + 16] = registry.add("fMassVsPtCharmBaryonToXiKa", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+K candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 16]}); hMassVsPtC[kNCharmParticles + 17] = registry.add("fMassVsPtCharmBaryonToXiPiPi", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+#pi+#pi candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 17]}); - hMassVsCtCharmBaryonToXiPiPi = registry.add("fMassVsCtCharmBaryonToXiPiPi", "#it{M} vs. ct distribution of triggered #Xi+#pi+#pi candidates;ct (cm);#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ctAxis, massAxisC[kNCharmParticles + 17]}); + hMassVsCtCharmBaryonToXi[0] = registry.add("fMassVsCtCharmBaryonToXiPi", "#it{M} vs. ct distribution of triggered #Xi+#pi candidates;ct (cm);#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ctAxis, massAxisC[kNCharmParticles + 15]}); + hMassVsCtCharmBaryonToXi[1] = registry.add("fMassVsCtCharmBaryonToXiPiPi", "#it{M} vs. ct distribution of triggered #Xi+#pi+#pi candidates;ct (cm);#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ctAxis, massAxisC[kNCharmParticles + 17]}); // JPsi hMassVsPtC[kNCharmParticles + 18] = registry.add("fMassVsPtJPsiToMuMu", "#it{M} vs. #it{p}_{T} distribution of triggered J/#psi to #mu#mu candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 18]}); // Lc resonances @@ -1949,10 +1951,10 @@ struct HfFilter { // Main struct for HF triggers bool isSelXiBach{false}; if (requireStrangenessTracking->get(0u, 0u) > 0) { if (hasStrangeTrack) { - isSelXiBach = helper.isSelectedXiBach(trackParCascTrack, trackParBachelor, isSelBachelor, collision, dfStrangeness, activateQA, hMassVsPtC[kNCharmParticles + 15], hMassVsPtC[kNCharmParticles + 16]); + isSelXiBach = helper.isSelectedXiBach(trackParCascTrack, trackParBachelor, isSelBachelor, collision, dfStrangeness, activateQA, hMassVsPtC[kNCharmParticles + 15], hMassVsPtC[kNCharmParticles + 16], hMassVsCtCharmBaryonToXi[0]); } } else { - isSelXiBach = helper.isSelectedXiBach(trackParCasc, trackParBachelor, isSelBachelor, collision, dfStrangeness, activateQA, hMassVsPtC[kNCharmParticles + 15], hMassVsPtC[kNCharmParticles + 16]); + isSelXiBach = helper.isSelectedXiBach(trackParCasc, trackParBachelor, isSelBachelor, collision, dfStrangeness, activateQA, hMassVsPtC[kNCharmParticles + 15], hMassVsPtC[kNCharmParticles + 16], hMassVsCtCharmBaryonToXi[0]); } if (isSelXiBach) { keepEvent[kCharmBarToXiBach] = true; @@ -1992,10 +1994,10 @@ struct HfFilter { // Main struct for HF triggers bool isSelXiBachBach{false}; if (requireStrangenessTracking->get(0u, 1u) > 0) { if (hasStrangeTrack) { - isSelXiBachBach = helper.isSelectedXiBachBach<3>(trackParCascTrack, {trackParBachelor, trackParBachelorSecond}, collision, dfStrangeness3, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXiPiPi); + isSelXiBachBach = helper.isSelectedXiBachBach<3>(trackParCascTrack, {trackParBachelor, trackParBachelorSecond}, collision, dfStrangeness3, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXi[1]); } } else { // vertex with only the two bachelors - isSelXiBachBach = helper.isSelectedXiBachBach<2>(trackParCasc, {trackParBachelor, trackParBachelorSecond}, collision, df2, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXiPiPi); + isSelXiBachBach = helper.isSelectedXiBachBach<2>(trackParCasc, {trackParBachelor, trackParBachelorSecond}, collision, df2, activateQA, hMassVsPtC[kNCharmParticles + 17], hMassVsCtCharmBaryonToXi[1]); } if (isSelXiBachBach) { keepEvent[kCharmBarToXi2Bach] = true; diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index d36f0f7cdeb..13bcfa93fa1 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -274,6 +274,7 @@ constexpr float massDPlus = o2::constants::physics::MassDPlus; constexpr float massDs = o2::constants::physics::MassDS; constexpr float massLc = o2::constants::physics::MassLambdaCPlus; constexpr float massXic = o2::constants::physics::MassXiCPlus; +constexpr float massXic0 = o2::constants::physics::MassXiC0; constexpr float massDStar = o2::constants::physics::MassDStar; constexpr float massBPlus = o2::constants::physics::MassBPlus; constexpr float massB0 = o2::constants::physics::MassB0; @@ -717,7 +718,7 @@ class HfFilterHelper template bool isCharmHadronMassInSbRegions(T1 const& massHypo1, T1 const& massHypo2, const float& lowLimitSB, const float& upLimitSB); template - bool isSelectedXiBach(T const& trackParCasc, T const& trackParBachelor, int8_t isSelBachelor, C const& collision, o2::vertexing::DCAFitterN<2>& dcaFitter, const int& activateQA, H2 hMassVsPtXiPi, H2 hMassVsPtXiKa); + bool isSelectedXiBach(T const& trackParCasc, T const& trackParBachelor, int8_t isSelBachelor, C const& collision, o2::vertexing::DCAFitterN<2>& dcaFitter, const int& activateQA, H2 hMassVsPtXiPi, H2 hMassVsPtXiKa, H2 hMassVsCtXiPi); template bool isSelectedXiBachBach(T const& trackParCasc, std::array const& trackParBachelor, C const& collision, o2::vertexing::DCAFitterN& dcaFitter, const int& activateQA, H2 hMassVsPtXiPiPi, H2 hMassVsCtXiPiPi); template @@ -2423,8 +2424,9 @@ inline bool HfFilterHelper::isCharmHadronMassInSbRegions(T1 const& massHypo1, T1 /// \param activateQA is the flag to activate the QA /// \param hMassVsPtXiPi is the 2D histogram with pT vs mass(XiPi) /// \param hMassVsPtXiKa is the 2D histogram with pT vs mass(XiKa) +/// \param hMassVsCtXiPi is the 2D histogram with ct vs mass(XiPi) template -inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& trackParBachelor, int8_t isSelBachelor, C const& collision, o2::vertexing::DCAFitterN<2>& dcaFitter, const int& activateQA, H2 hMassVsPtXiPi, H2 hMassVsPtXiKa) +inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& trackParBachelor, int8_t isSelBachelor, C const& collision, o2::vertexing::DCAFitterN<2>& dcaFitter, const int& activateQA, H2 hMassVsPtXiPi, H2 hMassVsPtXiKa, H2 hMassVsCtXiPi) { bool isSelectedXiPi{false}, isSelectedXiKa{false}; @@ -2483,13 +2485,16 @@ inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& tra return false; } - if (RecoDecay::distance(primVtx, vtx) < mDecLenMinXiBach[0]) { + auto decLenXiBach = RecoDecay::distance(primVtx, vtx); + if (decLenXiBach < mDecLenMinXiBach[0]) { return false; } if (activateQA) { if (isSelectedXiPi) { + auto ctXiBach = RecoDecay::ct(momXiBach, decLenXiBach, massXic0); hMassVsPtXiPi->Fill(ptXiBach, massXiPi); + hMassVsCtXiPi->Fill(ctXiBach, massXiPi); } if (isSelectedXiKa) { hMassVsPtXiKa->Fill(ptXiBach, massXiKa); From 13cde3b0ce3b8de076faac5702b12003b645f2ba Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 09:51:44 +0200 Subject: [PATCH 153/449] [Common] add cpaRZ in RecoDecay.h (#16227) --- Common/Core/RecoDecay.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index fcc50d23bf8..8d62822d68d 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -279,6 +279,27 @@ struct RecoDecay { return cos; } + /// Calculates cosine of pointing angle in the {r, z} plane. + /// \param posPV {x, y, z} position of the primary vertex + /// \param posSV {x, y, z} position of the secondary vertex + /// \param mom {x, y, z} momentum array + /// \return cosine of pointing angle in {r, z} + template + static double cpaRZ(const T& posPV, const U& posSV, const std::array& mom) + { + // CPARZ = (r . pz)/(|r| |pz|) + auto lineDecay = std::array{sqrtSumOfSquares(posSV[0] - posPV[0], posSV[1] - posPV[1]), posSV[2] - posPV[2]}; + auto momRZ = std::array{sqrtSumOfSquares(mom[0], mom[1]), mom[2]}; + auto cos = dotProd(lineDecay, momRZ) / std::sqrt(mag2(lineDecay) * mag2(momRZ)); + if (cos < -1.) { + return -1.; + } + if (cos > 1.) { + return 1.; + } + return cos; + } + /// Calculates proper lifetime times c. /// \note Promotes numbers to double before squaring to avoid precision loss in float multiplication. /// \param mom 3-momentum array From 29c49a8a599a5ac9a8ea524fac5d977c19dbc840 Mon Sep 17 00:00:00 2001 From: Zhengqing Wang Date: Wed, 13 May 2026 10:41:52 +0200 Subject: [PATCH 154/449] [PWGLF] Update on Event and Signal Loss (#16225) Co-authored-by: Qing --- PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx | 58 ++++++++++++-------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index d7fe4488ec0..6e390b0f7bb 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -99,9 +99,12 @@ std::shared_ptr hIsMatterGen; std::shared_ptr hIsMatterGenTwoBody; std::shared_ptr hEvtMC; std::shared_ptr hImpactParamGen; +std::shared_ptr hImpactParamGenOneReco; std::shared_ptr hImpactParamReco; std::shared_ptr hGen3HLBeforeEvtSel; std::shared_ptr hGen3HLAfterSel; +std::shared_ptr hGenOneRecoCentrality; +std::shared_ptr hRecoCentrality; std::shared_ptr hGenEventsNchEta05; std::shared_ptr hGenEventsNchEta08; std::shared_ptr hGenCentralityColvsMultiplicityGenEta05; @@ -348,6 +351,7 @@ struct hyperRecoTask { hCentFT0M = qaRegistry.add("hCentFT0M", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); if (doprocessEventLossMC) { + // Infomation for all generated collisions hEvtMC = qaRegistry.add("QAEvent/hEvtMC", ";; ", HistType::kTH1D, {{3, -0.5, 2.5}}); hEvtMC->GetXaxis()->SetBinLabel(1, "All gen evts"); hEvtMC->GetXaxis()->SetBinLabel(2, "Gen evts with al least one reconstructed"); @@ -358,25 +362,28 @@ struct hyperRecoTask { hGenEventsNchEta08 = qaRegistry.add("QAEvent/hGenEventsNchEta08", ";;", HistType::kTH2D, {{multAxis}, {2, -0.5f, +1.5f}}); hGenEventsNchEta08->GetYaxis()->SetBinLabel(1, "All gen. events"); hGenEventsNchEta08->GetYaxis()->SetBinLabel(2, "Gen evts with at least 1 rec. collisions"); - // Infomation for all generated collisions collisions hImpactParamGen = qaRegistry.add("QAEvent/McColAll/hImpactParamGen", "Impact parameter of generated MC events; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); - hGenCentralityColvsMultiplicityGenEta05 = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsMultiplicityGenEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); - hGenCentralityColvsMultiplicityGenEta08 = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsMultiplicityGenEta08", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); - hGenCentralityColvsImpactParamGen = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsImpactParamGen", "Correlation between FT0C centrality and impact parameter in generated MC events; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); - hGenCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in generated MC events; FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); - // Infomation for generated collisions collisions with at least one rec. event + // Infomation for generated collisions which at least one rec. collision and passed the event selection + hImpactParamGenOneReco = qaRegistry.add("QAEvent/McColPassedEvSel/hImpactParamGenOneReco", "Impact parameter of generated MC events with at least one rec. evt and passed the event selection; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); + hGenOneRecoCentrality = qaRegistry.add("QAEvent/McColPassedEvSel/hGenOneRecoCentrality", "Centrality distribution of generated MC events with at least one rec. evt and passed the event selection; Centrality (FT0C %); Counts", HistType::kTH1D, {centFT0CAxis}); + hGenCentralityColvsMultiplicityGenEta05 = qaRegistry.add("QAEvent/McColPassedEvSel/hGenCentralityColvsMultiplicityGenEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt and passed the event selection; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hGenCentralityColvsMultiplicityGenEta08 = qaRegistry.add("QAEvent/McColPassedEvSel/hGenCentralityColvsMultiplicityGenEta08", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt and passed the event selection; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hGenCentralityColvsImpactParamGen = qaRegistry.add("QAEvent/McColPassedEvSel/hGenCentralityColvsImpactParamGen", "Correlation between FT0C centrality and impact parameter in generated MC events with at least one rec. evt and passed the event selection; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); + hGenCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColPassedEvSel/hGenCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in generated MC events with at least one rec. evt and passed the event selection; FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); + // Infomation for all reconstructed collisions passed the event selection (for Event Splitting) hImpactParamReco = qaRegistry.add("QAEvent/McColAll/hImpactParamReco", "Impact parameter of generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); - hRecoCentralityColvsMultiplicityRecoEta05 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); - hRecoCentralityColvsMultiplicityRecoEta08 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta08", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); - hRecoCentralityColvsImpactParamReco = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsImpactParamReco", "Correlation between FT0C centrality and impact parameter in generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); - hRecoCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in generated MC events with at least one rec. evt; FT0C (%); FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); + hRecoCentrality = qaRegistry.add("QAEvent/McColAll/hRecoCentrality", "Centrality distribution of reconstructed MC events passed the event selection; Centrality (FT0C %); Counts", HistType::kTH1D, {centFT0CAxis}); + hRecoCentralityColvsMultiplicityRecoEta05 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta05", "Correlation between FT0C centrality and charged particle multiplicity in reconstructed MC events passed the event selection; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hRecoCentralityColvsMultiplicityRecoEta08 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta08", "Correlation between FT0C centrality and charged particle multiplicity in reconstructed MC events passed the event selection; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hRecoCentralityColvsImpactParamReco = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsImpactParamReco", "Correlation between FT0C centrality and impact parameter in reconstructed MC events passed the event selection; Impact Parameter (b); Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); + hRecoCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in reconstructed MC events passed the event selection; FT0C (%); FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); // Information of generated 3HL in generated events hGen3HLBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLBeforeEvtSel", "3HL generated #it{p}_{T} distribution in all gen evt;#it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); hGen3HLvsImpactParameterBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in all gen evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); hGen3HLvsMultiplicityGenEta05BeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05BeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); hGen3HLvsMultiplicityGenEta08BeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta08BeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.8", HistType::kTH2D, {ptAxis, multAxis}); hGen3HLvsMultiplicityFT0CBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityFT0CBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and FT0C multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); FT0C Multiplicity", HistType::kTH2D, {ptAxis, binsFT0CMultAxis}); - // Information of generated 3HL in generated events with at least one rec. event + // Information of generated 3HL in generated events with at least one rec. event and passed the event selection hGen3HLAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLAfterSel", "3HL generated #it{p}_{T} distribution in gen. evts with at least one rec. evt; #it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); hGen3HLvsImpactParameterAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterAfterSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); hGen3HLvsMultiplicityGenEta05AfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05AfterSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); @@ -1081,29 +1088,36 @@ struct hyperRecoTask { // Define the generated events with at least one reconstructed event bool atLeastOneRecoEvt = false; auto centralityFT0C = -999.; + int biggestNContribs = -1; for (auto const& col : collisions) { if (!passEvtSel(col)) { continue; } - centralityFT0C = col.centFT0C(); + // In case of multiple reconstructed collisions associated to the same generated one, only consider the one with the biggest number of contributors + if (biggestNContribs < col.numContrib()) { + biggestNContribs = col.numContrib(); + centralityFT0C = col.centFT0C(); + } atLeastOneRecoEvt = true; + hImpactParamReco->Fill(mcCollision.impactParameter()); + hRecoCentrality->Fill(col.centFT0C()); + hRecoCentralityColvsMultiplicityRecoEta05->Fill(col.centFT0C(), mcCollision.multMCNParticlesEta05()); + hRecoCentralityColvsMultiplicityRecoEta08->Fill(col.centFT0C(), mcCollision.multMCNParticlesEta08()); + hRecoCentralityColvsImpactParamReco->Fill(col.centFT0C(), mcCollision.impactParameter()); + hRecoCentralityColvsFT0Cmultiplicity->Fill(col.centFT0C(), mcCollision.multMCFT0C()); } - hGenCentralityColvsMultiplicityGenEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); - hGenCentralityColvsMultiplicityGenEta08->Fill(centralityFT0C, mcCollision.multMCNParticlesEta08()); - hGenCentralityColvsImpactParamGen->Fill(centralityFT0C, mcCollision.impactParameter()); - hGenCentralityColvsFT0Cmultiplicity->Fill(centralityFT0C, mcCollision.multMCFT0C()); - if (atLeastOneRecoEvt) { hEvtMC->Fill(2); hGenEventsNchEta05->Fill(mcCollision.multMCNParticlesEta05(), 1); hGenEventsNchEta08->Fill(mcCollision.multMCNParticlesEta08(), 1); - hImpactParamReco->Fill(mcCollision.impactParameter()); - hRecoCentralityColvsMultiplicityRecoEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); - hRecoCentralityColvsMultiplicityRecoEta08->Fill(centralityFT0C, mcCollision.multMCNParticlesEta08()); - hRecoCentralityColvsImpactParamReco->Fill(centralityFT0C, mcCollision.impactParameter()); - hRecoCentralityColvsFT0Cmultiplicity->Fill(centralityFT0C, mcCollision.multMCFT0C()); + hImpactParamGenOneReco->Fill(mcCollision.impactParameter()); + hGenOneRecoCentrality->Fill(centralityFT0C); + hGenCentralityColvsMultiplicityGenEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); + hGenCentralityColvsMultiplicityGenEta08->Fill(centralityFT0C, mcCollision.multMCNParticlesEta08()); + hGenCentralityColvsImpactParamGen->Fill(centralityFT0C, mcCollision.impactParameter()); + hGenCentralityColvsFT0Cmultiplicity->Fill(centralityFT0C, mcCollision.multMCFT0C()); } // Construct the H3L 4-vector based on the generated daugthers identification by PDG ROOT::Math::PxPyPzMVector daugh1, daugh2, mother; From 8d06289089f92501fd5f5d9cb240727ee35db4fa Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 13:05:53 +0200 Subject: [PATCH 155/449] [Common] remove unnecessary N (#16232) --- Common/Core/RecoDecay.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index 8d62822d68d..be50d7831ab 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -284,7 +284,7 @@ struct RecoDecay { /// \param posSV {x, y, z} position of the secondary vertex /// \param mom {x, y, z} momentum array /// \return cosine of pointing angle in {r, z} - template + template static double cpaRZ(const T& posPV, const U& posSV, const std::array& mom) { // CPARZ = (r . pz)/(|r| |pz|) From c25ce5872f78798e622cf09b078f57915cde8992 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Wed, 13 May 2026 13:22:47 +0200 Subject: [PATCH 156/449] [PWGLF] Fix bug in v0 loop for MC (#16233) --- PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx index 33561ee14cd..b557053295c 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -283,6 +283,7 @@ struct lambdaspincorrelation { using EventCandidates = soa::Filtered>; using AllTrackCandidates = soa::Join; using ResoV0s = aod::V0Datas; + Preslice perCollisionV0s = aod::v0data::collisionId; using EventCandidatesMC = soa::Join; using AllTrackCandidatesMC = soa::Join; void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) @@ -555,8 +556,9 @@ struct lambdaspincorrelation { occupancy < cfgCutOccupancy) { histos.fill(HIST("hEvtSelInfo"), 2.5); + auto groupedV0s = V0s.sliceBy(perCollisionV0s, collision.globalIndex()); - for (const auto& v0 : V0s) { + for (const auto& v0 : groupedV0s) { histos.fill(HIST("hEvtSelInfo"), 3.5); // all V0s seen auto [lambdaTag, aLambdaTag, isValid] = getLambdaTagsMC(v0, collision); From 060e4db73b43139402df338e5011736d6c5383e0 Mon Sep 17 00:00:00 2001 From: vojmach <137265951+vojmach@users.noreply.github.com> Date: Wed, 13 May 2026 13:32:00 +0200 Subject: [PATCH 157/449] [PWGCF] RCTflag fix + addition to flowMC (#16221) Co-authored-by: Vojtech Machacek --- PWGCF/Flow/Tasks/flowMc.cxx | 10 ++++++++++ PWGCF/Flow/Tasks/flowTask.cxx | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index e6d883c55a0..847da3642fb 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -20,6 +20,7 @@ #include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -63,6 +64,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -113,6 +115,7 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgRecoEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") O2_DEFINE_CONFIGURABLE(cfgRecoEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgRecoEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking', 'CBT_hadronPID' ") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.6003720411, 0.6152630970, 0.6288860646, 0.6360694031, 0.6409494798, 0.6450540203, 0.6482117301, 0.6512592056, 0.6640008690, 0.6862631416, 0.7005738691, 0.7106567432, 0.7170728333}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-1.007592e-05, -8.932635e-06, -9.114538e-06, -1.054818e-05, -1.220212e-05, -1.312304e-05, -1.376433e-05, -1.412813e-05, -1.289562e-05, -1.050065e-05, -8.635725e-06, -7.380821e-06, -6.201250e-06}, "parameter 1 for track density efficiency correction"}; @@ -177,6 +180,8 @@ struct FlowMc { TRandom3* fRndm = new TRandom3(0); double epsilon = 1e-6; + RCTFlagsChecker rctChecker{"CBT"}; + void init(InitContext&) { ccdb->setURL(ccdbUrl.value); @@ -338,6 +343,9 @@ struct FlowMc { funcV4 = new TF1("funcV4", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); funcV4->SetParameters(0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10); } + if (!cfgEvSelRCTflags.value.empty()) { + rctChecker.init(cfgEvSelRCTflags.value.c_str()); // override initialzation + } } void loadCorrections(uint64_t timestamp) @@ -435,6 +443,8 @@ struct FlowMc { if (cfgRecoEvSel8 && !collision.sel8()) { return 0; } + if (!cfgEvSelRCTflags.value.empty() && !rctChecker(*collision)) + return 0; if (cfgRecoEvkNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index b67a72bd13e..b3e57cdb226 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -323,7 +323,7 @@ struct FlowTask { std::unordered_map gHadronicRate; ctpRateFetcher mRateFetcher; TH2* gCurrentHadronicRate; - RCTFlagsChecker rctChecker{"CentralBarrelTracking"}; + RCTFlagsChecker rctChecker{"CBT"}; // phi-EP correction std::vector funcEff; @@ -759,7 +759,7 @@ struct FlowTask { LOGF(info, "DCAz pt-dependence function for Nch: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAzNSigma][kTrCutNch], cfgFuncParas.cfgDCAzFunc->c_str())); } if (!cfgEvSelRCTflags.value.empty()) { - rctChecker.init(cfgEvSelRCTflags.value.c_str(), true); // override initialzation + rctChecker.init(cfgEvSelRCTflags.value.c_str()); // override initialzation } } From c6b265abee6918fc44359a4344fe098e982fc754 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 15:04:21 +0200 Subject: [PATCH 158/449] [PWGEM/Dilepton] update lepton QC with prefilter (#16234) --- PWGEM/Dilepton/Core/SingleTrackQC.h | 32 +++++++++++++++++++++++++++ PWGEM/Dilepton/Core/SingleTrackQCMC.h | 32 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 487589c4862..015ed26ec32 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -165,6 +165,12 @@ struct SingleTrackQC { o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; @@ -205,6 +211,10 @@ struct SingleTrackQC { o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; @@ -868,9 +878,31 @@ struct SingleTrackQC { o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 2135886fa0e..8c823c9a1b3 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -174,6 +174,12 @@ struct SingleTrackQCMC { o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; @@ -214,6 +220,10 @@ struct SingleTrackQCMC { o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; @@ -1138,6 +1148,28 @@ struct SingleTrackQCMC { o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); From 7585005d91f6b2641c78cd305c38f354b6bd8f1b Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Wed, 13 May 2026 21:16:58 +0800 Subject: [PATCH 159/449] [PWGCF] Add PID Efficiency (#16237) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 358 +++++++++-------------------- 1 file changed, 114 insertions(+), 244 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index ef05ac8adbe..75b748d1523 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -130,14 +130,6 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgAcceptancePath, std::vector, (std::vector{"Users/f/fcui/NUA/NUAREFPartical", "Users/f/fcui/NUA/NUAK0s", "Users/f/fcui/NUA/NUALambda", "Users/f/fcui/NUA/NUAXi", "Users/f/fcui/NUA/NUAOmega"}), "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") - O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") - - O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") - O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") - - O2_DEFINE_CONFIGURABLE(cfgNUEOption, int, 1, "do NUE, 1: use 1D eff, 2: Using Eff(pt, cent), 3: use pid 1D eff, 4: use pid 2D eff, other: dont do NUE") } correctionPathOpts; O2_DEFINE_CONFIGURABLE(cfgRunNumbers, std::vector, (std::vector{544095, 544098, 544116, 544121, 544122, 544123, 544124}), "Preconfigured run numbers") @@ -154,7 +146,6 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug"); O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO"); O2_DEFINE_CONFIGURABLE(cfgCheck2MethodDiff, bool, false, "check difference between v2' && v2''"); - O2_DEFINE_CONFIGURABLE(cfgUseITSOnly4MeanPt, bool, false, "use ITS only to calculate mean pt"); O2_DEFINE_CONFIGURABLE(cfgClosureTest, int, 0, "choose (val) percent particle from charged to pass Pion PID selection"); } switchsOpts; @@ -323,8 +314,7 @@ struct PidFlowPtCorr { // graphs for NUE / NUA std::vector mAcceptance; - std::vector mEfficiency; - std::vector mEfficiency4ITSOnly; + std::vector mEfficiency; bool correctionsLoaded = false; @@ -413,6 +403,13 @@ struct PidFlowPtCorr { registry.add("hMultTPC", "", {HistType::kTH1D, {cfgaxisNch}}); registry.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); registry.add("hPt", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtCorr", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtPi", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtCorrPi", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtKa", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtCorrKa", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtPr", "", {HistType::kTH1D, {cfgaxisPt}}); + registry.add("hPtCorrPr", "", {HistType::kTH1D, {cfgaxisPt}}); registry.add("hNTracksPVvsCentrality", "", {HistType::kTH2D, {{5000, 0, 5000}, axisMultiplicity}}); registry.add("hNchUnCorrectedVSNchCorrected", "", {HistType::kTH2D, {cfgaxisNch, cfgaxisNch}}); @@ -460,7 +457,6 @@ struct PidFlowPtCorr { registry.add("correction/hPtCentMcRec", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); registry.add("correction/hPtCentMcGen", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); // ITS only - registry.add("correction/hPtCentMcRec4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); // hist for Pi eff registry.add("correction/hPtCentMcRecPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); @@ -479,8 +475,6 @@ struct PidFlowPtCorr { registry.add("ptSpectra/hCentEventCountMcGen", "", {HistType::kTH1D, {axisMultiplicity}}); registry.add("ptSpectra/hCentEventCountMcRec", "", {HistType::kTH1D, {axisMultiplicity}}); - registry.add("ptSpectra/hPtCentData4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); - registry.add("c22PrimeVsc22/Pi", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); registry.add("c22PrimeVsc22/Ka", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); registry.add("c22PrimeVsc22/Pr", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); @@ -1372,112 +1366,30 @@ struct PidFlowPtCorr { // here needs to load 2 NUE graph selected from 6 ccdb path /// @note when using eff 2D, convert TH1* to (TH2D *) // pid eff is not available now... - std::vector effPath1D = correctionPathOpts.cfgEfficiencyPath.value; - std::vector effPath2D = correctionPathOpts.cfgEfficiency2DPath.value; - std::vector effPathPid = correctionPathOpts.cfgPidEfficiencyPath.value; - - std::vector effPath1D4ITSOnly = correctionPathOpts.cfgEfficiencyPath4ITSOnly.value; - std::vector effPath2D4ITSOnly = correctionPathOpts.cfgEfficiency2DPath4ITSOnly.value; - std::vector effPathPid4ITSOnly = correctionPathOpts.cfgPidEfficiencyPath4ITSOnly.value; - - switch (correctionPathOpts.cfgNUEOption.value) { - case 1: // use 1D eff - // load 1d eff for global track - if (effPath1D.size() != static_cast(1)) { - LOGF(warning, "eff path 1d size != 1, skip eff 1d load"); - break; - } - mEfficiency.push_back(ccdb->getForTimeStamp(effPath1D[0], timestamp)); - if (mEfficiency.size() == static_cast(1)) { - LOGF(info, "Loaded efficiency histogram"); - } else { - LOGF(fatal, "Could not load efficiency histogram"); - } - // end load 1d eff for global track - - // load 1d eff for ITS only - if (effPath1D4ITSOnly.size() != static_cast(1)) { - LOGF(warning, "eff path for its 1d size != 1, skip its eff 1d load"); - break; - } - mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath1D4ITSOnly[0], timestamp)); - if (mEfficiency4ITSOnly.size() == static_cast(1)) { - LOGF(info, "Loaded ITS only efficiency histogram"); - } else { - LOGF(fatal, "Could not load ITS only efficiency histogram"); - } - // end load 1d eff for its only - - break; - // end use 1d eff - - case 2: // Use 2D eff - // load 2d eff for global track - if (effPath2D.size() != static_cast(1)) { - LOGF(warning, "eff path 2d size != 1, skip eff 2d load"); - break; - } - mEfficiency.push_back(ccdb->getForTimeStamp(effPath2D[0], timestamp)); - if (mEfficiency.size() == static_cast(1)) { - LOGF(info, "Loaded 2D efficiency histogram"); - } else { - LOGF(fatal, "Could not load 2D efficiency histogram"); - } - // end load 2d eff for global track - - // load 2d eff for ITS only - if (effPath2D4ITSOnly.size() != static_cast(1)) { - LOGF(warning, "eff path for its 2d size != 1, skip its eff 2d load"); - break; - } - mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath2D4ITSOnly[0], timestamp)); - if (mEfficiency4ITSOnly.size() == static_cast(1)) { - LOGF(info, "Loaded ITS only 2D efficiency histogram"); - } else { - LOGF(fatal, "Could not load ITS only 2D efficiency histogram"); - } - // end load 2d eff for its only - - break; - // end use 2d eff - - case 3: // use pid 1D eff - // load pid 1d eff for ITS + global track - if (effPathPid.size() != static_cast(3)) { - LOGF(warning, "eff path pid 1d size != 3, skip pid eff 1d load"); - break; - } - for (std::size_t i = 0; i < NSpecies; i++) { - mEfficiency.push_back(ccdb->getForTimeStamp(effPathPid[i], timestamp)); - } - if (mEfficiency.size() == static_cast(3)) { - LOGF(info, "Loaded PID efficiency histogram"); - } else { - LOGF(fatal, "Could not load PID efficiency histogram"); - } - // end load pid 1d eff for ITS + global track + // Load NUE (PID Efficiency) + std::vector effPath = correctionPathOpts.cfgEfficiencyPath.value; - // load pid 1d eff for ITS only - if (effPathPid4ITSOnly.size() != static_cast(3)) { - LOGF(warning, "eff path for its pid 1d size != 3, skip its pid eff 1d load"); - break; - } - for (std::size_t i = 0; i < NSpecies; i++) { - mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPathPid4ITSOnly[i], timestamp)); - } - if (mEfficiency4ITSOnly.size() == static_cast(3)) { - LOGF(info, "Loaded ITS only PID efficiency histogram"); - } else { - LOGF(fatal, "Could not load ITS only PID efficiency histogram"); - } - // end load pid 1d eff for its only + if (effPath.size() == static_cast(nspecies)) { + for (int i = 0; i <= nspecies - 1; i++) { + mEfficiency.push_back(ccdb->getForTimeStamp(effPath[i], timestamp)); + } + if (mEfficiency.size() == static_cast(nspecies)) + LOGF(info, "Loaded PID efficiency histogram"); + else + LOGF(warning, "Could not load PID efficiency histogram"); + } - break; - // end use pid 1d eff + if (effPath.size() == static_cast(totalSpecies)) { + for (int i = 0; i <= totalSpecies - 1; i++) { + mEfficiency.push_back(ccdb->getForTimeStamp(effPath[i], timestamp)); + } + if (mEfficiency.size() == static_cast(totalSpecies)) + LOGF(info, "Loaded PID efficiency histogram * 4"); + else + LOGF(warning, "Could not load PID efficiency histogram * 4"); + } - default: // not do NUE - break; - } // end switch load eff + // End load PID efficiency for ITS + global track correctionsLoaded = true; } @@ -1530,87 +1442,58 @@ struct PidFlowPtCorr { return true; } - /** - * @brief Set the Particle Nue Weight, for global track and ITS track, use different eff path - * - * @tparam TrackObject - * @param weight_nue - * @param track - * @param cent - * @param isGlobalTrack - * @return true weight setted succesfully, note that weight == 1 also return true; - * @return false eff got from graph == 0 - */ template - bool setParticleNUEWeight(float& weight_nue, TrackObject& track, double cent, bool isGlobalTrack) + bool setParticleNUEWeight(float& weight_nue, TrackObject& track, double cent) { - float eff = 1.; - - uint64_t sizeOfEffVec = mEfficiency.size(); - uint64_t sizeOfEffVec4ITS = mEfficiency4ITSOnly.size(); - - TH2* eff2D = 0; - TH2* eff2D4ITS = 0; - - /// @note 1. size check 2. load eff 3. dividezero check - switch (correctionPathOpts.cfgNUEOption.value) { - case 1: // 1d - if (sizeOfEffVec != 1) - break; - if (sizeOfEffVec4ITS != 1) - break; - - if (isGlobalTrack) - eff = mEfficiency[0]->GetBinContent(mEfficiency[0]->FindBin(track.pt())); - else - eff = mEfficiency4ITSOnly[0]->GetBinContent(mEfficiency4ITSOnly[0]->FindBin(track.pt())); - - if (eff == 0.) - return false; - - break; - // end 1d + if (mEfficiency.size() == static_cast(1) || mEfficiency.size() == static_cast(4)) { + TH2* eff2D = mEfficiency[0]; + int ptBin = eff2D->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D->GetYaxis()->FindBin(cent); + float eff = eff2D->GetBinContent(ptBin, centBin); + + if (eff == 0.) { + weight_nue = 1.; + return true; + } + weight_nue = 1. / eff; + } else { + weight_nue = 1.; + } + return true; + } - case 2: // 2d - if (sizeOfEffVec != 1) + template + bool setParticleNUEWeight(float& weight_nue, TrackObject& track, double cent, int pid) + { + if (mEfficiency.size() == static_cast(4)) { + TH2* eff2D = nullptr; + switch (pid) { + case MyParticleType::kPion: + eff2D = mEfficiency[1]; break; - if (sizeOfEffVec4ITS != 1) + case MyParticleType::kKaon: + eff2D = mEfficiency[2]; break; - - eff2D = dynamic_cast(mEfficiency[0]); - eff2D4ITS = dynamic_cast(mEfficiency4ITSOnly[0]); - - if (!eff2D || !eff2D4ITS) { - LOGF(warning, "failed while converting TH1 to TH2! skip eff apply"); + case MyParticleType::kProton: + eff2D = mEfficiency[3]; break; - } - - if (isGlobalTrack) { - int ptBin = eff2D->GetXaxis()->FindBin(track.pt()); - int centBin = eff2D->GetYaxis()->FindBin(cent); - eff = eff2D->GetBinContent(ptBin, centBin); - } else { - int ptBin = eff2D4ITS->GetXaxis()->FindBin(track.pt()); - int centBin = eff2D4ITS->GetYaxis()->FindBin(cent); - eff = eff2D4ITS->GetBinContent(ptBin, centBin); - } - - if (eff == 0.) - return false; - - break; - // end 2d + default: + weight_nue = 1.; + return true; + } - /// @todo add pid NUE eff - case 3: // pid - break; - // end pid + int ptBin = eff2D->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D->GetYaxis()->FindBin(cent); + float eff = eff2D->GetBinContent(ptBin, centBin); - default: - break; + if (eff == 0.) { + weight_nue = 1.; + return true; + } + weight_nue = 1. / eff; + } else { + weight_nue = 1.; } - - weight_nue = 1. / eff; return true; } @@ -1991,13 +1874,6 @@ struct PidFlowPtCorr { for (const auto& track : tracks) { float weff = 1; - // do nue - if (switchsOpts.cfgUseITSOnly4MeanPt.value) - setParticleNUEWeight(weff, track, cent, false); - else - setParticleNUEWeight(weff, track, cent, true); - // end do nue - // track cut ITS only if (!trackSelectedGlobal(track)) continue; @@ -2005,21 +1881,16 @@ struct PidFlowPtCorr { continue; if (!trackSelected4ITS(track)) continue; + if (!track.hasTPC()) + continue; + if (!trackSelected4TPC(track)) + continue; - if (switchsOpts.cfgUseITSOnly4MeanPt.value) { - if (track.hasTPC()) - continue; - } else { - if (!track.hasTPC()) - continue; - if (!trackSelected4TPC(track)) - continue; - } // end track cut its only - if (switchsOpts.cfgOutPutPtSpectra.value) { - registry.fill(HIST("ptSpectra/hPtCentData4ITSOnly"), track.pt(), cent); - } + // do nue + setParticleNUEWeight(weff, track, cent); + // end do nue // calculate ncharged(nch with weight) and pt if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { @@ -2033,26 +1904,30 @@ struct PidFlowPtCorr { // Unified PID logic (configurable) // ------------------------------ int pid = getPidConfigurable(track); + float weffPid = 1.; + // do nue + setParticleNUEWeight(weffPid, track, cent, pid); + // end do nue // Fill PID variables based on unified result if (pid == MyParticleType::kPion) { - nPionWeighted += weff; - nPionSquare += weff * weff; - pionPtSum += weff * track.pt(); - pionPtSumw2 += weff * weff * track.pt(); - pionPtSquareSum += weff * weff * track.pt() * track.pt(); + nPionWeighted += weffPid; + nPionSquare += weffPid * weffPid; + pionPtSum += weffPid * track.pt(); + pionPtSumw2 += weffPid * weffPid * track.pt(); + pionPtSquareSum += weffPid * weffPid * track.pt() * track.pt(); } else if (pid == MyParticleType::kKaon) { - nKaonWeighted += weff; - nKaonSquare += weff * weff; - kaonPtSum += weff * track.pt(); - kaonPtSumw2 += weff * weff * track.pt(); - kaonPtSquareSum += weff * weff * track.pt() * track.pt(); + nKaonWeighted += weffPid; + nKaonSquare += weffPid * weffPid; + kaonPtSum += weffPid * track.pt(); + kaonPtSumw2 += weffPid * weffPid * track.pt(); + kaonPtSquareSum += weffPid * weffPid * track.pt() * track.pt(); } else if (pid == MyParticleType::kProton) { - nProtonWeighted += weff; - nProtonSquare += weff * weff; - protonPtSum += weff * track.pt(); - protonPtSumw2 += weff * weff * track.pt(); - protonPtSquareSum += weff * weff * track.pt() * track.pt(); + nProtonWeighted += weffPid; + nProtonSquare += weffPid * weffPid; + protonPtSum += weffPid * track.pt(); + protonPtSumw2 += weffPid * weffPid * track.pt(); + protonPtSquareSum += weffPid * weffPid * track.pt() * track.pt(); } // else: do nothing (ambiguous or not identified) } @@ -2060,17 +1935,9 @@ struct PidFlowPtCorr { nchCorrectedPassed += weff; nchPassedSelection += 1; - - if (weff == 1. && switchsOpts.cfgDebugMyCode.value) { - LOGF(info, "weff is 1, if nue opt is open and this message appears a lot, check!"); - } } // end pt calculation using ITS only - if (switchsOpts.cfgDebugMyCode.value) { - LOGF(info, Form("its only track num %f", nchPassedSelection)); - } - int totalGlobalTrack = 0; // calculate number of pid particle int numOfPi = 0; @@ -2085,7 +1952,7 @@ struct PidFlowPtCorr { // do NUE && NUA setParticleNUAWeight(wacc, track, vtxz); - setParticleNUEWeight(weff, track, cent, true); + setParticleNUEWeight(weff, track, cent); // end do NUE && NUA if (switchsOpts.cfgDoLocDenCorr.value) { @@ -2132,6 +1999,7 @@ struct PidFlowPtCorr { registry.fill(HIST("hPhicorr"), track.phi(), wacc); registry.fill(HIST("hEta"), track.eta()); registry.fill(HIST("hPt"), track.pt()); + registry.fill(HIST("hPtCorr"), track.pt(), weff); // end fill QA hist // pt spectra @@ -2148,29 +2016,37 @@ struct PidFlowPtCorr { // ------------------------------ int pid = getPidConfigurable(track); float waccPid = 1; + float weffPid = 1; this->setParticleNUAWeight(waccPid, track, vtxz, pid); + this->setParticleNUEWeight(weffPid, track, cent, pid); // Fill GFW and counters based on unified result if (pid == MyParticleType::kPion) { // bitmask 18: 0010010 - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 2); - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 16, wacc * weff); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 2); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 16, wacc * weff); registry.fill(HIST("hPhiPi"), track.phi()); registry.fill(HIST("hPhicorrPi"), track.phi(), waccPid); + registry.fill(HIST("hPtPi"), track.pt()); + registry.fill(HIST("hPtCorrPi"), track.pt(), weffPid); numOfPi++; } else if (pid == MyParticleType::kKaon) { // bitmask 36: 0100100 - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 4); - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 32, wacc * weff); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 4); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 32, wacc * weff); registry.fill(HIST("hPhiKa"), track.phi()); registry.fill(HIST("hPhicorrKa"), track.phi(), waccPid); + registry.fill(HIST("hPtKa"), track.pt()); + registry.fill(HIST("hPtCorrKa"), track.pt(), weffPid); numOfKa++; } else if (pid == MyParticleType::kProton) { // bitmask 72: 1001000 - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 8); - fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weff, 64, wacc * weff); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 8); + fGFW->Fill(track.eta(), 0, track.phi(), waccPid * weffPid, 64, wacc * weff); registry.fill(HIST("hPhiPr"), track.phi()); registry.fill(HIST("hPhicorrPr"), track.phi(), waccPid); + registry.fill(HIST("hPtPr"), track.pt()); + registry.fill(HIST("hPtCorrPr"), track.pt(), weffPid); numOfPr++; } // else: do nothing (ambiguous or not identified) @@ -2626,12 +2502,6 @@ struct PidFlowPtCorr { // end identify particle and fill graph } // end global track, fill rec hist - - /// @note ITS track. fill rec hist - if (track.hasITS() && !track.hasTPC() && trackSelected4ITS(track)) { - registry.fill(HIST("correction/hPtCentMcRec4ITSOnly"), track.pt(), cent); - } - // end ITS track. fill rec hist } // end fill graph } From f4b43f5bd4e92651c8033b8fd6f4ca59831eb141 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Wed, 13 May 2026 21:17:21 +0800 Subject: [PATCH 160/449] [PWGCF] jEPFlowAnalysis.cxx: adding q2 analysis (#16238) --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index ed05872fee3..7e515140b8b 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -111,6 +111,10 @@ struct JEPFlowAnalysis { Configurable cfgShiftPath{"cfgShiftPath", "Users/j/junlee/Qvector/QvecCalib/Shift", "Path for Shift"}; Configurable cfgVertexZ{"cfgVertexZ", 10.0, "Maximum vertex Z selection"}; + Configurable cfgq2analysis{"cfgq2analysis", false, "ese analysis flag"}; + Configurable cfgq2high{"cfgq2high", 10.0, "high q2 selection"}; + Configurable cfgq2low{"cfgq2low", 0.0, "low q2 selection"}; + Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; Configurable cfgRefAName{"cfgRefAName", "TPCPos", "The name of detector for reference A"}; Configurable cfgRefBName{"cfgRefBName", "TPCNeg", "The name of detector for reference B"}; @@ -120,6 +124,7 @@ struct JEPFlowAnalysis { ConfigurableAxis cfgAxisEta{"cfgAxisEta", {20, -1, 1}, ""}; ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {200, -5.0, 5.0}, ""}; + ConfigurableAxis cfgAxisQ2{"cfgAxisQ2", {100, 0, 10}, ""}; ConfigurableAxis cfgAxisCentMC{"cfgAxisCentMC", {5, 0, 100}, ""}; ConfigurableAxis cfgAxisVtxZMC{"cfgAxisVtxZMC", {20, -10, 10}, ""}; @@ -141,6 +146,8 @@ struct JEPFlowAnalysis { float minQvecAmp = 1e-5; float minChg = 0.1; + float q2Mag; + std::vector shiftprofile{}; std::string fullCCDBShiftCorrPath; @@ -284,6 +291,8 @@ struct JEPFlowAnalysis { float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); + q2Mag = std::sqrt(std::pow(qx_shifted[0], 2) + std::pow(qy_shifted[0], 2)); + epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); @@ -292,6 +301,8 @@ struct JEPFlowAnalysis { epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); + epFlowHistograms.fill(HIST("hQ2"), i + 2, cent, q2Mag); + epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, qx_shifted[1] * qy_shifted[0] - qx_shifted[0] * qy_shifted[1]); epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); @@ -315,6 +326,14 @@ struct JEPFlowAnalysis { epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), track.eta(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + + if (cfgq2analysis) { + if (q2Mag > cfgq2high) { + epFlowHistograms.fill(HIST("SPvnxx_q2high"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + } else if (q2Mag < cfgq2low) { + epFlowHistograms.fill(HIST("SPvnxx_q2low"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + } + } } } } @@ -351,6 +370,7 @@ struct JEPFlowAnalysis { AxisSpec axisEta{cfgAxisEta, "eta"}; AxisSpec axisCos{cfgAxisCos, "cos"}; AxisSpec axisQvec{cfgAxisQvec, "Qvec"}; + AxisSpec axisQ2{cfgAxisQ2, "Q2"}; AxisSpec axisCentMC{cfgAxisCentMC, "cent"}; AxisSpec axisVtxZMC{cfgAxisVtxZMC, "vtxz"}; @@ -366,6 +386,8 @@ struct JEPFlowAnalysis { epFlowHistograms.add("EpResDetRefB", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("EpResRefARefB", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); + epFlowHistograms.add("hQ2", "", {HistType::kTH3F, {axisMod, axisCent, axisQ2}}); + epFlowHistograms.add("vncos", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisCos}}); epFlowHistograms.add("vnsin", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisCos}}); @@ -378,6 +400,10 @@ struct JEPFlowAnalysis { epFlowHistograms.add("SPvnxx", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); epFlowHistograms.add("SPvnxy", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); + if (cfgq2analysis) { + epFlowHistograms.add("SPvnxx_q2high", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); + epFlowHistograms.add("SPvnxx_q2low", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); + } epFlowHistograms.add("hCentrality", "", {HistType::kTH1F, {axisCent}}); epFlowHistograms.add("hVertex", "", {HistType::kTH1F, {axisVertex}}); From 3203ba3dfdafc27f33177463b0dbbae2c6dccc48 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Wed, 13 May 2026 16:01:40 +0200 Subject: [PATCH 161/449] [PWGCF] Flow Event Plane Update CCDB timestamp (#16240) --- PWGCF/Flow/Tasks/flowEventPlane.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index aae66f85825..09e4caa8a0a 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -180,6 +180,7 @@ struct SpectatorPlaneTableProducer { // CCDB Configurable cCcdbUrl{"cCcdbUrl", "http://ccdb-test.cern.ch:8080", "url of ccdb"}; Configurable cCcdbPath{"cCcdbPath", "Users/y/ypatley/DFOO", "Path for ccdb-object"}; + Configurable nolaterthan{"nolaterthan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; // Tracks Configurable cTrackMinPt{"cTrackMinPt", 0.1, "p_{T} minimum"}; @@ -238,6 +239,8 @@ struct SpectatorPlaneTableProducer { // Set CCDB url ccdbService->setURL(cCcdbUrl.value); ccdbService->setCaching(true); + ccdbService->setLocalObjectValidityChecking(); + ccdbService->setCreatedNotAfter(nolaterthan.value); // Define axes const AxisSpec axisZDCEnergy{500, 0, 500, "ZD[AC] Signal"}; @@ -379,7 +382,7 @@ struct SpectatorPlaneTableProducer { // Load ZDC gain calibration if (cDoGainCalib) { std::string ccdbPath = static_cast(cCcdbPath) + "/GainCalib" + "/Run" + std::to_string(cRunNum); - auto ccdbObj = ccdbService->getForTimeStamp(ccdbPath, 1); + auto ccdbObj = ccdbService->getForTimeStamp(ccdbPath, nolaterthan.value); CorrectionHistContainer.hGainCalib[0] = reinterpret_cast(ccdbObj->FindObject("hZNASignal")); CorrectionHistContainer.hGainCalib[1] = reinterpret_cast(ccdbObj->FindObject("hZNCSignal")); } @@ -407,7 +410,7 @@ struct SpectatorPlaneTableProducer { std::string ccdbPath = static_cast(cCcdbPath) + "/CorrItr_" + std::to_string(i + 1) + "/Run" + std::to_string(cRunNum); // Get object from CCDB - auto ccdbObject = ccdbService->getForTimeStamp(ccdbPath, 1); + auto ccdbObject = ccdbService->getForTimeStamp(ccdbPath, nolaterthan.value); // Check CCDB Object if (!ccdbObject) { From 5ae53affb7073c2fb316bafaad8c418ea5908791 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 17:02:18 +0200 Subject: [PATCH 162/449] [Common] add cast after #16227 (#16239) --- Common/Core/RecoDecay.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index be50d7831ab..c938280e865 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -288,8 +288,8 @@ struct RecoDecay { static double cpaRZ(const T& posPV, const U& posSV, const std::array& mom) { // CPARZ = (r . pz)/(|r| |pz|) - auto lineDecay = std::array{sqrtSumOfSquares(posSV[0] - posPV[0], posSV[1] - posPV[1]), posSV[2] - posPV[2]}; - auto momRZ = std::array{sqrtSumOfSquares(mom[0], mom[1]), mom[2]}; + auto lineDecay = std::array{sqrtSumOfSquares(posSV[0] - posPV[0], posSV[1] - posPV[1]), static_cast(posSV[2] - posPV[2])}; + auto momRZ = std::array{sqrtSumOfSquares(mom[0], mom[1]), static_cast(mom[2])}; auto cos = dotProd(lineDecay, momRZ) / std::sqrt(mag2(lineDecay) * mag2(momRZ)); if (cos < -1.) { return -1.; From ef87dbd780b3eea3c90ba31ea78271c33bcd08b5 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Wed, 13 May 2026 17:41:14 +0200 Subject: [PATCH 163/449] [PWGCF] only initialise QA histograms when QA filling specified (#16241) --- .../Tasks/flowGenericFramework.cxx | 334 +++++++++--------- 1 file changed, 175 insertions(+), 159 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index d86048f7b10..7135225d44d 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -148,9 +148,11 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A, 4:NTPV, 5:NGlobal, 6:MFT") O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Do correlations as function of Nch") O2_DEFINE_CONFIGURABLE(cfgUseNchCorrection, int, 1, "Use correction for Nch; 0: Use size of tracks table, 1: Use efficiency-corrected Nch values, 2: Use uncorrected Nch values"); - O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, false, "Fill NUA weights") - O2_DEFINE_CONFIGURABLE(cfgRunByRun, bool, false, "Fill histograms on a run-by-run basis") - O2_DEFINE_CONFIGURABLE(cfgFillQA, bool, false, "Fill QA histograms") + O2_DEFINE_CONFIGURABLE(cfgRunByRun, bool, false, "Use run-by-run NUA") + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, false, "Fill NUA weights") + O2_DEFINE_CONFIGURABLE(cfgFillQA, bool, false, "Fill QA histograms") + O2_DEFINE_CONFIGURABLE(cfgFillRunByRunQA, bool, false, "Fill histograms on a run-by-run basis")} cfgFill; O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, false, "Use additional event cut on mult correlations"); O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgUsePID, bool, true, "Enable PID information") @@ -558,51 +560,65 @@ struct FlowGenericFramework { fPtAxis = new TAxis(ptbins, &o2::analysis::gfw::ptbinning[0]); if (doprocessMCGen || doprocessOnTheFly) { - registryQA.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); - registryQA.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.addClone("MCGen/before/", "MCGen/after/"); - registry.add("MCGen/after/pt_centrality_K0_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("MCGen/after/pt_centrality_Lambda_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("MCGen/after/pt_centrality_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("MCGen/after/pt_centrality_proton_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - if (doprocessOnTheFly) - registryQA.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + if (cfgFill.cfgFillQA) { + registryQA.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); + registryQA.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.addClone("MCGen/before/", "MCGen/after/"); + registry.add("MCGen/after/pt_centrality_K0_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_Lambda_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_proton_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + if (doprocessOnTheFly) + registryQA.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + } } if (doprocessMCReco || doprocessData || doprocessRun2) { - registryQA.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); - registryQA.add("trackQA/before/pt_phi", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); - registryQA.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); - registryQA.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track", {HistType::kTH1D, {{100, 0., 50.}}}); - registryQA.add("trackQA/before/nTPCClusters", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); - registryQA.add("trackQA/before/nITSClusters", "Number of found ITS clusters", {HistType::kTH1D, {{100, 0, 20}}}); - registryQA.add("trackQA/before/nTPCCrossedRows", "Number of crossed TPC Rows", {HistType::kTH1D, {{100, 40, 180}}}); - - registryQA.addClone("trackQA/before/", "trackQA/after/"); - registryQA.add("trackQA/after/pt_ref", "; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); - registryQA.add("trackQA/after/pt_poi", "; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); - registryQA.add("trackQA/after/Nch_corrected", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); - registryQA.add("trackQA/after/Nch_uncorrected", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); - registryQA.add("trackQA/after/etaNch", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); - registryQA.add("trackQA/after/etaPtPt", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); - registryQA.add("trackQA/after/etaV0Daughters", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); - if (doprocessMCReco) { - registry.add("trackQA/after/pt_centrality_K0_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("trackQA/after/pt_centrality_Lambda_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("trackQA/after/pt_centrality_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); - registry.add("trackQA/after/pt_centrality_proton", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + if (cfgFill.cfgFillQA) { + registryQA.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); + registryQA.add("trackQA/before/pt_phi", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); + registryQA.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); + registryQA.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track", {HistType::kTH1D, {{100, 0., 50.}}}); + registryQA.add("trackQA/before/nTPCClusters", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); + registryQA.add("trackQA/before/nITSClusters", "Number of found ITS clusters", {HistType::kTH1D, {{100, 0, 20}}}); + registryQA.add("trackQA/before/nTPCCrossedRows", "Number of crossed TPC Rows", {HistType::kTH1D, {{100, 40, 180}}}); + + registryQA.addClone("trackQA/before/", "trackQA/after/"); + registryQA.add("trackQA/after/pt_ref", "; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registryQA.add("trackQA/after/pt_poi", "; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registryQA.add("trackQA/after/Nch_corrected", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); + registryQA.add("trackQA/after/Nch_uncorrected", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); + registryQA.add("trackQA/after/etaNch", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); + registryQA.add("trackQA/after/etaPtPt", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); + registryQA.add("trackQA/after/etaV0Daughters", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); + if (doprocessMCReco) { + registry.add("trackQA/after/pt_centrality_K0_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_Lambda_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_proton", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + } + if (!cfgFill.cfgFillRunByRunQA) { + if (cfgUsePID) { + registryQA.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.add("phi_eta_vtxz_ch", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.add("phi_eta_vtxz_pi", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.add("phi_eta_vtxz_ka", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registryQA.add("phi_eta_vtxz_pr", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + } else { + registryQA.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + } + } + registryQA.add("eventQA/before/globalTracks_centT0C", "; FT0C centrality (%); N_{global}", {HistType::kTH2D, {centAxis, nchAxis}}); + registryQA.add("eventQA/before/PVTracks_centT0C", "; FT0C centrality (%); N_{PV}", {HistType::kTH2D, {centAxis, multpvAxis}}); + registryQA.add("eventQA/before/globalTracks_PVTracks", "; N_{PV}; N_{global}", {HistType::kTH2D, {multpvAxis, nchAxis}}); + registryQA.add("eventQA/before/globalTracks_multT0A", "; multT0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registryQA.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {v0aAxis, nchAxis}}); + registryQA.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, v0aAxis}}); + registryQA.add("eventQA/before/multT0C_centT0C", "; multT0C; FT0C centrality (%)", {HistType::kTH2D, {centAxis, t0cAxis}}); + registryQA.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); } - registryQA.add("eventQA/before/centrality", "; centrality (%); Counts", {HistType::kTH1D, {centAxis}}); registryQA.add("eventQA/before/multiplicity", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); - registryQA.add("eventQA/before/globalTracks_centT0C", "; FT0C centrality (%); N_{global}", {HistType::kTH2D, {centAxis, nchAxis}}); - registryQA.add("eventQA/before/PVTracks_centT0C", "; FT0C centrality (%); N_{PV}", {HistType::kTH2D, {centAxis, multpvAxis}}); - registryQA.add("eventQA/before/globalTracks_PVTracks", "; N_{PV}; N_{global}", {HistType::kTH2D, {multpvAxis, nchAxis}}); - registryQA.add("eventQA/before/globalTracks_multT0A", "; multT0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registryQA.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {v0aAxis, nchAxis}}); - registryQA.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, v0aAxis}}); - registryQA.add("eventQA/before/multT0C_centT0C", "; multT0C; FT0C centrality (%)", {HistType::kTH2D, {centAxis, t0cAxis}}); - registryQA.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); registryQA.addClone("eventQA/before/", "eventQA/after/"); registryQA.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{15, 0.5, 15.5}}}); registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(FilteredEvent, "Filtered event"); @@ -621,33 +637,22 @@ struct FlowGenericFramework { registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(MultCuts, "after Mult cuts"); registryQA.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(TrackCent, "has track + within cent"); - if (!cfgRunByRun) { - if (cfgUsePID) { - registryQA.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.add("phi_eta_vtxz_ch", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.add("phi_eta_vtxz_pi", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.add("phi_eta_vtxz_ka", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - registryQA.add("phi_eta_vtxz_pr", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - } else { - registryQA.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); - } - } - AxisSpec axisK0Mass = {resoSwitchVals[MassBins][K0], resoCutVals[MassMin][K0], resoCutVals[MassMax][K0]}; AxisSpec axisLambdaMass = {resoSwitchVals[MassBins][Lambda], resoCutVals[MassMin][Lambda], resoCutVals[MassMax][Lambda]}; // QA histograms for V0s if (resoSwitchVals[UseParticle][K0]) { - registryQA.add("K0/PiPlusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("K0/PiMinusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("K0/PiPlusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("K0/PiMinusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("K0/hK0Phi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("K0/hK0Eta", "", {HistType::kTH1D, {etaAxis}}); - registryQA.add("K0/hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, ptAxis, nchAxis}}}); - registryQA.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); - registryQA.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); - + if (cfgFill.cfgFillQA) { + registryQA.add("K0/PiPlusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("K0/PiMinusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("K0/PiPlusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("K0/PiMinusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("K0/hK0Phi", "", {HistType::kTH1D, {phiAxis}}); + registryQA.add("K0/hK0Eta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("K0/hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, ptAxis, nchAxis}}}); + registryQA.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); + registryQA.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); + } registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate, "K0 candidates"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); @@ -664,23 +669,24 @@ struct FlowGenericFramework { } if (resoSwitchVals[UseParticle][Lambda]) { - registryQA.add("Lambda/PrPlusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("Lambda/PiMinusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("Lambda/PrPlusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("Lambda/PiMinusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("Lambda/hLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("Lambda/hLambdaEta", "", {HistType::kTH1D, {etaAxis}}); - registryQA.add("Lambda/hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); - registryQA.add("Lambda/PiPlusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("Lambda/PrMinusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); - registryQA.add("Lambda/PiPlusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("Lambda/PrMinusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); - registryQA.add("Lambda/hAntiLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); - registryQA.add("Lambda/hAntiLambdaEta", "", {HistType::kTH1D, {etaAxis}}); - registryQA.add("Lambda/hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); - registryQA.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); - registryQA.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); - + if (cfgFill.cfgFillQA) { + registryQA.add("Lambda/PrPlusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("Lambda/PiMinusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("Lambda/PrPlusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("Lambda/PiMinusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("Lambda/hLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); + registryQA.add("Lambda/hLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("Lambda/hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); + registryQA.add("Lambda/PiPlusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("Lambda/PrMinusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registryQA.add("Lambda/PiPlusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("Lambda/PrMinusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registryQA.add("Lambda/hAntiLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); + registryQA.add("Lambda/hAntiLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registryQA.add("Lambda/hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); + registryQA.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); + registryQA.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); + } registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate, "Lambda candidates"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); @@ -1100,7 +1106,7 @@ struct FlowGenericFramework { return false; } registryQA.fill(HIST("eventQA/eventSel"), TVXinTRD); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(TVXinTRD); } // Cut on event selection flags @@ -1110,7 +1116,7 @@ struct FlowGenericFramework { if (!collision.selection_bit(cut.flag)) return false; registryQA.fill(HIST("eventQA/eventSel"), cut.histBin); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(cut.histBin); } // Cut on vertex @@ -1166,7 +1172,7 @@ struct FlowGenericFramework { if (!(cfgMultCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) > fMultGlobalT0ACutHigh->Eval(multTrk)) return false; registryQA.fill(HIST("eventQA/eventSel"), MultCuts); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(MultCuts); return true; } @@ -1185,11 +1191,11 @@ struct FlowGenericFramework { phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle phimodn = fmod(phimodn, o2::constants::math::PI / 9.0); - if (cfgFillQA) + if (cfgFill.cfgFillQA) registryQA.fill(HIST("trackQA/before/pt_phi"), track.pt(), phimodn); if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt())) return false; // reject track - if (cfgFillQA) + if (cfgFill.cfgFillQA) registryQA.fill(HIST("trackQA/after/pt_phi"), track.pt(), phimodn); } if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgTrackCuts.cfgDCAxyNSigma / 7. * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1)))) @@ -1221,7 +1227,7 @@ struct FlowGenericFramework { double ptpidmaxs[] = {o2::analysis::gfw::ptpoiup, o2::analysis::gfw::ptpoiup, 6.0, 6.0}; // max pt for ch, pi, ka, pr bool withinPtPOI = (ptpidmins[pid_index] < track.pt()) && (track.pt() < ptpidmaxs[pid_index]); // within POI pT range bool withinPtRef = (o2::analysis::gfw::ptreflow < track.pt()) && (track.pt() < o2::analysis::gfw::ptrefup); // within RF pT range - if (cfgRunByRun) { + if (cfgFill.cfgFillRunByRunQA) { if (withinPtRef && !pid_index) th3sList[run][NUAref]->Fill(track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow if (withinPtPOI) @@ -1247,7 +1253,7 @@ struct FlowGenericFramework { } } } else { - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th3sList[run][NUAref]->Fill(track.phi(), track.eta(), vtxz); else registryQA.fill(HIST("phi_eta_vtxz_ref"), track.phi(), track.eta(), vtxz); @@ -1257,6 +1263,7 @@ struct FlowGenericFramework { void createRunByRunHistograms(const int run) { + LOGF(info, "Creating histograms for run %d", run); AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, cfgEta->first, cfgEta->second, "#eta"}; @@ -1270,18 +1277,22 @@ struct FlowGenericFramework { histos[VtxZ] = registryQA.add(Form("%d/vtxz", run), "", {HistType::kTH1D, {vtxAxis}}); histos[Mult] = registryQA.add(Form("%d/mult", run), "", {HistType::kTH1D, {nchAxis}}); histos[Cent] = registryQA.add(Form("%d/cent", run), "", {HistType::kTH1D, {centAxis}}); - histos[EventSel] = registryQA.add(Form("%d/eventSel", run), "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); - histos[EventSel]->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos[EventSel]->GetXaxis()->SetBinLabel(2, "sel8"); - histos[EventSel]->GetXaxis()->SetBinLabel(3, "occupancy"); - histos[EventSel]->GetXaxis()->SetBinLabel(4, "TVXinTRD"); - histos[EventSel]->GetXaxis()->SetBinLabel(5, "NoSameBunchPileup"); - histos[EventSel]->GetXaxis()->SetBinLabel(6, "IsGoodZvtxFT0vsPV"); - histos[EventSel]->GetXaxis()->SetBinLabel(7, "NoCollInTimeRangeStandard"); - histos[EventSel]->GetXaxis()->SetBinLabel(8, "IsVertexITSTPC"); - histos[EventSel]->GetXaxis()->SetBinLabel(9, "IsGoodITSLayersAll"); - histos[EventSel]->GetXaxis()->SetBinLabel(10, "after Mult cuts"); - histos[EventSel]->GetXaxis()->SetBinLabel(11, "has track + within cent"); + histos[EventSel] = registryQA.add(Form("%d/eventSel", run), "Number of Events;; Counts", {HistType::kTH1D, {{15, 0.5, 15.5}}}); + histos[EventSel]->GetXaxis()->SetBinLabel(FilteredEvent, "Filtered event"); + histos[EventSel]->GetXaxis()->SetBinLabel(Sel8, "sel8"); + histos[EventSel]->GetXaxis()->SetBinLabel(Occupancy, "occupancy"); + histos[EventSel]->GetXaxis()->SetBinLabel(TVXinTRD, "TVXinTRD"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoSameBunchPileup, "NoSameBunchPileup"); + histos[EventSel]->GetXaxis()->SetBinLabel(IsGoodZvtxFT0vsPV, "IsGoodZvtxFT0vsPV"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoCollInTimeRangeStandard, "NoCollInTimeRangeStandard"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoCollInRofStandard, "NoCollInRofStandard"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoHighMultCollInPrevRof, "NoHighMultCollInPrevRof"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoTimeFrameBorder, "NoTimeFrameBorder"); + histos[EventSel]->GetXaxis()->SetBinLabel(NoITSROFrameBorder, "NoITSROFrameBorder"); + histos[EventSel]->GetXaxis()->SetBinLabel(IsVertexITSTPC, "IsVertexITSTPC"); + histos[EventSel]->GetXaxis()->SetBinLabel(IsGoodITSLayersAll, "IsGoodITSLayersAll"); + histos[EventSel]->GetXaxis()->SetBinLabel(MultCuts, "after Mult cuts"); + histos[EventSel]->GetXaxis()->SetBinLabel(TrackCent, "has track + within cent"); th1sList.insert(std::make_pair(run, histos)); std::vector> histos3d(TH3NameCount); if (cfgUsePID) { @@ -1415,11 +1426,11 @@ struct FlowGenericFramework { return; if (dt != Gen) { registryQA.fill(HIST("eventQA/eventSel"), TrackCent); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(TrackCent); } float vtxz = collision.posZ(); - if (dt != Gen && cfgRunByRun) { + if (dt != Gen && cfgFill.cfgFillRunByRunQA) { th1sList[run][VtxZ]->Fill(vtxz); th1sList[run][Mult]->Fill(tracks.size()); th1sList[run][Cent]->Fill(centrality); @@ -1470,7 +1481,7 @@ struct FlowGenericFramework { for (const auto& track : tracks) { processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); } - if (dt != Gen) { + if (dt != Gen && cfgFill.cfgFillQA) { registryQA.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); registryQA.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.totaluncorr); } @@ -1491,7 +1502,7 @@ struct FlowGenericFramework { break; } - if (cfgFillWeights) + if (cfgFill.cfgFillWeights) return; fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom); @@ -1641,7 +1652,7 @@ struct FlowGenericFramework { auto mcParticle = track.mcParticle(); if (!mcParticle.isPhysicalPrimary()) return; - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); if (mcParticle.eta() < o2::analysis::gfw::etalow || mcParticle.eta() > o2::analysis::gfw::etaup || mcParticle.pt() < o2::analysis::gfw::ptlow || mcParticle.pt() > o2::analysis::gfw::ptup) @@ -1682,16 +1693,16 @@ struct FlowGenericFramework { histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); } - if (cfgFillWeights) { + if (cfgFill.cfgFillWeights) { fillWeights(mcParticle, vtxz, 0, run); } else { fillPtSums(track, vtxz); fillGFW(mcParticle, vtxz, pidIndex, densitycorrections); } - if (cfgFillQA) { + if (cfgFill.cfgFillQA) { fillTrackQA(track, vtxz); - if (cfgRunByRun) { + if (cfgFill.cfgFillRunByRunQA) { th1sList[run][Phi]->Fill(track.phi()); th1sList[run][Eta]->Fill(track.eta()); } @@ -1700,7 +1711,7 @@ struct FlowGenericFramework { } else if constexpr (framework::has_type_v) { if (!track.isPhysicalPrimary()) return; - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); if (track.eta() < o2::analysis::gfw::etalow || track.eta() > o2::analysis::gfw::etaup || track.pt() < o2::analysis::gfw::ptlow || track.pt() > o2::analysis::gfw::ptup) return; @@ -1727,11 +1738,11 @@ struct FlowGenericFramework { fillPtSums(track, vtxz); fillGFW(track, vtxz, pidIndex, densitycorrections); - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); } else { - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); // Select tracks with nominal cuts always if (!nchSelected(track)) @@ -1763,15 +1774,15 @@ struct FlowGenericFramework { histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); } - if (cfgFillWeights) { + if (cfgFill.cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { fillPtSums(track, vtxz); fillGFW(track, vtxz, pidIndex, densitycorrections); } - if (cfgFillQA) { + if (cfgFill.cfgFillQA) { fillTrackQA(track, vtxz); - if (cfgRunByRun) { + if (cfgFill.cfgFillRunByRunQA) { th1sList[run][Phi]->Fill(track.phi()); th1sList[run][Eta]->Fill(track.eta()); } @@ -1808,7 +1819,8 @@ struct FlowGenericFramework { // Eta cuts on daughter particles to remove self-correlations with correlated observables if (track.eta() < cfgEtaV0Daughters->first || track.eta() > cfgEtaV0Daughters->second) return false; - registryQA.fill(HIST("trackQA/after/etaV0Daughters"), track.eta()); + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("trackQA/after/etaV0Daughters"), track.eta()); return true; } @@ -1867,28 +1879,31 @@ struct FlowGenericFramework { return false; registryQA.fill(HIST("K0/hK0Count"), FillDaughterTrackSelection); - registryQA.fill(HIST("K0/hK0Mass_sparse"), massK0s, v0.pt(), centrality); - registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); - registryQA.fill(HIST("K0/hK0Eta"), v0.eta()); - registryQA.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); - registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); - registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); - registryQA.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); - - registryQA.fill(HIST("K0/hK0s"), 0.5, 1); - if (cfgUsePIDEfficiencies) { - double weffDaughter1 = getEfficiency(postrack, 1); - double weffDaughter2 = getEfficiency(negtrack, 1); - weff = weffDaughter1 * weffDaughter2; - if (weff > 0) - registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); + if (cfgFill.cfgFillQA) { + registryQA.fill(HIST("K0/hK0Mass_sparse"), massK0s, v0.pt(), centrality); + registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); + registryQA.fill(HIST("K0/hK0Eta"), v0.eta()); + registryQA.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); + registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); + registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registryQA.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); + registryQA.fill(HIST("K0/hK0s"), 0.5, 1); + if (cfgUsePIDEfficiencies) { + double weffDaughter1 = getEfficiency(postrack, 1); + double weffDaughter2 = getEfficiency(negtrack, 1); + weff = weffDaughter1 * weffDaughter2; + if (weff > 0) + registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); + } } if (doprocessMCReco) { - registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); + if (cfgFill.cfgFillQA) { + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); + } } return true; @@ -1971,7 +1986,7 @@ struct FlowGenericFramework { } registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelection); - if (isL) { + if (isL && cfgFill.cfgFillQA) { registryQA.fill(HIST("Lambda/hLambdaMass_sparse"), mlambda, v0.pt(), centrality); registryQA.fill(HIST("Lambda/hLambdaPhi"), v0.phi()); registryQA.fill(HIST("Lambda/hLambdaEta"), v0.eta()); @@ -1994,7 +2009,7 @@ struct FlowGenericFramework { registry.fill(HIST("trackQA/after/pt_centrality_proton"), postrack.pt(), centrality); } } - if (isAL) { + if (isAL && cfgFill.cfgFillQA) { registryQA.fill(HIST("Lambda/hAntiLambdaMass_sparse"), mantilambda, v0.pt(), centrality); registryQA.fill(HIST("Lambda/hAntiLambdaPhi"), v0.phi()); registryQA.fill(HIST("Lambda/hAntiLambdaEta"), v0.eta()); @@ -2130,7 +2145,7 @@ struct FlowGenericFramework { if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) registryQA.fill(HIST("trackQA/after/etaNch"), track.eta()); - if (track.eta() > cfgEtaPtPt->first && track.eta() < cfgEtaPtPt->second) + if (track.eta() > cfgEtaPtPt->first && track.eta() < cfgEtaPtPt->second && cfgFill.cfgFillQA) registryQA.fill(HIST("trackQA/after/etaPtPt"), track.eta()); } } @@ -2197,45 +2212,46 @@ struct FlowGenericFramework { LOGF(info, "run = %d", run); if (cfgRunByRun) { if (std::find(runNumbers.begin(), runNumbers.end(), run) == runNumbers.end()) { - LOGF(info, "Creating histograms for run %d", run); - createRunByRunHistograms(run); + if (cfgFill.cfgFillRunByRunQA) + createRunByRunHistograms(run); runNumbers.push_back(run); } else { LOGF(info, "run %d already in runNumbers", run); } - if (!cfgFillWeights) + if (!cfgFill.cfgFillWeights) loadCorrections(bc); } } - if (!cfgFillWeights && !cfgRunByRun) + if (!cfgFill.cfgFillWeights && !cfgRunByRun) loadCorrections(bc); registryQA.fill(HIST("eventQA/eventSel"), 0.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(0.5); if (!collision.sel8()) return; registryQA.fill(HIST("eventQA/eventSel"), 1.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(1.5); - float centrality = getCentrality(collision); if (cfgDoOccupancySel) { int occupancy = collision.trackOccupancyInTimeRange(); - registryQA.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); if (occupancy < 0 || occupancy > cfgOccupancySelection) return; - registryQA.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); } registryQA.fill(HIST("eventQA/eventSel"), 2.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(2.5); - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillEventQA(collision, tracks); registryQA.fill(HIST("eventQA/before/centrality"), centrality); registryQA.fill(HIST("eventQA/before/multiplicity"), tracks.size()); if (!eventSelected(collision, tracks.size(), centrality, run)) return; - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillEventQA(collision, tracks); registryQA.fill(HIST("eventQA/after/centrality"), centrality); registryQA.fill(HIST("eventQA/after/multiplicity"), tracks.size()); @@ -2253,19 +2269,19 @@ struct FlowGenericFramework { int run = bc.runNumber(); if (run != lastRun) { lastRun = run; - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) createRunByRunHistograms(run); } registryQA.fill(HIST("eventQA/eventSel"), 0.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(0.5); if (!collision.sel8()) return; registryQA.fill(HIST("eventQA/eventSel"), 1.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(1.5); const auto centrality = getCentrality(collision); @@ -2278,17 +2294,17 @@ struct FlowGenericFramework { registryQA.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); } registryQA.fill(HIST("eventQA/eventSel"), 2.5); - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) th1sList[run][EventSel]->Fill(2.5); - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillEventQA(collision, tracks); if (!eventSelected(collision, tracks.size(), centrality, run)) return; - if (cfgFillQA) + if (cfgFill.cfgFillQA) fillEventQA(collision, tracks); - if (!cfgFillWeights) + if (!cfgFill.cfgFillWeights) loadCorrections(bc); int defaultMagCut = 99999; auto field = (cfgMagField == defaultMagCut) ? getMagneticField(bc.timestamp()) : cfgMagField; @@ -2324,13 +2340,13 @@ struct FlowGenericFramework { int run = bc.runNumber(); if (run != lastRun) { lastRun = run; - if (cfgRunByRun) + if (cfgFill.cfgFillRunByRunQA) createRunByRunHistograms(run); } if (!collision.sel7()) return; const auto centrality = collision.centRun2V0M(); - if (!cfgFillWeights) + if (!cfgFill.cfgFillWeights) loadCorrections(bc); int defaultMagCut = 99999; auto field = (cfgMagField == defaultMagCut) ? getMagneticField(bc.timestamp()) : cfgMagField; From 989f2615300e401d79d994632a6984026365c976 Mon Sep 17 00:00:00 2001 From: Pravata Panigrahi <158029188+pravatp98@users.noreply.github.com> Date: Wed, 13 May 2026 22:39:15 +0530 Subject: [PATCH 164/449] [PWGCF] Net charge fluctuations3 (#16229) --- .../EbyEFluctuations/Tasks/nchCumulantsId.cxx | 156 ++++++++++++------ 1 file changed, 101 insertions(+), 55 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index 32800bfb680..c10ece98349 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -9,10 +9,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file nchCumulantsId.cxx +/// \file NchCumulantsId.cxx /// \brief Event by Event conserved charges fluctuations /// \author Pravata Panigrahi :: Sadhana Dash(sadhana@phy.iitb.ac.in) +#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -20,28 +21,19 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include "CCDB/BasicCCDBManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/HistogramSpec.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include -#include -#include -#include -#include +#include #include -#include #include using namespace o2; @@ -113,18 +105,14 @@ struct NchCumulantsId { Configurable cfgCutEta{"cfgCutEta", 0.8, "cut for eta"}; Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "max cut for pT"}; Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "min cut for pT"}; - Configurable netChBin{"netChBin", 160, "bins for netch"}; - Configurable netChMax{"netChMax", 80.0, "max for netch"}; - Configurable netChMin{"netChMin", -80.0, "min for netch"}; - Configurable chBins{"chBins", 501, "bins for ch"}; - Configurable chMax{"chMax", 500.0, "max for ch"}; - Configurable chMin{"chMin", -1.0, "min for ch"}; - Configurable midRapMax{"midRapMax", 1000.0, "max for midrapmult"}; - Configurable midRapBins{"midRapBins", 1001, "bins for midrapmult"}; Configurable checkCollPosZMc{"checkCollPosZMc", false, "checkCollPosZMc"}; Configurable flagUnusedVariableError{"flagUnusedVariableError", false, "flagUnusedVariableError"}; + Configurable cfgEvSel01doNoSameBunchPileup{"cfgEvSel01doNoSameBunchPileup", true, "apply kNoSameBunchPileup"}; + Configurable cfgEvSel02doIsGoodZvtxFT0vsPV{"cfgEvSel02doIsGoodZvtxFT0vsPV", true, "apply kIsGoodZvtxFT0vsPV"}; + Configurable cfgEvSel03doIsGoodITSLayersAll{"cfgEvSel03doIsGoodITSLayersAll", true, "apply kIsGoodITSLayersAll"}; + // Configurables for particle Identification Configurable cfgId01CheckVetoCut{"cfgId01CheckVetoCut", false, "cfgId01CheckVetoCut"}; Configurable cfgId02DoElRejection{"cfgId02DoElRejection", true, "cfgId02DoElRejection"}; @@ -133,31 +121,31 @@ struct NchCumulantsId { Configurable cfgId05DoTpcInnerParamId{"cfgId05DoTpcInnerParamId", false, "cfgId05DoTpcInnerParamId"}; Configurable cfgIdPi01ThrPforTOF{"cfgIdPi01ThrPforTOF", 0.7, "cfgIdPi01ThrPforTOF"}; - Configurable cfgIdPi02IdCutTypeLowP{"cfgIdPi02IdCutTypeLowP", 0, "cfgIdPi02IdCutTypeLowP"}; + Configurable cfgIdPi02IdCutTypeLowP{"cfgIdPi02IdCutTypeLowP", 1, "cfgIdPi02IdCutTypeLowP"}; Configurable cfgIdPi03NSigmaTPCLowP{"cfgIdPi03NSigmaTPCLowP", 2.0, "cfgIdPi03NSigmaTPCLowP"}; Configurable cfgIdPi04NSigmaTOFLowP{"cfgIdPi04NSigmaTOFLowP", 2.0, "cfgIdPi04NSigmaTOFLowP"}; Configurable cfgIdPi05NSigmaRadLowP{"cfgIdPi05NSigmaRadLowP", 4.0, "cfgIdPi05NSigmaRadLowP"}; - Configurable cfgIdPi06IdCutTypeHighP{"cfgIdPi06IdCutTypeHighP", 0, "cfgIdPi06IdCutTypeHighP"}; + Configurable cfgIdPi06IdCutTypeHighP{"cfgIdPi06IdCutTypeHighP", 1, "cfgIdPi06IdCutTypeHighP"}; Configurable cfgIdPi07NSigmaTPCHighP{"cfgIdPi07NSigmaTPCHighP", 2.0, "cfgIdPi07NSigmaTPCHighP"}; Configurable cfgIdPi08NSigmaTOFHighP{"cfgIdPi08NSigmaTOFHighP", 2.0, "cfgIdPi08NSigmaTOFHighP"}; Configurable cfgIdPi09NSigmaRadHighP{"cfgIdPi09NSigmaRadHighP", 4.0, "cfgIdPi09NSigmaRadHighP"}; Configurable cfgIdKa01ThrPforTOF{"cfgIdKa01ThrPforTOF", 0.8, "cfgIdKa01ThrPforTOF"}; - Configurable cfgIdKa02IdCutTypeLowP{"cfgIdKa02IdCutTypeLowP", 0, "cfgIdKa02IdCutTypeLowP"}; + Configurable cfgIdKa02IdCutTypeLowP{"cfgIdKa02IdCutTypeLowP", 1, "cfgIdKa02IdCutTypeLowP"}; Configurable cfgIdKa03NSigmaTPCLowP{"cfgIdKa03NSigmaTPCLowP", 2.0, "cfgIdKa03NSigmaTPCLowP"}; Configurable cfgIdKa04NSigmaTOFLowP{"cfgIdKa04NSigmaTOFLowP", 2.0, "cfgIdKa04NSigmaTOFLowP"}; Configurable cfgIdKa05NSigmaRadLowP{"cfgIdKa05NSigmaRadLowP", 4.0, "cfgIdKa05NSigmaRadLowP"}; - Configurable cfgIdKa06IdCutTypeHighP{"cfgIdKa06IdCutTypeHighP", 0, "cfgIdKa06IdCutTypeHighP"}; + Configurable cfgIdKa06IdCutTypeHighP{"cfgIdKa06IdCutTypeHighP", 1, "cfgIdKa06IdCutTypeHighP"}; Configurable cfgIdKa07NSigmaTPCHighP{"cfgIdKa07NSigmaTPCHighP", 2.0, "cfgIdKa07NSigmaTPCHighP"}; Configurable cfgIdKa08NSigmaTOFHighP{"cfgIdKa08NSigmaTOFHighP", 2.0, "cfgIdKa08NSigmaTOFHighP"}; Configurable cfgIdKa09NSigmaRadHighP{"cfgIdKa09NSigmaRadHighP", 4.0, "cfgIdKa09NSigmaRadHighP"}; Configurable cfgIdPr01ThrPforTOF{"cfgIdPr01ThrPforTOF", 0.8, "cfgIdPr01ThrPforTOF"}; - Configurable cfgIdPr02IdCutTypeLowP{"cfgIdPr02IdCutTypeLowP", 0, "cfgIdPr02IdCutTypeLowP"}; + Configurable cfgIdPr02IdCutTypeLowP{"cfgIdPr02IdCutTypeLowP", 1, "cfgIdPr02IdCutTypeLowP"}; Configurable cfgIdPr03NSigmaTPCLowP{"cfgIdPr03NSigmaTPCLowP", 2.0, "cfgIdPr03NSigmaTPCLowP"}; Configurable cfgIdPr04NSigmaTOFLowP{"cfgIdPr04NSigmaTOFLowP", 2.0, "cfgIdPr04NSigmaTOFLowP"}; Configurable cfgIdPr05NSigmaRadLowP{"cfgIdPr05NSigmaRadLowP", 4.0, "cfgIdPr05NSigmaRadLowP"}; - Configurable cfgIdPr06IdCutTypeHighP{"cfgIdPr06IdCutTypeHighP", 0, "cfgIdPr06IdCutTypeHighP"}; + Configurable cfgIdPr06IdCutTypeHighP{"cfgIdPr06IdCutTypeHighP", 1, "cfgIdPr06IdCutTypeHighP"}; Configurable cfgIdPr07NSigmaTPCHighP{"cfgIdPr07NSigmaTPCHighP", 2.0, "cfgIdPr07NSigmaTPCHighP"}; Configurable cfgIdPr08NSigmaTOFHighP{"cfgIdPr08NSigmaTOFHighP", 2.0, "cfgIdPr08NSigmaTOFHighP"}; Configurable cfgIdPr09NSigmaRadHighP{"cfgIdPr09NSigmaRadHighP", 4.0, "cfgIdPr09NSigmaRadHighP"}; @@ -245,16 +233,16 @@ struct NchCumulantsId { const AxisSpec axisTOFNSigma = {200, -10.0, 10.0, "n#sigma_{TOF}"}; const AxisSpec axisTOFExpMom = {200, 0.0f, 10.0f, "#it{p}_{tofExpMom} (GeV/#it{c})"}; - const AxisSpec axisNch(netChBin, netChMin, netChMax, "Net_charge_dN"); - const AxisSpec axisPosCh(chBins, chMin, chMax, "Pos_charge"); - const AxisSpec axisNegCh(chBins, chMin, chMax, "Neg_charge"); - const AxisSpec axisNt(midRapBins, chMin, midRapMax, "Mult_midRap_Nch"); - const AxisSpec axisPrCh(chBins, chMin, chMax, "Pr_charge"); - const AxisSpec axisAPrCh(chBins, chMin, chMax, "APr_charge"); - const AxisSpec axisKaCh(chBins, chMin, chMax, "Ka_charge"); - const AxisSpec axisAKaCh(chBins, chMin, chMax, "AKa_charge"); - const AxisSpec axisPiCh(chBins, chMin, chMax, "Pion_Positive"); - const AxisSpec axisAPiCh(chBins, chMin, chMax, "Pion_Negative"); + const AxisSpec axisNch(100, -50, 50, "Net_charge_dN"); + const AxisSpec axisPosCh(101, -1, 100, "Pos_charge"); + const AxisSpec axisNegCh(101, -1, 100, "Neg_charge"); + const AxisSpec axisNt(201, -1, 200, "Mult_midRap_Nch"); + const AxisSpec axisPrCh(101, -1, 100, "Pr_charge"); + const AxisSpec axisAPrCh(101, -1, 100, "APr_charge"); + const AxisSpec axisKaCh(101, -1, 100, "Ka_charge"); + const AxisSpec axisAKaCh(101, -1, 100, "AKa_charge"); + const AxisSpec axisPiCh(101, -1, 100, "Pion_Positive"); + const AxisSpec axisAPiCh(101, -1, 100, "Pion_Negative"); HistogramConfigSpec qnHist1({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPrCh, axisAPrCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); HistogramConfigSpec qnHist2({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPiCh, axisAPiCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); @@ -894,6 +882,28 @@ struct NchCumulantsId { fillIdentificationQA(hist, track); // Look at Proton } + // template + // void fillGenTrackQA(H& histReg, const T& mcTrack) + // { + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h12_p"), mcTrack.p()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h13_pt"), mcTrack.pt()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h14_eta"), mcTrack.eta()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h15_phi"), mcTrack.phi()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h16_rapidity"), mcTrack.y()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); + // } + // + // template + // void fillRecoTrackQA(H& histReg, const T& track) + // { + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h12_p"), track.p()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h13_pt"), track.pt()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h14_eta"), track.eta()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h15_phi"), track.phi()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h16_rapidity"), track.y()); + // histReg.fill(HIST(HistRegDire2[Mode]) + HIST(PidDire[pidMode]) + HIST("h20_pt_eta"), track.pt(), track.eta()); + // } + template void fillGenTrackQA(HistogramRegistry& r, const TrackType& t) { @@ -1026,12 +1036,27 @@ struct NchCumulantsId { using MyAllTracks = soa::Join; - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; using MyTracksWithMclabels = soa::Join; - using MyCollisionsWithMcLabels = soa::Join; + using MyCollisionsWithMcLabels = soa::Join; + + template + bool isEventSelected(const CollisionType& col) + { + if (cfgEvSel01doNoSameBunchPileup && + !col.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + if (cfgEvSel02doIsGoodZvtxFT0vsPV && + !col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (cfgEvSel03doIsGoodITSLayersAll && + !col.selection_bit(aod::evsel::kIsGoodITSLayersAll)) + return false; + return true; + } // tracks and collision filters Filter col = aod::evsel::sel8 == true; @@ -1081,6 +1106,8 @@ struct NchCumulantsId { if constexpr (analysisType == doDataProcessing) { for (const auto& col : collisions) { + if (!isEventSelected(col)) + continue; nP = 0; nM = 0; nCh = 0; @@ -1171,6 +1198,8 @@ struct NchCumulantsId { LOG(warning) << "No MC collision for this collision, skip..."; continue; } + if (!isEventSelected(col)) + continue; float nP = 0; float nM = 0; float nCh = 0; @@ -1297,6 +1326,8 @@ struct NchCumulantsId { LOG(warning) << "No MC collision for this event, skip..."; continue; } + if (!isEventSelected(col)) + continue; const auto& mcColl = col.mcCollision(); // ---- apply same Vz cut as data/reco ---- @@ -1330,6 +1361,7 @@ struct NchCumulantsId { int pdg = mcTrack.pdgCode(); if (pdg == kPiPlus || pdg == kKPlus || pdg == kProton || pdg == kPositron || pdg == kMuonPlus || pdg == kDeuteron) { + // fillGenTrackQA(genAnalysis, mcTrack); nP++; genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h12_p"), mcTrack.p()); @@ -1339,6 +1371,7 @@ struct NchCumulantsId { genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h16_rapidity"), mcTrack.y()); genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); } else if (pdg == kPiMinus || pdg == kKMinus || pdg == kProtonBar || pdg == kElectron || pdg == kMuonMinus || pdg == -kDeuteron) { + // fillGenTrackQA(genAnalysis, mcTrack); nM++; genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h12_p"), mcTrack.p()); @@ -1350,21 +1383,27 @@ struct NchCumulantsId { } // ----- Pions ----- if (pdg == kPiPlus) { + // fillGenTrackQA(genAnalysis, mcTrack); nPi++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kPiMinus) { + // fillGenTrackQA(genAnalysis, mcTrack); nAPi++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kKPlus) { + // fillGenTrackQA(genAnalysis, mcTrack); nKa++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kKMinus) { + // fillGenTrackQA(genAnalysis, mcTrack); nAKa++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kProton) { + // fillGenTrackQA(genAnalysis, mcTrack); nPr++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kProtonBar) { + // fillGenTrackQA(genAnalysis, mcTrack); nAPr++; fillGenTrackQA(genAnalysis, mcTrack); } @@ -1399,6 +1438,8 @@ struct NchCumulantsId { LOG(warning) << "No MC collision for this collision, skip..."; continue; } + if (!isEventSelected(col)) + continue; auto mcCollision = col.mcCollision(); if (checkCollPosZMc && std::abs(mcCollision.posZ()) > cfgCutPosZ) @@ -1429,6 +1470,7 @@ struct NchCumulantsId { int pdg = mcTrack.pdgCode(); if (pdg == kPiPlus || pdg == kKPlus || pdg == kProton || pdg == kPositron || pdg == kMuonPlus || pdg == kDeuteron) { + // fillGenTrackQA(genAnalysis, mcTrack); nPGen++; genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h12_p"), mcTrack.p()); @@ -1438,6 +1480,7 @@ struct NchCumulantsId { genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h16_rapidity"), mcTrack.y()); genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); } else if (pdg == kPiMinus || pdg == kKMinus || pdg == kProtonBar || pdg == kElectron || pdg == kMuonMinus || pdg == -kDeuteron) { + // fillGenTrackQA(genAnalysis, mcTrack); nMGen++; genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h12_p"), mcTrack.p()); @@ -1447,23 +1490,29 @@ struct NchCumulantsId { genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h16_rapidity"), mcTrack.y()); genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); } - + // ----- Pions ----- if (pdg == kPiPlus) { + // fillGenTrackQA(genAnalysis, mcTrack); nPiGen++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kPiMinus) { + // fillGenTrackQA(genAnalysis, mcTrack); nAPiGen++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kKPlus) { + // fillGenTrackQA(genAnalysis, mcTrack); nKaGen++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kKMinus) { + // fillGenTrackQA(genAnalysis, mcTrack); nAKaGen++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kProton) { + // fillGenTrackQA(genAnalysis, mcTrack); nPrGen++; fillGenTrackQA(genAnalysis, mcTrack); } else if (pdg == kProtonBar) { + // fillGenTrackQA(genAnalysis, mcTrack); nAPrGen++; fillGenTrackQA(genAnalysis, mcTrack); } @@ -1584,23 +1633,20 @@ struct NchCumulantsId { } // purity check - check pdg aginst sign bool purityPion = false; + bool purityKaon = false; + bool purityProton = false; + if (trackIsPion) { if (track.sign() > 0 && pdg == kPiPlus) purityPion = true; if (track.sign() < 0 && pdg == kPiMinus) purityPion = true; - } - - bool purityKaon = false; - if (trackIsKaon) { + } else if (trackIsKaon) { if (track.sign() > 0 && pdg == kKPlus) purityKaon = true; if (track.sign() < 0 && pdg == kKMinus) purityKaon = true; - } - - bool purityProton = false; - if (trackIsProton) { + } else if (trackIsProton) { if (track.sign() > 0 && pdg == kProton) purityProton = true; if (track.sign() < 0 && pdg == kProtonBar) From 50b1943de27abc4a5dfc10f39c23431f5a2daa97 Mon Sep 17 00:00:00 2001 From: a-m-andrushko <96832230+a-m-andrushko@users.noreply.github.com> Date: Wed, 13 May 2026 20:02:10 +0200 Subject: [PATCH 165/449] [PWGCF] FemtoUniverse -- Improve K0Short histogramming. (#16222) --- .../femtoUniversePairTaskTrackV0Helicity.cxx | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx index 60cd704ca06..5b0bdbae389 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -195,6 +195,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { Configurable confLimitHel4{"confLimitHel4", -1.0, "Lowest value of the helicity angle"}; ConfigurableAxis confInvMassMotherpTBinsHel{"confInvMassMotherpTBinsHel", {5, 0, 5}, "pT binning in the pT vs. InvMassMother plot for helicity"}; ConfigurableAxis confInvMassMotherBinsHel{"confInvMassMotherBinsHel", {1000, 0.8, 1.4}, "InvMassMother binning in the pT vs. InvMassMother plot for helicity"}; + Configurable isRealK0Short{"isRealK0Short", true, "If true, fill invariant mass for real K0Short; if false, fill invariant mass as if dealing with Lambda (needed for estimation of K0Short fraction in the Lambda sample)"}; ConfigurableAxis confInvMassK0Short{"confInvMassK0Short", {1000, 0.2, 0.8}, "Invariant mass binning for K0 Short"}; // o2-linter: disable=lowerCamelCase (consistency with generally accepted particle name) } helicityconfigs; @@ -330,10 +331,6 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/Data/hInvMassLambdaHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {helicityconfigs.confInvMassMotherpTBinsHel, helicityconfigs.confInvMassMotherBinsHel}); - thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel1", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel2", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel3", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); - thetaRegistry.add("Theta/Mother/Data/hInvMassK0ShortHel4", " ; M_{K^{0}_{S}}; ;", kTH1F, {helicityconfigs.confInvMassK0Short}); thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMC", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel1", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); thetaRegistry.add("Theta/Mother/MCReco/hInvMassLambdaMCHel2", " ; M_{#Lambda}; ;", kTH1F, {helicityconfigs.confInvMassMotherBinsHel}); @@ -496,7 +493,6 @@ struct FemtoUniversePairTaskTrackV0Helicity { auto negChildMass = pdg->Mass(V0configs.confPDGCodeNegChild); auto posChildBoosted = FemtoUniverseMath::boostPRF(posChild, posChildMass, negChild, negChildMass); auto cosineTheta = (posChildBoosted.Px() * part.px() + posChildBoosted.Py() * part.py() + posChildBoosted.Pz() * part.pz()) / (posChildBoosted.P() * part.p()); - auto invMassK0Short = TMath::Sqrt(TMath::Power(TMath::Sqrt(posChild.p() * posChild.p() + pdg->Mass(V0configs.confPDGCodePosChild) * pdg->Mass(V0configs.confPDGCodePosChild)) + TMath::Sqrt(negChild.p() * negChild.p() + pdg->Mass(V0configs.confPDGCodeNegChild) * pdg->Mass(V0configs.confPDGCodeNegChild)), 2) - TMath::Power(posChild.p() + negChild.p(), 2)); // "fake" K0Short invariant mass to estimate their fraction in the Lambda sample trackHistoPartTwo.fillQA(part); posChildHistos.fillQA(posChild); @@ -512,19 +508,14 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negChild.eta(), cosineTheta); thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); - if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) { + if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel1"), part.pt(), part.mLambda()); - thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel1"), invMassK0Short); - } else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) { + else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel2"), part.pt(), part.mLambda()); - thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel2"), invMassK0Short); - } else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) { + else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel3"), part.pt(), part.mLambda()); - thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel3"), invMassK0Short); - } else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) { + else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassLambdaHel4"), part.pt(), part.mLambda()); - thetaRegistry.fill(HIST("Theta/Mother/Data/hInvMassK0ShortHel4"), invMassK0Short); - } /// Histogramming for MC Reco to calculate fraction of K0Short in the Lambda sample for each helicity bin if constexpr (confIsMC) { @@ -535,25 +526,41 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMC"), part.mKaon()); if (cosineTheta <= helicityconfigs.confLimitHel0 && cosineTheta >= helicityconfigs.confLimitHel1) { - if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) { thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel1"), part.mLambda()); - else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel1"), part.mKaon()); + } else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { + if (helicityconfigs.isRealK0Short) + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel1"), part.mKaon()); + else + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel1"), part.mLambda()); + } } else if (cosineTheta < helicityconfigs.confLimitHel1 && cosineTheta >= helicityconfigs.confLimitHel2) { - if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) { thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel2"), part.mLambda()); - else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel2"), part.mKaon()); + } else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { + if (helicityconfigs.isRealK0Short) + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel2"), part.mKaon()); + else + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel2"), part.mLambda()); + } } else if (cosineTheta < helicityconfigs.confLimitHel2 && cosineTheta >= helicityconfigs.confLimitHel3) { - if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) { thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel3"), part.mLambda()); - else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel3"), part.mKaon()); + } else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { + if (helicityconfigs.isRealK0Short) + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel3"), part.mKaon()); + else + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel3"), part.mLambda()); + } } else if (cosineTheta < helicityconfigs.confLimitHel3 && cosineTheta >= helicityconfigs.confLimitHel4) { - if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) + if ((part.fdMCParticle()).pdgMCTruth() == kLambda0) { thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassLambdaMCHel4"), part.mLambda()); - else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) - thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel4"), part.mKaon()); + } else if ((part.fdMCParticle()).pdgMCTruth() == kK0Short) { + if (helicityconfigs.isRealK0Short) + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel4"), part.mKaon()); + else + thetaRegistry.fill(HIST("Theta/Mother/MCReco/hInvMassK0ShortMCHel4"), part.mLambda()); + } } } } From 06d2a6b93e8acfaf7a91540ac8242bcf70db4345 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 20:29:09 +0200 Subject: [PATCH 166/449] [PWGEM/Dilepton] add more variables in taggingHFE.cxx (#16242) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 72 +++++++++++++++--------- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 74 ++++++++++++------------- PWGEM/Dilepton/Utils/SemiCharmTag.h | 9 ++- 3 files changed, 90 insertions(+), 65 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index b332f509bb1..84ba7db9e85 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -202,39 +202,57 @@ DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of namespace emmltrack { DECLARE_SOA_COLUMN(IsMotherFromBeauty, isMotherFromBeauty, bool); //! is b quark included in decay history +DECLARE_SOA_COLUMN(Signed1PtL, signedPtL, float); //! sign/pT of lepton +DECLARE_SOA_COLUMN(EtaL, etaL, float); //! eta of lepton +DECLARE_SOA_COLUMN(PhiL, phiL, float); //! phi of lepton +DECLARE_SOA_COLUMN(ImpParXYL, impParXYL, float); //! impact parameter for lepton in XY plane +DECLARE_SOA_COLUMN(ImpParZL, impParZL, float); //! impact parameter for lepton in Z plane +DECLARE_SOA_COLUMN(ImpParCYYL, impParCYYL, float); //! sigma of impact parameter for lepton in XY +DECLARE_SOA_COLUMN(ImpParCZYL, impParCZYL, float); //! sigma of impact parameter for lepton, correlaion term +DECLARE_SOA_COLUMN(ImpParCZZL, impParCZZL, float); //! sigma of impact parameter for lepton in Z DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); //! pdg code of mother of lepton } // namespace emmltrack DECLARE_SOA_TABLE(EMMLLeptons, "AOD", "EMMLLEPTON", //! o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmlevent::SubGeneratorId, - track::Signed1Pt, track::Eta, - track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, + emmltrack::Signed1PtL, emmltrack::EtaL, + emmltrack::ImpParXYL, emmltrack::ImpParZL, emmltrack::ImpParCYYL, emmltrack::ImpParCZYL, emmltrack::ImpParCZZL, emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother); // iterators using EMMLLepton = EMMLLeptons::iterator; namespace emmllhpair { -DECLARE_SOA_INDEX_COLUMN(EMMLLepton, emmllepton); //! most propable emeventId +DECLARE_SOA_INDEX_COLUMN(EMMLLepton, emmllepton); //! most propable emeventId + +DECLARE_SOA_COLUMN(Signed1PtH, signedPtH, float); //! sign/pT of associated hadron +DECLARE_SOA_COLUMN(PtH, ptH, float); //! pT of associated hadron +DECLARE_SOA_COLUMN(EtaH, etaH, float); //! eta of associated hadron +DECLARE_SOA_COLUMN(PhiH, phiH, float); //! phi of associated hadron DECLARE_SOA_COLUMN(RapidityV0, rapidityV0, float); //! rapidity of associated V0 DECLARE_SOA_COLUMN(RapidityC, rapidityC, float); //! rapidity of associated Cascade -DECLARE_SOA_COLUMN(ImpParHXY, impParHXY, float); //! impact parameter for V0/Cascade in XY plane -DECLARE_SOA_COLUMN(ImpParHZ, impParHZ, float); //! impact parameter for V0/Cascade in Z plane -DECLARE_SOA_COLUMN(ImpParHCYY, impParHCYY, float); //! sigma of impact parameter for V0/Cascade in XY -DECLARE_SOA_COLUMN(ImpParHCZY, impParHCZY, float); //! sigma of impact parameter for V0/Cascade, correlaion term -DECLARE_SOA_COLUMN(ImpParHCZZ, impParHCZZ, float); //! sigma of impact parameter for V0/Cascade in Z +DECLARE_SOA_COLUMN(ImpParXYH, impParXYH, float); //! impact parameter for V0/Cascade in XY plane +DECLARE_SOA_COLUMN(ImpParZH, impParZH, float); //! impact parameter for V0/Cascade in Z plane +DECLARE_SOA_COLUMN(ImpParCYYH, impParCYYH, float); //! sigma of impact parameter for V0/Cascade in XY +DECLARE_SOA_COLUMN(ImpParCZYH, impParCZYH, float); //! sigma of impact parameter for V0/Cascade, correlaion term +DECLARE_SOA_COLUMN(ImpParCZZH, impParCZZH, float); //! sigma of impact parameter for V0/Cascade in Z -DECLARE_SOA_COLUMN(V0CosPA, v0copa, float); //! cosPA of V0 -DECLARE_SOA_COLUMN(V0CosPAXY, v0copaXY, float); //! cosPA of V0 in XY plane +DECLARE_SOA_COLUMN(V0CPA, v0cpa, float); //! cosPA of V0 +DECLARE_SOA_COLUMN(V0CPAXY, v0cpaXY, float); //! cosPA of V0 in XY plane +DECLARE_SOA_COLUMN(V0CPARZ, v0cpaRZ, float); //! cosPA of V0 in XY plane -DECLARE_SOA_COLUMN(CascCosPA, casccopa, float); //! cosPA of Cascade -DECLARE_SOA_COLUMN(CascCosPAXY, casccopaXY, float); //! cosPA of Cascade in XY plane +DECLARE_SOA_COLUMN(CascCPA, casccpa, float); //! cosPA of Cascade +DECLARE_SOA_COLUMN(CascCPAXY, casccpaXY, float); //! cosPA of Cascade in XY plane +DECLARE_SOA_COLUMN(CascCPARZ, casccpaRZ, float); //! cosPA of Cascade in RZ plane -DECLARE_SOA_COLUMN(Mass, mass, float); //! invariant mass of LH assuming kaon -DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron -DECLARE_SOA_COLUMN(CosPA, cospa, float); //! flight direction of LH pair -DECLARE_SOA_COLUMN(CosPAXY, cospaXY, float); //! flight direction of LH pair in XY +// LH pair variables +DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming pion +DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pT of LH pair +DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron +DECLARE_SOA_COLUMN(CPA, cpa, float); //! cosine of pointing angle of LH pair +DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); //! cosine of pointing angle of LH pair in XY +DECLARE_SOA_COLUMN(CPARZ, cpaRZ, float); //! cosine of pointing angle of LH pair in RZ DECLARE_SOA_COLUMN(Lxy, lxy, float); //! decay length of LH pair DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair @@ -256,12 +274,12 @@ DECLARE_SOA_COLUMN(FoundCommonMother, foundCommonMother, bool); //! decay length DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! emmllhpair::EMMLLeptonId, - track::Signed1Pt, track::Eta, - track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, + emmllhpair::Signed1PtH, emmllhpair::EtaH, + emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); @@ -270,10 +288,10 @@ using EMMLLHPair = EMMLLHPairs::iterator; DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::EMMLLeptonId, - track::Pt, emmllhpair::RapidityV0, - emmllhpair::V0CosPA, emmllhpair::V0CosPAXY, - emmllhpair::ImpParHXY, emmllhpair::ImpParHZ, emmllhpair::ImpParHCYY, emmllhpair::ImpParHCZY, emmllhpair::ImpParHCZZ, - emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, + emmllhpair::PtH, emmllhpair::RapidityV0, + emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, + emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); @@ -282,10 +300,10 @@ using EMMLLV0Pair = EMMLLV0Pairs::iterator; DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCAPAIR", //! emmllhpair::EMMLLeptonId, - track::Pt, emmllhpair::RapidityC, - emmllhpair::CascCosPA, emmllhpair::CascCosPAXY, - emmllhpair::ImpParHXY, emmllhpair::ImpParHZ, emmllhpair::ImpParHCYY, emmllhpair::ImpParHCZY, emmllhpair::ImpParHCZZ, - emmllhpair::Mass, emmllhpair::DcaLH, emmllhpair::CosPA, emmllhpair::CosPAXY, + emmllhpair::PtH, emmllhpair::RapidityC, + emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, + emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index fc3e540fd07..147b73d609b 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -83,8 +83,6 @@ struct taggingHFE { aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFbeta, aod::TOFSignal, aod::TOFEvTime>; using MyTracksWithMCLabel = soa::Join; - // using MyV0s = soa::Join; - // using MyCascades = soa::Join; using MyV0s = soa::Join; using MyCascades = soa::Join; @@ -265,29 +263,23 @@ struct taggingHFE { struct : ConfigurableGroup { std::string prefix = "lKPairCut"; - Configurable cfg_min_mass{"cfg_min_mass", 0, "min mass at SV"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass at SV"}; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 0.1, "max distance between 2 legs"}; + Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; } lKPairCut; struct : ConfigurableGroup { std::string prefix = "lV0PairCut"; - Configurable cfg_min_mass{"cfg_min_mass", 0, "min mass at SV"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass at SV"}; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1e+10, "max distance between 2 legs"}; + Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; } lV0PairCut; struct : ConfigurableGroup { std::string prefix = "lCPairCut"; - Configurable cfg_min_mass{"cfg_min_mass", 0, "min mass at SV"}; - Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass at SV"}; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1e+10, "max distance between 2 legs"}; + Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; } lCPairCut; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -469,8 +461,8 @@ struct taggingHFE { fRegistry.add("V0/hMassAntiLambda_misid", "Anti-Lambda mass;m_{#bar{p}#pi^{+}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); // for cascade - fRegistry.add("Cascade/hPt", "pT of V0;p_{T} (GeV/c)", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Cascade/hYPhi", "rapidity vs. #varphi of V0;#varphi (rad.);rapidity_{#Lambda}", kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); + fRegistry.add("Cascade/hPt", "pT of cascade;p_{T} (GeV/c)", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Cascade/hYPhi", "rapidity vs. #varphi of cascade;#varphi (rad.);rapidity_{#Lambda}", kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); fRegistry.add("Cascade/hCosPA", "cosPA;cosine of pointing angle", kTH1F, {{100, 0.9, 1}}, false); fRegistry.add("Cascade/hDCA2Legs", "distance between 2 legs at PCA;distance between 2 legs (cm)", kTH1F, {{100, 0, 1}}, false); fRegistry.add("Cascade/hV0CosPA", "cosPA of V0 in cascade;cosine of pointing angle", kTH1F, {{100, 0.9, 1}}, false); @@ -1670,7 +1662,7 @@ struct taggingHFE { continue; } - if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { continue; } @@ -1709,7 +1701,7 @@ struct taggingHFE { kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -1733,7 +1725,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { continue; } @@ -1772,7 +1764,7 @@ struct taggingHFE { kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -1805,7 +1797,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (!(lV0PairCut.cfg_min_mass < eV0pair.mass && eV0pair.mass < lV0PairCut.cfg_max_mass) || eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { continue; } @@ -1847,8 +1839,9 @@ struct taggingHFE { v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, + eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -1881,7 +1874,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (!(lV0PairCut.cfg_min_mass < eV0pair.mass && eV0pair.mass < lV0PairCut.cfg_max_mass) || eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { continue; } @@ -1907,8 +1900,9 @@ struct taggingHFE { v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, + eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -1940,7 +1934,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (!(lCPairCut.cfg_min_mass < eCpair.mass && eCpair.mass < lCPairCut.cfg_max_mass) || eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { continue; } @@ -1972,8 +1966,9 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, + eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2005,7 +2000,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (!(lCPairCut.cfg_min_mass < eCpair.mass && eCpair.mass < lCPairCut.cfg_max_mass) || eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { continue; } @@ -2037,8 +2032,9 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, + eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2091,7 +2087,7 @@ struct taggingHFE { continue; } - if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { continue; } @@ -2130,7 +2126,7 @@ struct taggingHFE { kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -2155,7 +2151,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (!(lKPairCut.cfg_min_mass < eKpair.mass && eKpair.mass < lKPairCut.cfg_max_mass) || eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { continue; } @@ -2194,7 +2190,7 @@ struct taggingHFE { kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, + eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -2227,7 +2223,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (!(lV0PairCut.cfg_min_mass < eV0pair.mass && eV0pair.mass < lV0PairCut.cfg_max_mass) || eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { continue; } @@ -2268,8 +2264,9 @@ struct taggingHFE { v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, + eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -2302,7 +2299,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (!(lV0PairCut.cfg_min_mass < eV0pair.mass && eV0pair.mass < lV0PairCut.cfg_max_mass) || eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { continue; } @@ -2328,8 +2325,9 @@ struct taggingHFE { v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, + eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -2361,7 +2359,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (!(lCPairCut.cfg_min_mass < eCpair.mass && eCpair.mass < lCPairCut.cfg_max_mass) || eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { continue; } @@ -2393,8 +2391,9 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, + eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2426,7 +2425,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (!(lCPairCut.cfg_min_mass < eCpair.mass && eCpair.mass < lCPairCut.cfg_max_mass) || eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { continue; } @@ -2458,8 +2457,9 @@ struct taggingHFE { cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), + RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, + eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index b8bfaffb118..75607042ca6 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -37,9 +37,11 @@ namespace o2::aod::pwgem::dilepton::utils struct LHPair { // struct to store electron-hadron pair information float mass{-999.f}; + float pt{-999.f}; float dca2legs{-999.f}; float cospa{-999.f}; float cospaXY{-999.f}; + float cospaRZ{-999.f}; float lxy{-999.f}; float lz{-999.f}; float lxyz{-999.f}; @@ -95,6 +97,7 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); + pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); @@ -139,6 +142,7 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton ROOT::Math::PxPyPzMVector v2(pvec1[0], pvec1[1], pvec1[2], o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); + pair.pt = v12.Pt(); pair.isOK = true; return pair; @@ -195,6 +199,7 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); + pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); @@ -246,8 +251,8 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co } ROOT::Math::PxPyPzMVector v12 = v1 + v2; - pair.mass = v12.M(); + pair.pt = v12.Pt(); pair.isOK = true; return pair; @@ -308,6 +313,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); + pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); @@ -361,6 +367,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); + pair.pt = v12.Pt(); pair.isOK = true; return pair; From 52d99c9b6afd5412cf17f70984ac2f11aea4e964 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 13 May 2026 22:25:11 +0200 Subject: [PATCH 167/449] [PWGEM/Dilepton] add v0,cascade type in taggingHFE (#16245) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 9 ++++++--- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 84ba7db9e85..61bb2b0886b 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -246,6 +246,9 @@ DECLARE_SOA_COLUMN(CascCPA, casccpa, float); //! cosPA of Cascade DECLARE_SOA_COLUMN(CascCPAXY, casccpaXY, float); //! cosPA of Cascade in XY plane DECLARE_SOA_COLUMN(CascCPARZ, casccpaRZ, float); //! cosPA of Cascade in RZ plane +DECLARE_SOA_COLUMN(V0Type, v0Type, uint8_t); //! v0 type, 0 = K0S, 1 = Lambda, 2 = AntiLambda +DECLARE_SOA_COLUMN(CascadeType, cascadeType, uint8_t); //! cascade type, 0 = XiMunus, 1 = OmegaMinus + // LH pair variables DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming pion DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pT of LH pair @@ -287,7 +290,7 @@ DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! using EMMLLHPair = EMMLLHPairs::iterator; DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! - emmllhpair::EMMLLeptonId, + emmllhpair::EMMLLeptonId, emmllhpair::V0Type, emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, @@ -299,8 +302,8 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! using EMMLLV0Pair = EMMLLV0Pairs::iterator; DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCAPAIR", //! - emmllhpair::EMMLLeptonId, - emmllhpair::PtH, emmllhpair::RapidityC, + emmllhpair::EMMLLeptonId, emmllhpair::CascadeType, + emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 147b73d609b..dc084721e7b 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1835,7 +1835,7 @@ struct taggingHFE { continue; } - emmllv0pair(leptonTable.lastIndex(), + emmllv0pair(leptonTable.lastIndex(), 0, v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1896,7 +1896,7 @@ struct taggingHFE { continue; } - emmllv0pair(leptonTable.lastIndex(), + emmllv0pair(leptonTable.lastIndex(), 1, v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -1962,8 +1962,8 @@ struct taggingHFE { continue; } - emmllcascpair(leptonTable.lastIndex(), - cascade.pt(), cascade.rapidity(0), + emmllcascpair(leptonTable.lastIndex(), 0, + cascade.sign() / cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -2028,8 +2028,8 @@ struct taggingHFE { continue; } - emmllcascpair(leptonTable.lastIndex(), - cascade.pt(), cascade.rapidity(2), + emmllcascpair(leptonTable.lastIndex(), 1, + cascade.sign() / cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -2260,7 +2260,7 @@ struct taggingHFE { continue; } - emmllv0pair(leptonTable.lastIndex(), + emmllv0pair(leptonTable.lastIndex(), 0, v0.pt(), v0.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -2321,7 +2321,7 @@ struct taggingHFE { continue; } - emmllv0pair(leptonTable.lastIndex(), + emmllv0pair(leptonTable.lastIndex(), 2, v0.pt(), v0.rapidity(1), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), @@ -2387,8 +2387,8 @@ struct taggingHFE { continue; } - emmllcascpair(leptonTable.lastIndex(), - cascade.pt(), cascade.rapidity(0), + emmllcascpair(leptonTable.lastIndex(), 0, + cascade.sign() / cascade.pt(), cascade.rapidity(0), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), @@ -2453,8 +2453,8 @@ struct taggingHFE { continue; } - emmllcascpair(leptonTable.lastIndex(), - cascade.pt(), cascade.rapidity(2), + emmllcascpair(leptonTable.lastIndex(), 1, + cascade.sign() / cascade.pt(), cascade.rapidity(2), RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), From 2324a6dd6d19d529c66dd68af6c042368b490cc8 Mon Sep 17 00:00:00 2001 From: navneetkumar231295 <71565461+navneetkumar231295@users.noreply.github.com> Date: Thu, 14 May 2026 12:51:44 +0530 Subject: [PATCH 168/449] [PWGLF] To add the event loss and event factor correction (#16235) Co-authored-by: Navneet --- .../Tasks/Resonances/chargedkstaranalysis.cxx | 145 +++++++++++++++++- 1 file changed, 140 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx index e494d017558..e04c58be4d2 100644 --- a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx @@ -19,6 +19,7 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" @@ -79,8 +80,19 @@ struct Chargedkstaranalysis { FT0C = 1, FT0M = 2 }; + enum EvtStep { + kAll = 0, + kZvtx, + kINELgt0, + kAssocReco, + kNSteps + }; + + const int nSteps = static_cast(EvtStep::kNSteps); + SliceCache cache; Preslice perCollision = aod::track::collisionId; + Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; bool currentIsGen = false; struct : ConfigurableGroup { ConfigurableAxis cfgvtxbins{"cfgvtxbins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; @@ -116,6 +128,9 @@ struct Chargedkstaranalysis { int noOfDaughters = 2; } helicityCfgs; + Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", true, "Truth denominator: require INEL>0"}; + Configurable cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", true, "Truth denominator: also require |vtxz|; // using EventCandidates = soa::Join; // using TrackCandidates = soa::Join; @@ -295,7 +310,7 @@ struct Chargedkstaranalysis { // Variable declaration ROOT::Math::PxPyPzEVector beam1{0., 0., -helicityCfgs.beamMomentum, 13600. / 2.}; ROOT::Math::PxPyPzEVector beam2{0., 0., helicityCfgs.beamMomentum, 13600. / 2.}; - + double fMaxPosPV = 1e-2; void init(o2::framework::InitContext&) { centrality = -999; @@ -558,6 +573,18 @@ struct Chargedkstaranalysis { histos.add("EffKstar/recoKstar", "Kstar Reco matched (final all)", HistType::kTH2F, {ptAxis, centAxis}); histos.add("MCReco/hInvmass_Kstar_true", "MC-reco truth-tagged chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); + histos.add("Correction/sigLoss_den", "Gen Kstar (|y|<0.5) in truth class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_den_pri", "Gen primary Kstar (|y|<0.5) in truth class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_num", "Gen Kstar (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_num_pri", "Gen primary Kstar (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/EF_den", "Gen events (truth class)", HistType::kTH1F, {centAxis}); + histos.add("Correction/EF_num", "Reco events (selected events)", HistType::kTH1F, {centAxis}); + histos.add("Correction/hNEventsMCTruth", "hNEventsMCTruth", HistType::kTH1F, {AxisSpec{nSteps, 0.5, nSteps + 0.5, ""}}); + auto hstep = histos.get(HIST("Correction/hNEventsMCTruth")); + hstep->GetXaxis()->SetBinLabel(1, "All"); + hstep->GetXaxis()->SetBinLabel(2, "zvtx"); + hstep->GetXaxis()->SetBinLabel(3, "INEL>0"); + hstep->GetXaxis()->SetBinLabel(4, "Assoc with reco coll"); } ccdb->setURL(cfgURL); @@ -573,7 +600,8 @@ struct Chargedkstaranalysis { std::unordered_set allowedMcIds; std::unordered_map centTruthByAllowed; - + std::unordered_set refClassIds; + std::unordered_map refCentByMcId; float lMultiplicity; template float getCentrality(CollisionType const& collision) @@ -1210,12 +1238,13 @@ struct Chargedkstaranalysis { } PROCESS_SWITCH(Chargedkstaranalysis, processDataME, "Process Event for data without Partitioning", true); - void processMC(soa::Join const&, aod::McParticles const& mcParticles, soa::Join const& events, MCV0Candidates const& v0s, MCTrackCandidates const& tracks) + void processMC(soa::Join const& mccolls, aod::McParticles const& mcParticles, soa::Join const& events, MCV0Candidates const& v0s, MCTrackCandidates const& tracks) { allowedMcIds.clear(); centTruthByAllowed.clear(); - - // To apply event selection and store the collision IDs of reconstructed tracks that pass the selection criteria + refClassIds.clear(); + refCentByMcId.clear(); + // To apply event selection and store the collision IDs of reconstructed events that pass the selection criteria for (const auto& coll : events) { if (!coll.has_mcCollision()) @@ -1252,6 +1281,30 @@ struct Chargedkstaranalysis { allowedMcIds.insert(mcid); centTruthByAllowed.emplace(mcid, lCentrality); } + + // To builds a list of accepted MC collisions ID's for the truth candidates: i.e. the total number of generated events + for (const auto& coll : mccolls) { + bool pass = true; + + if (cfgTruthIncludeZvtx && std::abs(coll.posZ()) >= eventCutCfgs.confEvtZvtx) + pass = false; + + if (pass && cfgTruthUseInelGt0) { + auto partsThisMc = mcParticles.sliceBy(perMCCollision, coll.globalIndex()); // This is to slice all MC particles belonging to the current MC collision. + // To check the INEL > 0 + if (!pwglf::isINELgtNmc(partsThisMc, 0, pdg)) + pass = false; + } + + if (!pass) + continue; + + const auto mcid = coll.globalIndex(); + refClassIds.insert(mcid); + const float lCentrality = coll.centFT0M(); + refCentByMcId.emplace(mcid, lCentrality); + } + // Calculating the generated Kstar for (const auto& part : mcParticles) { currentIsGen = true; @@ -1408,6 +1461,88 @@ struct Chargedkstaranalysis { histos.fill(HIST("MCReco/hInvmass_Kstar_true"), lCentrality, ptreco, lResoKstar.M()); } } + // To calculate the event losses to store the generated KstartPlus --> To check the number of events remains after passing all the event selection criteria for chk892 + for (auto const& part : mcParticles) { + if (!part.has_mcCollision()) + continue; + if (std::abs(part.pdgCode()) != kKstarPlus) + continue; + if (std::abs(part.y()) > kstarCutCfgs.cKstarMaxRap) + continue; + + const auto mcid = part.mcCollisionId(); + if (allowedMcIds.count(mcid) == 0) + continue; + + auto iter = centTruthByAllowed.find(mcid); + if (iter == centTruthByAllowed.end()) + continue; + + const float lCentrality = iter->second; + + histos.fill(HIST("Correction/sigLoss_num"), part.pt(), lCentrality); + if (part.vt() == 0) { + histos.fill(HIST("Correction/sigLoss_num_pri"), part.pt(), lCentrality); + } + } + // To calculate the denominator -> To check the all the events have chk892 + for (auto const& part : mcParticles) { + if (!part.has_mcCollision()) + continue; + if (std::abs(part.pdgCode()) != kKstarPlus) + continue; + if (std::abs(part.y()) > kstarCutCfgs.cKstarMaxRap) + continue; + + const auto mcid = part.mcCollisionId(); + if (refClassIds.count(mcid) == 0) + continue; + + auto iter = refCentByMcId.find(mcid); + if (iter == refCentByMcId.end()) + continue; + + const float lCentrality = iter->second; + + histos.fill(HIST("Correction/sigLoss_den"), part.pt(), lCentrality); + if (part.vt() == 0) { + histos.fill(HIST("Correction/sigLoss_den_pri"), part.pt(), lCentrality); + } + } + // To calculate the event fraction correction + for (const auto& mcid : refClassIds) { + histos.fill(HIST("Correction/EF_den"), refCentByMcId[mcid]); + } + for (const auto& mcid : allowedMcIds) { + auto iter = centTruthByAllowed.find(mcid); + if (iter == centTruthByAllowed.end()) + continue; + + const float lCentrality = iter->second; + histos.fill(HIST("Correction/EF_num"), lCentrality); + } + + for (auto const& mcc : mccolls) { + const auto mcid = mcc.globalIndex(); + + histos.fill(HIST("Correction/hNEventsMCTruth"), 1.0); + + bool passZvtx = true; + if (cfgTruthIncludeZvtx && std::abs(mcc.posZ()) > eventCutCfgs.confEvtZvtx) { + passZvtx = false; + } + if (passZvtx) { + histos.fill(HIST("Correction/hNEventsMCTruth"), 2.0); + + auto partsThisMc = mcParticles.sliceBy(perMCCollision, mcid); + if (pwglf::isINELgtNmc(partsThisMc, 0, pdg)) { + histos.fill(HIST("Correction/hNEventsMCTruth"), 3.0); + } + } + if (allowedMcIds.count(mcid)) { + histos.fill(HIST("Correction/hNEventsMCTruth"), 4.0); + } + } } PROCESS_SWITCH(Chargedkstaranalysis, processMC, "Process Event for MC", false); }; From 7682fd6160d66a949fdb67789bcc043c323b6f99 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 14 May 2026 12:40:41 +0200 Subject: [PATCH 169/449] [PWGEM/Dilepton] update taggingHFE.cxx (#16247) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 3 +- PWGEM/Dilepton/Tasks/associateMCcollision.cxx | 2 +- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 57 +++++++++---------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 61bb2b0886b..dd9001ab964 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -211,13 +211,14 @@ DECLARE_SOA_COLUMN(ImpParCYYL, impParCYYL, float); //! sigma of i DECLARE_SOA_COLUMN(ImpParCZYL, impParCZYL, float); //! sigma of impact parameter for lepton, correlaion term DECLARE_SOA_COLUMN(ImpParCZZL, impParCZZL, float); //! sigma of impact parameter for lepton in Z DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); //! pdg code of mother of lepton +DECLARE_SOA_COLUMN(IsCorrectCollision, isCorrectCollision, bool); //! LH pair is associated to correct collision. } // namespace emmltrack DECLARE_SOA_TABLE(EMMLLeptons, "AOD", "EMMLLEPTON", //! o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmlevent::SubGeneratorId, emmltrack::Signed1PtL, emmltrack::EtaL, emmltrack::ImpParXYL, emmltrack::ImpParZL, emmltrack::ImpParCYYL, emmltrack::ImpParCZYL, emmltrack::ImpParCZZL, - emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother); + emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother, emmltrack::IsCorrectCollision); // iterators using EMMLLepton = EMMLLeptons::iterator; diff --git a/PWGEM/Dilepton/Tasks/associateMCcollision.cxx b/PWGEM/Dilepton/Tasks/associateMCcollision.cxx index 9d66de55cd5..a48141be999 100644 --- a/PWGEM/Dilepton/Tasks/associateMCcollision.cxx +++ b/PWGEM/Dilepton/Tasks/associateMCcollision.cxx @@ -59,7 +59,7 @@ struct associateMCcollision { void runMC(TMCCollisions const& mcCollisions, TCollisions const& collisions, TPreslice const& perMCCollision) { - for (auto& mcCollision : mcCollisions) { + for (const auto& mcCollision : mcCollisions) { auto rec_colls_per_mccoll = collisions.sliceBy(perMCCollision, mcCollision.globalIndex()); fRegistry.fill(HIST("hReccollsPerMCcoll"), rec_colls_per_mccoll.size()); uint32_t maxNumContrib = 0; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index dc084721e7b..893767d09ee 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -238,7 +238,7 @@ struct taggingHFE { Configurable cfg_min_rxy{"cfg_min_rxy", 0.1, "minimum V0 rxy in cascade"}; Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; Configurable cfg_min_dcaxy_bachelor{"cfg_min_dcaxy_bachelor", 0.05, "min dca XY for bachelor in cm"}; - Configurable cfg_min_dcaxy_v0{"cfg_min_dcaxy_v0", 0.05, "min dca XY for V0 in cm"}; + Configurable cfg_min_dcaxy_v0{"cfg_min_dcaxy_v0", 0.0, "min dca XY for V0 in cm"}; } cascadeCut; struct : ConfigurableGroup { @@ -311,7 +311,7 @@ struct taggingHFE { dist01 = std::uniform_real_distribution(0.0f, 1.0f); fitter_eK.setPropagateToPCA(true); - fitter_eK.setMaxR(20.f); + fitter_eK.setMaxR(200.f); fitter_eK.setMinParamChange(1e-3); fitter_eK.setMinRelChi2Change(0.9); fitter_eK.setMaxDZIni(1e9); @@ -321,7 +321,7 @@ struct taggingHFE { fitter_eK.setMatCorrType(matCorr); fitter_eV0.setPropagateToPCA(true); - fitter_eV0.setMaxR(20.f); + fitter_eV0.setMaxR(200.f); fitter_eV0.setMinParamChange(1e-3); fitter_eV0.setMinRelChi2Change(0.9); fitter_eV0.setMaxDZIni(1e9); @@ -331,7 +331,7 @@ struct taggingHFE { fitter_eV0.setMatCorrType(matCorr); fitter_eCascade.setPropagateToPCA(true); - fitter_eCascade.setMaxR(20.f); + fitter_eCascade.setMaxR(200.f); fitter_eCascade.setMinParamChange(1e-3); fitter_eCascade.setMinRelChi2Change(0.9); fitter_eCascade.setMaxDZIni(1e9); @@ -441,6 +441,7 @@ struct taggingHFE { fRegistry.add("Generated/Lc/hsAcc", "pT-#eta acc.;p_{T,l} (GeV/c);p_{T,#Lambda} (GeV/c);#eta_{l};#eta_{#Lambda};", kTHnSparseF, {{100, 0, 10}, {100, 0, 10}, {100, -5, +5}, {100, -5, +5}}, false); fRegistry.add("Electron/hs", "hs;p_{T} (GeV/c);#eta;#varphi (rad.)", kTHnSparseF, {{100, 0, 10}, {40, -1, 1}, {36, 0, 2 * M_PI}}, false); + fRegistry.add("Electron/hDCA", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1, 1}, {200, -1, 1}}, false); fRegistry.add("Electron/hTPCdEdx", "TPC dE/dx vs. pin;p_{in} (GeV/c);TPC dE/dx", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Electron/hTOFbeta", "TOF #beta vs. p;p_{pv} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); fRegistry.addClone("Electron/", "Hadron/"); @@ -1419,6 +1420,7 @@ struct taggingHFE { continue; } + auto mcCollision_from_collision = collision.template mcCollision_as(); fRegistry.fill(HIST("Event/hCollisionCounter"), 0); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; @@ -1471,8 +1473,8 @@ struct taggingHFE { if (mcCollision_ele.getSubGeneratorId() == eventCut.cfgRejectEventGenerator) { continue; } - fRegistry.fill(HIST("Electron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); + fRegistry.fill(HIST("Electron/hDCA"), dcaXY, dcaZ); fRegistry.fill(HIST("Electron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Electron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); @@ -1491,6 +1493,7 @@ struct taggingHFE { if (isSelectedHadron(collision, track, trackParCov, dcaXY, dcaZ)) { // electrons can be included in hadron sample. fRegistry.fill(HIST("Hadron/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); + fRegistry.fill(HIST("Hadron/hDCA"), dcaXY, dcaZ); fRegistry.fill(HIST("Hadron/hTPCdEdx"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Hadron/hTOFbeta"), track.p(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); if (track.sign() > 0) { // K+ @@ -1594,9 +1597,9 @@ struct taggingHFE { continue; } - // if (cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadeCut.cfg_min_dcaxy_v0) { - // continue; - // } + if (std::fabs(cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascadeCut.cfg_min_dcaxy_v0) { + continue; + } fillCascadeHistograms(collision, cascade); @@ -1629,7 +1632,8 @@ struct taggingHFE { auto mcpos = pos.template mcParticle_as(); auto mcMother = mcpos.template mothers_as()[0]; bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; - auto mcCollision = mcpos.template mcCollision_as(); + auto mcCollision_mcpos = mcpos.template mcCollision_as(); + bool isCorrectCollision = mcCollision_mcpos.globalIndex() == mcCollision_from_collision.globalIndex(); bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; // e from prompt J/psi is treated as the same as Z. // e from nonprompt J/psi is treated as the same as B. @@ -1639,9 +1643,13 @@ struct taggingHFE { continue; } - leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), + if ((is_e_from_dy || is_e_from_jpsi) && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } + + leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision_mcpos.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromB, mcMother.pdgCode()); + isMotherFromB, mcMother.pdgCode(), isCorrectCollision); // D0 -> e+ nu_e K-, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonMinusIds) { @@ -1688,10 +1696,6 @@ struct taggingHFE { continue; } - if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary - continue; - } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -1751,10 +1755,6 @@ struct taggingHFE { continue; } - if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary - continue; - } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -2055,7 +2055,8 @@ struct taggingHFE { auto mcele = ele.template mcParticle_as(); auto mcMother = mcele.template mothers_as()[0]; bool isMotherFromB = IsFromBeauty(mcMother, mcParticles) > -1; - auto mcCollision = mcele.template mcCollision_as(); + auto mcCollision_mcele = mcele.template mcCollision_as(); + bool isCorrectCollision = mcCollision_mcele.globalIndex() == mcCollision_from_collision.globalIndex(); bool is_e_from_dy = std::abs(mcMother.pdgCode()) == 23; // virtual photon is Z in simulation. bool is_e_from_jpsi = std::abs(mcMother.pdgCode()) == 443; // e from prompt J/psi is treated as the same as Z. // e from nonprompt J/psi is treated as the same as B. // B+ -> J/psi K+ -> e+ e- K+ @@ -2065,9 +2066,13 @@ struct taggingHFE { continue; } - leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision.getSubGeneratorId(), + if ((is_e_from_dy || is_e_from_jpsi) && dist01(engine) > cfgDownSampling) { // random sampling, if necessary + continue; + } + + leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision_mcele.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromB, mcMother.pdgCode()); + isMotherFromB, mcMother.pdgCode(), isCorrectCollision); for (const auto& kaonId : kaonMinusIds) { auto kaon = tracks.rawIteratorAt(kaonId); @@ -2113,10 +2118,6 @@ struct taggingHFE { continue; } - if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary - continue; - } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; @@ -2177,10 +2178,6 @@ struct taggingHFE { continue; } - if (!foundCommonMother && dist01(engine) > cfgDownSampling) { // random sampling, if necessary - continue; - } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; From 3ae3c03f17cb3f0febba309fe89ef95439a22631 Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Thu, 14 May 2026 13:55:37 +0200 Subject: [PATCH 170/449] [PWGCF] FemtoUniverse: Fix in processFractionsSingleTruth (#16248) --- .../Tasks/femtoUniversePairTaskTrackV0Extended.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 9bb5265f6be..c33d24594a8 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -1690,7 +1690,7 @@ struct FemtoUniversePairTaskTrackV0Extended { } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processFractionsSingleReco, "Process MC data to obtain fractions for V0 and protons particles", false); - void processFractionsSingleTruth(FilteredFDCollision const& col, FemtoRecoParticles const&) + void processFractionsSingleTruth(FilteredFDCollision const& col, FemtoFullParticles const&) { auto groupPartsOne = partsOneMCFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwoMCFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); From 58161cf6f0df6fbde3a2f3e773c58973e1e9ab2d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 14 May 2026 15:18:47 +0200 Subject: [PATCH 171/449] [PWGEM/Dilepton] improve charm and beauty selection in MC (#16249) --- PWGEM/Dilepton/Utils/MCUtilities.h | 57 +++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index d0a9a69df0e..7b28d713aa5 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -80,6 +80,9 @@ bool isCharmonia(T const& track) if (std::abs(track.pdgCode()) < 100) { return false; } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } std::string pdgStr = std::to_string(std::abs(track.pdgCode())); int n = pdgStr.length(); @@ -95,11 +98,22 @@ bool isCharmonia(T const& track) template bool isCharmMeson(T const& track) { + if (std::abs(track.pdgCode()) < 100) { + return false; + } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } + if (isCharmonia(track)) { return false; } - if (400 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 500) { + std::string pdgStr = std::to_string(std::abs(track.pdgCode())); + int n = pdgStr.length(); + int pdg3 = std::stoi(pdgStr.substr(n - 3, 3)); // excited states are included too. + + if (400 < pdg3 && pdg3 < 500) { return true; } else { return false; @@ -109,6 +123,13 @@ bool isCharmMeson(T const& track) template bool isCharmBaryon(T const& track) { + if (std::abs(track.pdgCode()) < 100) { + return false; + } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } + if (4000 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 5000) { return true; } else { @@ -122,6 +143,9 @@ bool isBottomonia(T const& track) if (std::abs(track.pdgCode()) < 100) { return false; } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } std::string pdgStr = std::to_string(std::abs(track.pdgCode())); int n = pdgStr.length(); @@ -137,11 +161,22 @@ bool isBottomonia(T const& track) template bool isBeautyMeson(T const& track) { + if (std::abs(track.pdgCode()) < 100) { + return false; + } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } + if (isBottomonia(track)) { return false; } - if (500 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 600) { + std::string pdgStr = std::to_string(std::abs(track.pdgCode())); + int n = pdgStr.length(); + int pdg3 = std::stoi(pdgStr.substr(n - 3, 3)); // excited states are included too. + + if (500 < pdg3 && pdg3 < 600) { return true; } else { return false; @@ -151,6 +186,13 @@ bool isBeautyMeson(T const& track) template bool isBeautyBaryon(T const& track) { + if (std::abs(track.pdgCode()) < 100) { + return false; + } + if (std::abs(track.pdgCode()) > 1e+9) { + return false; + } + if (5000 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 6000) { return true; } else { @@ -409,14 +451,14 @@ int IsFromBeauty(TMCParticle const& p, TMCParticles const& mcparticles) int motherid = p.mothersIds()[0]; // first mother index auto mp_tmp = mcparticles.iteratorAt(motherid); - if (std::abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 2] == '5' && std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 3] == '5') && std::abs(mp_tmp.pdgCode()) % 2 == 1) { + if (isBottomonia(mp_tmp)) { return -999; // reject bottomonia } while (motherid > -1) { if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed? auto mp = mcparticles.iteratorAt(motherid); - if (std::abs(mp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 3] == '5' || std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 4] == '5')) { + if (isBeautyMeson(mp) || isBeautyBaryon(mp)) { return motherid; } if (mp.has_mothers()) { @@ -431,7 +473,6 @@ int IsFromBeauty(TMCParticle const& p, TMCParticles const& mcparticles) return -999; } - //_______________________________________________________________________ template int IsFromCharm(TMCParticle const& p, TMCParticles const& mcparticles) @@ -442,13 +483,13 @@ int IsFromCharm(TMCParticle const& p, TMCParticles const& mcparticles) int motherid = p.mothersIds()[0]; // first mother index auto mp_tmp = mcparticles.iteratorAt(motherid); - if (std::abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 2] == '4' && std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 3] == '4') && std::abs(mp_tmp.pdgCode()) % 2 == 1) { - return -999; // reject bottomonia + if (isCharmonia(mp_tmp)) { + return -999; // reject charmonia } while (motherid > -1) { if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed? auto mp = mcparticles.iteratorAt(motherid); - if (std::abs(mp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 3] == '4' || std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 4] == '4')) { + if (isCharmMeson(mp) || isCharmBaryon(mp)) { return motherid; } if (mp.has_mothers()) { From e60f433d6b7ad6dacd42c8eb5462fffd669912a4 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Thu, 14 May 2026 17:35:52 +0200 Subject: [PATCH 172/449] [PWGLF] added configurables for its pid and tpc corrections for he3 and pid in tracking. Removed pool processes (#16252) --- PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx | 477 +++++++----------- 1 file changed, 194 insertions(+), 283 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index cd5851d8272..fa2bb7a33a1 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -88,8 +88,6 @@ using TrackCandidatesMC = soa::Join betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; constexpr int Li4PDG = o2::constants::physics::Pdg::kLithium4; constexpr int H3LPDG = o2::constants::physics::Pdg::kHyperTriton; @@ -148,16 +146,30 @@ enum ParticleFlags { kFromOtherDecays = BIT(4), // from other decays }; -std::array kDCAxyResolutionParams[static_cast(Species::kAllSpecies)] = { - {0.0118, 0.6889, 0.0017}, // He3 - {0.0032, 0.5206, 0.0012} // Pr +constexpr double kItsParamsDefault[static_cast(Species::kAllSpecies)][6] = { + {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, // He3 + {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32} // hadron }; -std::array kDCAzResolutionParams[static_cast(Species::kAllSpecies)] = { - {0.1014, 1.7512, 0.0024}, // He3 - {0.0021, 1.1122, 0.0021} // Pr +static const std::vector kItsParNames{"p0", "p1", "p2", "res0", "res1", "res2"}; + +constexpr double kBetheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +static const std::vector kBetheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; + +constexpr double kBetheBlochCorrectionDefault[1][6]{{0.0, -1.e32, -1.e32, 0.0, -1.e32, -1.e32}}; +static const std::vector kBetheBlochCorrectionParNames{"p0", "p1", "p2", "p3", "p4", "p5"}; + +constexpr double kDCAxyResDefault[static_cast(Species::kAllSpecies)][4] = { + {1.09e-4, 0.0011, 0.0065, 1.0399}, // He3 + {8.19e-5, 0.004, 0.0026, 1.1741} // Pr +}; +constexpr double kDCAzResDefault[static_cast(Species::kAllSpecies)][4] = { + {9.36e-5, 0.0019, 0.0080, 1.416}, // He3 + {1.18e-4, 0.0020, 0.0025, 1.3460} // Pr }; +static const std::vector kDCAResParNames{"res0", "res1", "res2", "mean"}; -std::array kHePidTrkParams = {0.1593, -0.0445}; +constexpr double kHePidTrkPtParamsHeDefault[3] = {0.3101, -0.1759, 0.0262}; +constexpr double kHePidTrkPParamsHeDefault[3] = {1.1157, -0.9171, 0.1987}; } // namespace @@ -180,7 +192,6 @@ struct He3HadCandidate { float dcazHe3 = -10.f; float dcaxyHad = -10.f; float dcazHad = -10.f; - float dcaPair = -10.f; // DCA between the two tracks uint16_t tpcSignalHe3 = 0u; uint16_t tpcSignalHad = 0u; @@ -246,27 +257,30 @@ struct he3HadronFemto { // Selections Configurable settingHadPDGCode{"settingHadPDGCode", 211, "Hadron - PDG code"}; - Configurable settingCutVertex{"settingCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable settingCutRigidityMinHe3{"settingCutRigidityMinHe3", 0.8f, "Minimum rigidity for He3"}; - Configurable settingCutEta{"settingCutEta", 0.9f, "Eta cut on daughter track"}; - Configurable settingCutDCAxy{"settingCutDCAxy", 2.0f, "DCAxy range for tracks"}; - Configurable settingCutDCAz{"settingCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable settingCutNClsTPC{"settingCutNClsTPC", 90, "number of TPC clusters for a generic track"}; - Configurable settingCutNClsTPCHe3{"settingCutNClsTPCHe3", 110.0f, "number of TPC clusters for a He3 track"}; - Configurable settingCutChi2tpcLow{"settingCutChi2tpcLow", 0.f, "Low cut on TPC chi2"}; - Configurable settingCutChi2tpcLowHe3{"settingCutChi2tpcLowHe3", 0.5f, "Low cut on TPC chi2 for He3"}; - Configurable settingCutInvMass{"settingCutInvMass", 0.0f, "Invariant mass upper limit"}; - Configurable settingCutPtMinhe3Had{"settingCutPtMinhe3Had", 0.0f, "Minimum PT cut on he3Had4"}; - Configurable settingCutClSizeItsHe3{"settingCutClSizeItsHe3", 4.0f, "Minimum ITS cluster size for He3"}; - Configurable settingCutNCls{"settingCutNCls", 5.0f, "Minimum ITS Ncluster for tracks"}; - Configurable settingCutChi2NClITS{"settingCutChi2NClITS", 36.f, "Maximum ITS Chi2 for tracks"}; - Configurable settingCutNsigmaDcaXy{"settingCutNsigmaDcaXy", 3.0f, "Value of the DCA xy Nsigma cut"}; - Configurable settingCutNsigmaDcaZ{"settingCutNsigmaDcaZ", 3.0f, "Value of the DCA z Nsigma cut"}; - Configurable settingCutNsigmaTPC{"settingCutNsigmaTPC", 3.0f, "Value of the TPC Nsigma cut"}; - Configurable settingCutNsigmaITSHad{"settingCutNsigmaITSHad", -2.f, "Value of the ITS Nsigma cutfor Had"}; - Configurable settingCutNsigmaITSHe3{"settingCutNsigmaITSHe3", -1.5f, "Value of the ITS Nsigma cutfor He3"}; - Configurable settingCutPtMinTOFHad{"settingCutPtMinTOFHad", 0.4f, "Minimum pT to apply the TOF cut on hadrons"}; - Configurable settingCutNsigmaTOF{"settingCutNsigmaTOF", 3.0f, "Value of the TOF Nsigma cut"}; + struct : o2::framework::ConfigurableGroup { + std::string prefix{"cutSettings"}; + Configurable settingCutVertex{"settingCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable settingCutRigidityMinHe3{"settingCutRigidityMinHe3", 0.8f, "Minimum rigidity for He3"}; + Configurable settingCutEta{"settingCutEta", 0.9f, "Eta cut on daughter track"}; + Configurable settingCutDCAxy{"settingCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable settingCutDCAz{"settingCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable settingCutNClsTPC{"settingCutNClsTPC", 90, "number of TPC clusters for a generic track"}; + Configurable settingCutNClsTPCHe3{"settingCutNClsTPCHe3", 110.0f, "number of TPC clusters for a He3 track"}; + Configurable settingCutChi2tpcLow{"settingCutChi2tpcLow", 0.f, "Low cut on TPC chi2"}; + Configurable settingCutChi2tpcLowHe3{"settingCutChi2tpcLowHe3", 0.5f, "Low cut on TPC chi2 for He3"}; + Configurable settingCutInvMass{"settingCutInvMass", 0.0f, "Invariant mass upper limit"}; + Configurable settingCutPtMinhe3Had{"settingCutPtMinhe3Had", 0.0f, "Minimum PT cut on he3Had4"}; + Configurable settingCutClSizeItsHe3{"settingCutClSizeItsHe3", 4.0f, "Minimum ITS cluster size for He3"}; + Configurable settingCutNCls{"settingCutNCls", 5.0f, "Minimum ITS Ncluster for tracks"}; + Configurable settingCutChi2NClITS{"settingCutChi2NClITS", 36.f, "Maximum ITS Chi2 for tracks"}; + Configurable settingCutNsigmaDcaXy{"settingCutNsigmaDcaXy", 3.0f, "Value of the DCA xy Nsigma cut"}; + Configurable settingCutNsigmaDcaZ{"settingCutNsigmaDcaZ", 3.0f, "Value of the DCA z Nsigma cut"}; + Configurable settingCutNsigmaTPC{"settingCutNsigmaTPC", 3.0f, "Value of the TPC Nsigma cut"}; + Configurable settingCutNsigmaITSHad{"settingCutNsigmaITSHad", -2.f, "Value of the ITS Nsigma cutfor Had"}; + Configurable settingCutNsigmaITSHe3{"settingCutNsigmaITSHe3", -1.5f, "Value of the ITS Nsigma cutfor He3"}; + Configurable settingCutPtMinTOFHad{"settingCutPtMinTOFHad", 0.4f, "Minimum pT to apply the TOF cut on hadrons"}; + Configurable settingCutNsigmaTOF{"settingCutNsigmaTOF", 3.0f, "Value of the TOF Nsigma cut"}; + } cutSettings; Configurable> settingEventSelections{"settingEventSelections", {nuclei::EvSelDefault[0], 8, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable settingNoMixedEvents{"settingNoMixedEvents", 5, "Number of mixed events per event"}; @@ -295,7 +309,14 @@ struct he3HadronFemto { Configurable settingGeoPath{"settingGeoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable settingPidPath{"settingPidPath", "", "Path to the PID response object"}; - Configurable> settingBetheBlochParams{"settingBetheBlochParams", {betheBlochDefault[0], 1, 6, {"He3"}, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; + Configurable> settingBetheBlochParams{"settingBetheBlochParams", {kBetheBlochDefault[0], 1, 6, {"He3"}, kBetheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; + Configurable> settingBetheBlochCorrectionParams{"settingBetheBlochCorrectionParams", {kBetheBlochCorrectionDefault[0], 1, 6, {"He3"}, kBetheBlochCorrectionParNames}, "TPC Bethe-Bloch correction parameterisation for He3"}; + Configurable> settingItsParams{"settingItsParams", {kItsParamsDefault[0], 2, 6, {"He3", "Had"}, kItsParNames}, "ITS parameterisation"}; + Configurable> settingDCAxyResParams{"settingDCAxyResParams", {kDCAxyResDefault[0], 2, 4, {"He3", "Had"}, kDCAResParNames}, "DCAxy resolution parameterisation"}; + Configurable> settingDCAzResParams{"settingDCAzResParams", {kDCAzResDefault[0], 2, 4, {"He3", "Had"}, kDCAResParNames}, "DCAz resolution parameterisation"}; + Configurable> settingHePidTrkPtParams{"settingHePidTrkPtParams", {kHePidTrkPtParamsHeDefault, 1, 3, {"He3"}, {"p0", "p1", "p2"}}, "PID in tracking pT dependence for He3"}; + Configurable> settingHePidTrkPParams{"settingHePidTrkPParams", {kHePidTrkPParamsHeDefault, 1, 3, {"He3"}, {"p0", "p1", "p2"}}, "PID in tracking p dependence for He3"}; + Configurable settingCompensatePIDinTracking{"settingCompensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; Configurable settingMaterialCorrection{"settingMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Material correction type"}; @@ -310,7 +331,16 @@ struct he3HadronFemto { SliceCache cache; SameKindPair mPair{binningPolicy, settingNoMixedEvents, -1, &cache}; - std::array mBBparamsHe; + struct He3HadronParams { + std::array betheBlochParams; + std::array betheBlochCorrectionParams; + std::array, static_cast(Species::kAllSpecies)> itsParams; + std::array, static_cast(Species::kAllSpecies)> dcaxyResParams; + std::array, static_cast(Species::kAllSpecies)> dcazResParams; + std::array hePidTrkPtParams; + std::array hePidTrkPParams; + } mHe3HadronParams; + o2::aod::ITSResponse mResponseITS; std::vector mRecoCollisionIDs; @@ -400,9 +430,41 @@ struct he3HadronFemto { const int nBetheBlochParameters = 5; for (int i = 0; i < nBetheBlochParameters; i++) { - mBBparamsHe[i] = settingBetheBlochParams->get("He3", Form("p%i", i)); + mHe3HadronParams.betheBlochParams[i] = settingBetheBlochParams->get("He3", Form("p%i", i)); + } + mHe3HadronParams.betheBlochParams[5] = settingBetheBlochParams->get("He3", "resolution"); + + const int nBetheBlochCorrectionParameters = 6; + for (int i = 0; i < nBetheBlochCorrectionParameters; i++) { + mHe3HadronParams.betheBlochCorrectionParams[i] = settingBetheBlochCorrectionParams->get("He3", Form("p%i", i)); + } + + const int nItsParameters = 6; + const int nDCAResParameters = 4; + for (int iSpecies = 0; iSpecies < static_cast(Species::kAllSpecies); iSpecies++) { + + for (int i = 0; i < nItsParameters; i++) { + mHe3HadronParams.itsParams[iSpecies][i] = i < 3 ? settingItsParams->get(Species(iSpecies), Form("p%i", i)) : settingItsParams->get(Species(iSpecies), Form("res%i", i - 3)); + } + + for (int i = 0; i < nDCAResParameters; i++) { + mHe3HadronParams.dcaxyResParams[iSpecies][i] = settingDCAxyResParams->get(Species(iSpecies), i < 3 ? Form("res%i", i) : "mean"); + mHe3HadronParams.dcazResParams[iSpecies][i] = settingDCAzResParams->get(Species(iSpecies), i < 3 ? Form("res%i", i) : "mean"); + } + } + + if (mHe3HadronParams.itsParams[Species::kHe3][0] > -1e31) { + mResponseITS.setParameters(mHe3HadronParams.itsParams[Species::kHad][0], mHe3HadronParams.itsParams[Species::kHad][1], mHe3HadronParams.itsParams[Species::kHad][2], + mHe3HadronParams.itsParams[Species::kHe3][0], mHe3HadronParams.itsParams[Species::kHe3][1], mHe3HadronParams.itsParams[Species::kHe3][2], + mHe3HadronParams.itsParams[Species::kHad][3], mHe3HadronParams.itsParams[Species::kHad][4], mHe3HadronParams.itsParams[Species::kHad][5], + mHe3HadronParams.itsParams[Species::kHe3][3], mHe3HadronParams.itsParams[Species::kHe3][4], mHe3HadronParams.itsParams[Species::kHe3][5]); + } + + const int nHePidTrkParams = 3; + for (int i = 0; i < nHePidTrkParams; i++) { + mHe3HadronParams.hePidTrkPtParams[i] = settingHePidTrkPtParams->get("He3", Form("p%i", i)); + mHe3HadronParams.hePidTrkPParams[i] = settingHePidTrkPParams->get("He3", Form("p%i", i)); } - mBBparamsHe[5] = settingBetheBlochParams->get("He3", "resolution"); std::vector selectionLabels = {"All", "Track selection", "PID"}; for (int i = 0; i < Selections::kAll; i++) { @@ -467,7 +529,7 @@ struct he3HadronFemto { auto bc = collision.template bc_as(); initCCDB(bc); - if (!nuclei::eventSelection(collision, mQaRegistry, settingEventSelections, settingCutVertex)) { + if (!nuclei::eventSelection(collision, mQaRegistry, settingEventSelections, cutSettings.settingCutVertex)) { return false; } if (settingSkimmedProcessing) { @@ -487,71 +549,69 @@ struct he3HadronFemto { template bool selectTrack(const Ttrack& candidate, const int ispecies) { - if (std::abs(candidate.eta()) > settingCutEta) { + if (std::abs(candidate.eta()) > cutSettings.settingCutEta) { return false; } - const int minTPCNClsFound = ispecies == Species::kHe3 ? static_cast(settingCutNClsTPCHe3) : static_cast(settingCutNClsTPCHe3); + const int minTPCNClsFound = ispecies == Species::kHe3 ? static_cast(cutSettings.settingCutNClsTPCHe3) : static_cast(cutSettings.settingCutNClsTPCHe3); const int minTPCNClsCrossedRows = 70; - const float crossedRowsToFindableRatio = 0.8f; - const float minChi2NCl = ispecies == Species::kHe3 ? static_cast(settingCutChi2tpcLowHe3) : static_cast(settingCutChi2tpcLow); + const float minChi2NCl = ispecies == Species::kHe3 ? static_cast(cutSettings.settingCutChi2tpcLowHe3) : static_cast(cutSettings.settingCutChi2tpcLow); const float maxChi2NCl = 4.f; - if (candidate.itsNCls() < settingCutNCls || + if (candidate.itsNCls() < cutSettings.settingCutNCls || candidate.tpcNClsFound() < minTPCNClsFound || candidate.tpcNClsCrossedRows() < minTPCNClsCrossedRows || - candidate.tpcNClsCrossedRows() < crossedRowsToFindableRatio * candidate.tpcNClsFindable() || candidate.tpcChi2NCl() > maxChi2NCl || candidate.tpcChi2NCl() < minChi2NCl || - candidate.itsChi2NCl() > settingCutChi2NClITS) { + candidate.itsChi2NCl() > cutSettings.settingCutChi2NClITS) { return false; } return true; } - template - float correctPtHe3TrackedAsTriton(const Ttrack& candidate) + float correctPtHe3TrackedAsTriton(const float pt, const uint32_t pidForTracking) { - if (candidate.pt() * 2. < 2.5 && candidate.pidForTracking() == o2::track::PID::Triton) - return candidate.pt() * 2. * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * candidate.pt() * 2.); + if (pt < 2.5 && pidForTracking == o2::track::PID::Triton) + return pt * (1. - mHe3HadronParams.hePidTrkPtParams[0] - mHe3HadronParams.hePidTrkPtParams[1] * pt - mHe3HadronParams.hePidTrkPtParams[2] * pt * pt); - return candidate.pt() * 2.; + return pt; } - float correctPtHe3TrackedAsTriton(const float pt, const uint32_t pidForTracking) + float correctTpcInnerParamHe3(const float tpcInnerParam, const uint32_t pidForTracking) { - if (pt < 2.5 && pidForTracking == o2::track::PID::Triton) - return pt * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * pt); + bool heliumPID = pidForTracking == o2::track::PID::Helium3 || pidForTracking == o2::track::PID::Alpha; + float correctedTPCinnerParam = (heliumPID && settingCompensatePIDinTracking) ? tpcInnerParam / 2.f : tpcInnerParam; - return pt; + correctedTPCinnerParam *= 2.f; // rigidity to momentum + if (correctedTPCinnerParam < 2.5 && pidForTracking == o2::track::PID::Triton) + return correctedTPCinnerParam * (1. - mHe3HadronParams.hePidTrkPParams[0] - mHe3HadronParams.hePidTrkPParams[1] * correctedTPCinnerParam - mHe3HadronParams.hePidTrkPParams[2] * correctedTPCinnerParam * correctedTPCinnerParam); + + return correctedTPCinnerParam; } float computeNsigmaDCA(const float pt, const float dca, const int iSpecies, const char* dcaType = "xy") { - std::array parameters; + std::array parameters; if (std::strcmp(dcaType, "xy") == 0) { - parameters = kDCAxyResolutionParams[iSpecies]; + parameters = mHe3HadronParams.dcaxyResParams[iSpecies]; } else if (std::strcmp(dcaType, "z") == 0) { - parameters = kDCAzResolutionParams[iSpecies]; + parameters = mHe3HadronParams.dcazResParams[iSpecies]; } else { LOG(error) << "Invalid dcaType. Accepted types are 'xy' 'z'"; - parameters = {0., 0., 0.}; + parameters = {0., 0., 0., 0.}; } - const float sigma = parameters[0] * - std::exp(-std::abs(pt) * parameters[1]) + - parameters[2]; - return dca / sigma; + const float sigma = parameters[1] + parameters[2] / std::pow(std::abs(pt), parameters[3]); + const float mean = parameters[0]; + return (dca - mean) / sigma; } - template - bool selectDcaNsigmaCut(const Ttrack& candidate, const int ispecies) + bool selectDcaNsigmaCut(const float pt, const float dcaXY, const float dcaZ, const int ispecies) { - const float pt = ispecies == Species::kHe3 ? 2. * candidate.pt() : candidate.pt(); - const float nsigmaDcaXy = computeNsigmaDCA(pt, candidate.dcaXY(), ispecies, "xy"); - const float nsigmaDcaZ = computeNsigmaDCA(pt, candidate.dcaZ(), ispecies, "z"); + const float nsigmaDcaXy = computeNsigmaDCA(pt, dcaXY, ispecies, "xy"); + const float nsigmaDcaZ = computeNsigmaDCA(pt, dcaZ, ispecies, "z"); - if (std::abs(nsigmaDcaXy) > settingCutNsigmaDcaXy || - std::abs(nsigmaDcaZ) > settingCutNsigmaDcaZ) + if (std::abs(nsigmaDcaXy) > cutSettings.settingCutNsigmaDcaXy || + std::abs(nsigmaDcaZ) > cutSettings.settingCutNsigmaDcaZ) return false; return true; @@ -590,20 +650,20 @@ struct he3HadronFemto { { auto tpcNSigmaHad = computeTPCNSigmaHadron(candidate); mQaRegistry.fill(HIST("Had/h2NsigmaHadronTPC_preselection"), candidate.tpcInnerParam(), tpcNSigmaHad); - if (candidate.hasTOF() && candidate.pt() > settingCutPtMinTOFHad) { + if (candidate.hasTOF() && candidate.pt() > cutSettings.settingCutPtMinTOFHad) { auto tofNSigmaHad = computeTOFNSigmaHadron(candidate); - if (std::abs(tpcNSigmaHad) > settingCutNsigmaTPC) { + if (std::abs(tpcNSigmaHad) > cutSettings.settingCutNsigmaTPC) { return false; } mQaRegistry.fill(HIST("Had/h2NsigmaHadronTOF_preselection"), candidate.pt(), tofNSigmaHad); - if (std::abs(tofNSigmaHad) > settingCutNsigmaTOF) { + if (std::abs(tofNSigmaHad) > cutSettings.settingCutNsigmaTOF) { return false; } mQaRegistry.fill(HIST("Had/h2NsigmaHadronTPC"), candidate.pt(), tpcNSigmaHad); mQaRegistry.fill(HIST("Had/h2NsigmaHadronTOF"), candidate.pt(), tofNSigmaHad); return true; - } else if (std::abs(tpcNSigmaHad) < settingCutNsigmaTPC) { + } else if (std::abs(tpcNSigmaHad) < cutSettings.settingCutNsigmaTPC) { mQaRegistry.fill(HIST("Had/h2NsigmaHadronTPC"), candidate.pt(), tpcNSigmaHad); return true; } @@ -615,37 +675,50 @@ struct he3HadronFemto { { bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; float correctedTPCinnerParam = (heliumPID && settingCompensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); - float expTPCSignal = o2::common::BetheBlochAleph(static_cast(correctedTPCinnerParam * 2.f / constants::physics::MassHelium3), mBBparamsHe[0], mBBparamsHe[1], mBBparamsHe[2], mBBparamsHe[3], mBBparamsHe[4]); + float expTPCSignal = o2::common::BetheBlochAleph(static_cast(correctedTPCinnerParam * 2.f / constants::physics::MassHelium3), mHe3HadronParams.betheBlochParams[0], mHe3HadronParams.betheBlochParams[1], mHe3HadronParams.betheBlochParams[2], mHe3HadronParams.betheBlochParams[3], mHe3HadronParams.betheBlochParams[4]); - double resoTPC{expTPCSignal * mBBparamsHe[5]}; + double resoTPC{expTPCSignal * mHe3HadronParams.betheBlochParams[5]}; return static_cast((candidate.tpcSignal() - expTPCSignal) / resoTPC); } + float computeNSigmaHe3(const float tpcInnerParam, const float tpcSignal, const bool applyCorrection = false) + { + const float betagamma = tpcInnerParam / constants::physics::MassHelium3; + float expTPCSignal = o2::common::BetheBlochAleph(static_cast(betagamma), mHe3HadronParams.betheBlochParams[0], mHe3HadronParams.betheBlochParams[1], mHe3HadronParams.betheBlochParams[2], mHe3HadronParams.betheBlochParams[3], mHe3HadronParams.betheBlochParams[4]); + if (applyCorrection) { + double residualCorrection = (mHe3HadronParams.betheBlochCorrectionParams[0] * std::exp(-(betagamma - mHe3HadronParams.betheBlochCorrectionParams[1]) * (betagamma - mHe3HadronParams.betheBlochCorrectionParams[1]) / (2 * mHe3HadronParams.betheBlochCorrectionParams[2] * mHe3HadronParams.betheBlochCorrectionParams[2])) + mHe3HadronParams.betheBlochCorrectionParams[3] * std::exp(-(betagamma - mHe3HadronParams.betheBlochCorrectionParams[4]) * (betagamma - mHe3HadronParams.betheBlochCorrectionParams[4]) / (2 * mHe3HadronParams.betheBlochCorrectionParams[5] * mHe3HadronParams.betheBlochCorrectionParams[5]))); + expTPCSignal += residualCorrection; + } + + double resoTPC{expTPCSignal * mHe3HadronParams.betheBlochParams[5]}; + return static_cast((tpcSignal - expTPCSignal) / resoTPC); + } + template bool selectionPIDHe3(const Ttrack& candidate) { - bool heliumPID = candidate.pidForTracking() == o2::track::PID::Helium3 || candidate.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParam = (heliumPID && settingCompensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); + const float correctedTPCinnerParam = correctTpcInnerParamHe3(candidate.tpcInnerParam(), candidate.pidForTracking()); + const float correctedPt = correctPtHe3TrackedAsTriton(candidate.pt(), candidate.pidForTracking()); - if (correctedTPCinnerParam < settingCutRigidityMinHe3) { + if (correctedTPCinnerParam < cutSettings.settingCutRigidityMinHe3) { return false; } - auto nSigmaHe3 = computeNSigmaHe3(candidate); - mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC_preselection"), candidate.sign() * 2 * candidate.pt(), nSigmaHe3); - if (std::abs(nSigmaHe3) > settingCutNsigmaTPC) { + auto nSigmaHe3 = computeNSigmaHe3(correctedTPCinnerParam, candidate.tpcSignal(), /*applyCorrection*/ true); + mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC_preselection"), candidate.sign() * correctedPt, nSigmaHe3); + if (std::abs(nSigmaHe3) > cutSettings.settingCutNsigmaTPC) { return false; } auto itsNsigmaHe3 = mResponseITS.nSigmaITS(candidate.itsClusterSizes(), 2 * candidate.p(), candidate.eta()); - mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS_preselection"), candidate.sign() * 2 * candidate.pt(), itsNsigmaHe3); - if (itsNsigmaHe3 < settingCutNsigmaITSHe3) { + mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS_preselection"), candidate.sign() * correctedPt, itsNsigmaHe3); + if (itsNsigmaHe3 < cutSettings.settingCutNsigmaITSHe3) { return false; } mQaRegistry.fill(HIST("He3/h2dEdxHe3candidates"), candidate.sign() * correctedTPCinnerParam, candidate.tpcSignal()); - mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC"), candidate.sign() * 2 * candidate.pt(), nSigmaHe3); - mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS"), candidate.sign() * 2 * candidate.pt(), itsNsigmaHe3); + mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC"), candidate.sign() * correctedPt, nSigmaHe3); + mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS"), candidate.sign() * correctedPt, itsNsigmaHe3); return true; } @@ -721,11 +794,11 @@ struct he3HadronFemto { LOG(info) << "invalid PDG code for invMass"; } - if (settingCutInvMass > 0 && invMass > settingCutInvMass) { + if (cutSettings.settingCutInvMass > 0 && invMass > cutSettings.settingCutInvMass) { return false; } float pthe3Had = std::hypot(he3Hadcand.momHe3[0] + he3Hadcand.momHad[0], he3Hadcand.momHe3[1] + he3Hadcand.momHad[1]); - if (pthe3Had < settingCutPtMinhe3Had) { + if (pthe3Had < cutSettings.settingCutPtMinhe3Had) { return false; } @@ -746,18 +819,16 @@ struct he3HadronFemto { o2::base::Propagator::Instance()->propagateToDCABxByBz({collisionVertex[0], collisionVertex[1], collisionVertex[2]}, trackCovHad, 2.f, mFitter.getMatCorrType(), &dcaInfo); he3Hadcand.dcaxyHad = dcaInfo[0]; he3Hadcand.dcazHad = dcaInfo[1]; - he3Hadcand.dcaPair = std::sqrt(std::abs(mFitter.getChi2AtPCACandidate())); } he3Hadcand.tpcSignalHe3 = trackHe3.tpcSignal(); - bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && settingCompensatePIDinTracking) ? trackHe3.tpcInnerParam() / 2.f : trackHe3.tpcInnerParam(); + const float correctedTPCinnerParamHe3 = correctTpcInnerParamHe3(trackHe3.tpcInnerParam(), trackHe3.pidForTracking()); he3Hadcand.momHe3TPC = correctedTPCinnerParamHe3; he3Hadcand.tpcSignalHad = trackHad.tpcSignal(); he3Hadcand.momHadTPC = trackHad.tpcInnerParam(); he3Hadcand.nTPCClustersHe3 = trackHe3.tpcNClsFound(); - he3Hadcand.nSigmaHe3 = computeNSigmaHe3(trackHe3); + he3Hadcand.nSigmaHe3 = computeNSigmaHe3(correctedTPCinnerParamHe3, trackHe3.tpcSignal(), /*applyCorrection*/ true); he3Hadcand.nSigmaTPCHad = computeTPCNSigmaHadron(trackHad); he3Hadcand.nSigmaTPCHadPi = trackHad.tpcNSigmaPi(); he3Hadcand.nSigmaTPCHadKa = trackHad.tpcNSigmaKa(); @@ -795,8 +866,6 @@ struct he3HadronFemto { if (trackHe3.hasTOF()) { float beta = o2::pid::tof::Beta::GetBeta(trackHe3); beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParamHe3 = (heliumPID && settingCompensatePIDinTracking) ? trackHe3.tpcInnerParam() / 2.f : trackHe3.tpcInnerParam(); he3Hadcand.massTOFHe3 = correctedTPCinnerParamHe3 * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); } if (trackHad.hasTOF()) { @@ -901,62 +970,33 @@ struct he3HadronFemto { void fillTable(const He3HadCandidate& he3Hadcand, const Tcoll& collision, bool isMC = false) { outputDataTable( - he3Hadcand.recoPtHe3(), - he3Hadcand.recoEtaHe3(), - he3Hadcand.recoPhiHe3(), - he3Hadcand.recoPtHad(), - he3Hadcand.recoEtaHad(), - he3Hadcand.recoPhiHad(), - he3Hadcand.dcaxyHe3, - he3Hadcand.dcazHe3, - he3Hadcand.dcaxyHad, - he3Hadcand.dcazHad, - he3Hadcand.tpcSignalHe3, - he3Hadcand.momHe3TPC, - he3Hadcand.tpcSignalHad, - he3Hadcand.momHadTPC, - he3Hadcand.nTPCClustersHe3, - he3Hadcand.nSigmaHe3, - he3Hadcand.nSigmaTPCHad, - he3Hadcand.nSigmaTOFHad, - he3Hadcand.chi2TPCHe3, - he3Hadcand.chi2TPCHad, - he3Hadcand.massTOFHad, - he3Hadcand.pidtrkHe3, - he3Hadcand.itsClSizeHe3, - he3Hadcand.itsClSizeHad, + he3Hadcand.recoPtHe3(), he3Hadcand.recoEtaHe3(), he3Hadcand.recoPhiHe3(), + he3Hadcand.recoPtHad(), he3Hadcand.recoEtaHad(), he3Hadcand.recoPhiHad(), + he3Hadcand.dcaxyHe3, he3Hadcand.dcazHe3, + he3Hadcand.dcaxyHad, he3Hadcand.dcazHad, + he3Hadcand.tpcSignalHe3, he3Hadcand.momHe3TPC, + he3Hadcand.tpcSignalHad, he3Hadcand.momHadTPC, + he3Hadcand.nTPCClustersHe3, he3Hadcand.nSigmaHe3, + he3Hadcand.nSigmaTPCHad, he3Hadcand.nSigmaTOFHad, + he3Hadcand.chi2TPCHe3, he3Hadcand.chi2TPCHad, + he3Hadcand.massTOFHad, he3Hadcand.pidtrkHe3, + he3Hadcand.itsClSizeHe3, he3Hadcand.itsClSizeHad, he3Hadcand.sharedClustersHe3); if (isMC) { outputMcTable( - he3Hadcand.momHe3MC, - he3Hadcand.etaHe3MC, - he3Hadcand.phiHe3MC, - he3Hadcand.momHadMC, - he3Hadcand.etaHadMC, - he3Hadcand.phiHadMC, - he3Hadcand.l4PtMC, - he3Hadcand.l4MassMC, - he3Hadcand.flags); + he3Hadcand.momHe3MC, he3Hadcand.etaHe3MC, he3Hadcand.phiHe3MC, + he3Hadcand.momHadMC, he3Hadcand.etaHadMC, he3Hadcand.phiHadMC, + he3Hadcand.l4PtMC, he3Hadcand.l4MassMC, he3Hadcand.flags); } outputMultiplicityTable( - collision.globalIndex(), - collision.posZ(), - collision.numContrib(), - collision.centFT0C(), - collision.multFT0C()); + collision.globalIndex(), collision.posZ(), collision.numContrib(), + collision.centFT0C(), collision.multFT0C()); outputQaTable( - he3Hadcand.trackIDHe3, - he3Hadcand.trackIDHad, - he3Hadcand.massTOFHe3, - he3Hadcand.pidtrkHad, - he3Hadcand.sharedClustersHad); + he3Hadcand.trackIDHe3, he3Hadcand.trackIDHad, he3Hadcand.massTOFHe3, + he3Hadcand.pidtrkHad, he3Hadcand.sharedClustersHad); outputPidTable( - he3Hadcand.nSigmaTPCHadPi, - he3Hadcand.nSigmaTPCHadKa, - he3Hadcand.nSigmaTPCHadPr, - he3Hadcand.nSigmaTOFHadPi, - he3Hadcand.nSigmaTOFHadKa, - he3Hadcand.nSigmaTOFHadPr); + he3Hadcand.nSigmaTPCHadPi, he3Hadcand.nSigmaTPCHadKa, he3Hadcand.nSigmaTPCHadPr, + he3Hadcand.nSigmaTOFHadPi, he3Hadcand.nSigmaTOFHadKa, he3Hadcand.nSigmaTOFHadPr); } void fillHistograms(const He3HadCandidate& he3Hadcand, bool isMc = false) @@ -1244,134 +1284,6 @@ struct he3HadronFemto { } PROCESS_SWITCH(he3HadronFemto, processMC, "Process MC", false); - void processSameEventPools(const CollisionsFull& collisions, const TrackCandidates& tracks, const aod::AmbiguousTracks& ambiguousTracks, const aod::BCsWithTimestamps& bcs) - { - mGoodCollisions.clear(); - mGoodCollisions.resize(collisions.size(), false); - - for (const auto& collision : collisions) { - if (selectCollision(collision, bcs)) { - mGoodCollisions[collision.globalIndex()] = true; - } - } - - mSvPoolCreator.clearPools(); - mSvPoolCreator.fillBC2Coll(collisions, bcs); - - for (const auto& track : tracks) { - - mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); - if (!selectTrack(track, Species::kHad)) // specific he3 cuts skipped here, might need to refactor this - continue; - mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); - - bool selHad = selectionPIDHadron(track); - bool selHe = selectionPIDHe3(track); - if ((!selHad && !selHe) || (selHad && selHe)) { - continue; - } - mQaRegistry.fill(HIST("hTrackSel"), Selections::kPID); - - int pdgHypo = selHe ? He3PDG : ProtonPDG; - - mSvPoolCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); - } - - mTrackPairs = mSvPoolCreator.getSVCandPool(collisions, true); - if (mTrackPairs.size() == 0) { - mQaRegistry.fill(HIST("hEmptyPool"), 1); - return; - } - mQaRegistry.fill(HIST("hEmptyPool"), 0); - - fillPairs(collisions, tracks, /*isMixedEvent*/ false); - } - PROCESS_SWITCH(he3HadronFemto, processSameEventPools, "Process Same event pools", false); - - void processMcPools(const CollisionsFullMC& collisions, const TrackCandidatesMC& tracks, const aod::AmbiguousTracks& ambiguousTracks, const aod::BCsWithTimestamps& bcs, const aod::McParticles& mcParticles, const aod::McTrackLabels& mcTrackLabels) - { - std::vector filledMothers; - - mGoodCollisions.clear(); - mGoodCollisions.resize(collisions.size(), false); - - for (const auto& collision : collisions) { - if (selectCollision(collision, bcs)) { - mGoodCollisions[collision.globalIndex()] = true; - } - } - - mSvPoolCreator.clearPools(); - mSvPoolCreator.fillBC2Coll(collisions, bcs); - - for (const auto& track : tracks) { - - mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); - if (!selectTrack(track, Species::kHad)) // specific he3 cuts skipped here, might need to refactor this - continue; - mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); - - bool selHad = selectionPIDHadron(track); - bool selHe = selectionPIDHe3(track); - if ((!selHad && !selHe) || (selHad && selHe)) - continue; - mQaRegistry.fill(HIST("hTrackSel"), Selections::kPID); - - int pdgHypo = selHe ? He3PDG : ProtonPDG; - - mSvPoolCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); - } - - auto& svPool = mSvPoolCreator.getSVCandPool(collisions, true); - if (svPool.size() == 0) { - mQaRegistry.fill(HIST("hEmptyPool"), 1); - return; - } - mQaRegistry.fill(HIST("hEmptyPool"), 0); - - for (const auto& svCand : svPool) { - auto heTrack = tracks.rawIteratorAt(svCand.tr0Idx); - auto prTrack = tracks.rawIteratorAt(svCand.tr1Idx); - auto heTrackLabel = mcTrackLabels.rawIteratorAt(svCand.tr0Idx); - auto prTrackLabel = mcTrackLabels.rawIteratorAt(svCand.tr1Idx); - auto collBracket = svCand.collBracket; - - if (!heTrackLabel.has_mcParticle() || !prTrackLabel.has_mcParticle()) { - continue; - } - - auto mctrackHe3 = heTrackLabel.mcParticle_as(); - auto mctrackHad = prTrackLabel.mcParticle_as(); - - if (std::abs(mctrackHe3.pdgCode()) != He3PDG || std::abs(mctrackHad.pdgCode()) != ProtonPDG || !mctrackHe3.has_mothers() || !mctrackHad.has_mothers()) { - continue; - } - - for (const auto& mothertrackHe : mctrackHe3.mothers_as()) { - for (const auto& mothertrackHad : mctrackHad.mothers_as()) { - - if (mothertrackHe.globalIndex() != mothertrackHad.globalIndex() || std::abs(mothertrackHe.pdgCode()) != Li4PDG || std::abs(mothertrackHe.y()) > 1) { - continue; - } - - He3HadCandidate he3Hadcand; - if (!fillCandidateInfo(heTrack, prTrack, collBracket, collisions, he3Hadcand, tracks, /*mix*/ false)) { - continue; - } - fillCandidateInfoMC(mctrackHe3, mctrackHad, he3Hadcand); - fillMotherInfoMC(mctrackHe3, mctrackHad, mothertrackHe, he3Hadcand); - fillHistograms(he3Hadcand); - auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); - fillTable(he3Hadcand, collision, /*isMC*/ true); - filledMothers.push_back(mothertrackHe.globalIndex()); - } - } - } - - fillMcParticles(collisions, mcParticles, filledMothers); - } - PROCESS_SWITCH(he3HadronFemto, processMcPools, "Process MC pools", false); - void processPurity(const CollisionsFull::iterator& collision, const TrackCandidates& tracks, const aod::BCsWithTimestamps& bcs) { if (!selectCollision(collision, bcs)) @@ -1385,7 +1297,7 @@ struct he3HadronFemto { const float itsNSigmaHad = settingHadPDGCode == PDG_t::kProton ? mResponseITS.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta()) : mResponseITS.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta()); mQaRegistry.fill(HIST("Had/h2NsigmaHadronITS_preselection"), track.sign() * track.pt(), itsNSigmaHad); - if (selectDcaNsigmaCut(track, Species::kHad) && (itsNSigmaHad > settingCutNsigmaITSHad)) { + if (selectDcaNsigmaCut(track.pt(), track.dcaXY(), track.dcaZ(), Species::kHad) && (itsNSigmaHad > cutSettings.settingCutNsigmaITSHad)) { mQaRegistry.fill(HIST("Had/hHadronPt"), track.sign() * track.pt()); mQaRegistry.fill(HIST("Had/h2NsigmaHadronITS"), track.sign() * track.pt(), itsNSigmaHad); @@ -1399,11 +1311,11 @@ struct he3HadronFemto { } } - const float ptHe3Corrected = correctPtHe3TrackedAsTriton(track); + const float ptHe3Corrected = correctPtHe3TrackedAsTriton(track.pt(), track.pidForTracking()); const float itsNSigmaHe3 = mResponseITS.nSigmaITS(track.itsClusterSizes(), 2 * track.p(), track.eta()); mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS_preselection"), ptHe3Corrected, itsNSigmaHe3); - if (!selectTrack(track, Species::kHe3) || !selectDcaNsigmaCut(track, Species::kHe3) || (itsNSigmaHe3 < settingCutNsigmaITSHe3)) + if (!selectTrack(track, Species::kHe3) || !selectDcaNsigmaCut(ptHe3Corrected, track.dcaXY(), track.dcaZ(), Species::kHe3) || (itsNSigmaHe3 < cutSettings.settingCutNsigmaITSHe3)) continue; mQaRegistry.fill(HIST("He3/hHe3Pt"), track.sign() * ptHe3Corrected); @@ -1411,13 +1323,12 @@ struct he3HadronFemto { mQaRegistry.fill(HIST("He3/hDCAzHe3"), track.dcaZ()); mQaRegistry.fill(HIST("He3/h2NsigmaHe3ITS"), track.sign() * ptHe3Corrected, itsNSigmaHe3); - bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParam = (heliumPID && settingCompensatePIDinTracking) ? track.tpcInnerParam() / 2.f : track.tpcInnerParam(); - if (correctedTPCinnerParam < settingCutRigidityMinHe3) { + const float correctedTPCinnerParam = correctTpcInnerParamHe3(track.tpcInnerParam(), track.pidForTracking()); + if (correctedTPCinnerParam < cutSettings.settingCutRigidityMinHe3) { continue; } - const float tpcNSigmaHe3 = computeNSigmaHe3(track); + const float tpcNSigmaHe3 = computeNSigmaHe3(correctedTPCinnerParam, track.tpcSignal(), /*applyCorrection*/ true); mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC_preselection"), track.sign() * ptHe3Corrected, tpcNSigmaHe3); } } @@ -1437,7 +1348,7 @@ struct he3HadronFemto { if (!selectTrack(track, Species::kHad)) continue; - if (selectDcaNsigmaCut(track, Species::kHad)) { + if (selectDcaNsigmaCut(track.pt(), track.dcaXY(), track.dcaZ(), Species::kHad)) { mQaRegistry.fill(HIST("Had/hHadronPt"), track.pt()); const float tpcNSigmaHad = computeTPCNSigmaHadron(track); @@ -1461,21 +1372,21 @@ struct he3HadronFemto { } } - if (!selectTrack(track, Species::kHe3) || !selectDcaNsigmaCut(track, Species::kHe3)) + const float ptHe3Corrected = correctPtHe3TrackedAsTriton(track.pt(), track.pidForTracking()); + if (!selectTrack(track, Species::kHe3) || !selectDcaNsigmaCut(ptHe3Corrected, track.dcaXY(), track.dcaZ(), Species::kHe3)) continue; - mQaRegistry.fill(HIST("He3/hHe3Pt"), track.pt() * 2.f); + mQaRegistry.fill(HIST("He3/hHe3Pt"), ptHe3Corrected); mQaRegistry.fill(HIST("He3/hDCAxyHe3"), track.dcaXY()); mQaRegistry.fill(HIST("He3/hDCAzHe3"), track.dcaZ()); - bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; - float correctedTPCinnerParam = (heliumPID && settingCompensatePIDinTracking) ? track.tpcInnerParam() / 2.f : track.tpcInnerParam(); - if (correctedTPCinnerParam < settingCutRigidityMinHe3) { + const float correctedTPCinnerParam = correctTpcInnerParamHe3(track.tpcInnerParam(), track.pidForTracking()); + if (correctedTPCinnerParam < cutSettings.settingCutRigidityMinHe3) { continue; } - const float nSigmaHe3 = computeNSigmaHe3(track); - mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC_preselection"), track.sign() * 2 * track.pt(), nSigmaHe3); + const float nSigmaHe3 = computeNSigmaHe3(correctedTPCinnerParam, track.tpcSignal(), /*applyCorrection*/ true); + mQaRegistry.fill(HIST("He3/h2NsigmaHe3TPC_preselection"), track.sign() * ptHe3Corrected, nSigmaHe3); } } PROCESS_SWITCH(he3HadronFemto, processPurityMc, "Process for purity studies mc", false); From fc6741c6e600c627ee47ed42258be3bd811e1f07 Mon Sep 17 00:00:00 2001 From: nkaratze Date: Thu, 14 May 2026 17:37:51 +0200 Subject: [PATCH 173/449] [PWGLF] PWGLF:Updated Genprocess to accomodate INEL>0 (#16254) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 198 ++++++++++++------- 1 file changed, 130 insertions(+), 68 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index ec4360f2a5a..f87b4f1cb83 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -23,6 +23,7 @@ This analysis includes three processes, one for Real Data and two for MC at the #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" @@ -92,6 +93,7 @@ struct V0PtInvMassPlots { // Configurables for Cuts Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutZVertexGen{"cutZVertexGen", 100.0f, "Accepted z-vertex range (cm) for generated events"}; Configurable nSigmaTPCPion{"nSigmaTPCPion", 4, "nSigmaTPCPion"}; Configurable nSigmaTPCProton{"nSigmaTPCProton", 4, "nSigmaTPCProton"}; Configurable compv0masscut{"compv0masscut", 0.01, "CompetitiveV0masscut (GeV)"}; @@ -364,6 +366,18 @@ struct V0PtInvMassPlots { rMCCorrections.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); rMCCorrections.add("hGenPartcles", "hGenPartcles", {HistType::kTH2D, {nchAxis, centAxis}}); + // Generated Level Pt Spectrums (with rapidity cut for RecoINEL>0) + rMCCorrections.add("hK0shGeneratedRecoPtSpectrum", "hK0shGeneratedRecoPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hLambdaGeneratedRecoPtSpectrum", "hLambdaGeneratedRecoPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); + rMCCorrections.add("hAntiLambdaGeneratedRecoPtSpectrum", "hAntiLambdaGeneratedRecoPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hXiMinusGeneratedRecoPtSpectrum", "hXiMinusGeneratedRecoPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); + rMCCorrections.add("hXiZeroGeneratedRecoPtSpectrum", "hXiZeroGeneratedRecoPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); + rMCCorrections.add("hOmegaGeneratedRecoPtSpectrum", "hOmegaGeneratedRecoPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); + rMCCorrections.add("hXiPlusGeneratedRecoPtSpectrum", "hXiPlusGeneratedRecoPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hAntiXiZeroGeneratedRecoPtSpectrum", "hAntiXiZeroGeneratedRecoPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hAntiOmegaGeneratedRecoPtSpectrum", "hAntiOmegaGeneratedRecoPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hPhiGeneratedRecoPtSpectrum", "hPhiGeneratedRecoPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + // NCh Analysis rNchAnalysis.add("hNchCentralityGenerated", "hNchCentralityGenerated", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated rNchAnalysis.add("hNchCentralityGeneratedAfterEventSelection", "hNchCentralityGeneratedAfterEventSelection", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated After Event Selection @@ -757,102 +771,150 @@ struct V0PtInvMassPlots { soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) { - // Event Efficiency, Event Split and V0 Signal Loss Corrections rMCCorrections.fill(HIST("hNEvents_Corrections"), 0.5, mcCollision.centFT0M()); // All Events - if (std::abs(mcCollision.posZ()) > cutZVertex) { + if (std::abs(mcCollision.posZ()) > cutZVertexGen) { // Generated Z vertex cut return; } - if (!(mcCollision.multMCNParticlesEta10() > 0)) { // TRY TO CHANGE TO THIS - // if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { - return; + // if (!(mcCollision.multMCNParticlesEta10() > 0)) { // TRY TO CHANGE TO THIS + bool isINELgt0 = false; + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + // return; + isINELgt0 = true; + rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5, mcCollision.centFT0M()); // Event Efficiency Denominator } - rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5, mcCollision.centFT0M()); // Event Efficiency Denominator - int NParticlesPerCollision = 0; // Counter for the number of particles per collision for the Nch analysis + int NParticlesPerCollision = 0; // Counter for the number of particles per collision for the Nch analysis // Particles (of interest) Generated Pt Spectrum and Signal Loss Denominator Loop for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.y()) < rapidityCut) { if (mcParticle.isPhysicalPrimary()) { - rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); - if (mcParticle.pdgCode() == kK0Short) // K0sh matched - { - rMCCorrections.fill(HIST("hK0shGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kLambda0) // Lambda matched - { - rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kLambda0Bar) // AntiLambda matched - { - rMCCorrections.fill(HIST("hAntiLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched - { - rMCCorrections.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kXi0) // Xi Zero matched - { - rMCCorrections.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched - { - rMCCorrections.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched - { - rMCCorrections.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched - { - rMCCorrections.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched - { - rMCCorrections.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); - } - if (mcParticle.pdgCode() == kPhi) // Phi - { - rMCCorrections.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + if (isINELgt0) { + rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); + if (mcParticle.pdgCode() == kK0Short) // K0sh matched + { + rMCCorrections.fill(HIST("hK0shGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kLambda0) // Lambda matched + { + rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // AntiLambda matched + { + rMCCorrections.fill(HIST("hAntiLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched + { + rMCCorrections.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kXi0) // Xi Zero matched + { + rMCCorrections.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched + { + rMCCorrections.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched + { + rMCCorrections.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched + { + rMCCorrections.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched + { + rMCCorrections.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kPhi) // Phi + { + rMCCorrections.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (acceptGeneratedParticle(mcParticle, mcCollision)) { + NParticlesPerCollision++; + } } } } - if (acceptGeneratedParticle(mcParticle, mcCollision)) { - NParticlesPerCollision++; - } - } + } // End of MCParticle Loop rNchAnalysis.fill(HIST("hNchCentralityGenerated"), mcCollision.centFT0M(), NParticlesPerCollision); + // Signal Loss Numenator Loop + + int recoCollINEL = 0; + int recoCollINELgt0 = 0; for (const auto& collision : collisions) { rMCCorrections.fill(HIST("hNEvents_Corrections"), 2.5, mcCollision.centFT0M()); // Number of Events Reconsctructed if (!acceptEvent(collision)) { // Event Selection - return; + continue; + } + rMCCorrections.fill(HIST("hNEvents_Corrections"), 3.5, mcCollision.centFT0M()); // Event Split Numerator + recoCollINEL++; + if (collision.isInelGt0()) { // Check if the reconstructed collision fulfills the INEL>0 requirement + rMCCorrections.fill(HIST("hNEvents_Corrections"), 4.5, mcCollision.centFT0M()); // Event Split Denominator?????????????? + recoCollINELgt0++; + } + } + + // From now on keep only mc collisions with at least one reconstructed collision (INEL) + if (recoCollINEL < 1) { + return; + } + if (recoCollINELgt0 > 0) { + rMCCorrections.fill(HIST("hNEvents_Corrections"), 5.5, mcCollision.centFT0M()); // Event Efficiency Numerator and Event Split Denominator?????????? + } + + // Singnal Loss Numerator Loop + for (auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcParticle.y()) > 0.5f) { + continue; } - rMCCorrections.fill(HIST("hNEvents_Corrections"), 3.5, mcCollision.centFT0M()); // Event Split Denomimator and Event Efficiency Numenator - for (const auto& mcParticle : mcParticles) { - if (acceptGeneratedParticle(mcParticle, mcCollision)) { - NParticlesPerCollision++; // Counter to fill the NchCerntralityPlot after the loop + if (recoCollINELgt0 > 0) { + rMCCorrections.fill(HIST("hNEvents_Corrections"), 6.5, mcCollision.centFT0M()); + if (mcParticle.pdgCode() == kK0Short) // K0sh matched + { + rMCCorrections.fill(HIST("hK0shGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kLambda0) // Lambda matched + { + rMCCorrections.fill(HIST("hLambdaGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // AntiLambda matched + { + rMCCorrections.fill(HIST("hAntiLambdaGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (!mcParticle.isPhysicalPrimary()) { - continue; + if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched + { + rMCCorrections.fill(HIST("hXiMinusGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kXi0) // Xi Zero matched + { + rMCCorrections.fill(HIST("hXiZeroGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (std::abs(mcParticle.y()) > rapidityCut) { - continue; + if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched + { + rMCCorrections.fill(HIST("hOmegaGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + } + if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched + { + rMCCorrections.fill(HIST("hXiPlusGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kK0Short) // kzero matched + if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched { - rMCCorrections.fill(HIST("hK0shAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hAntiXiZeroGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0) // lambda matched + if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched { - rMCCorrections.fill(HIST("hLambdaAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hAntiOmegaGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + if (mcParticle.pdgCode() == kPhi) // Phi { - rMCCorrections.fill(HIST("hAntiLambdaAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hPhiGeneratedRecoPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } } } - rNchAnalysis.fill(HIST("hNchCentralityGeneratedAfterEventSelection"), mcCollision.centFT0M(), NParticlesPerCollision); - // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data // void recMCProcess(soa::Join::iterator const& collision, From 45edeb4a8f172563766da94419cd1c4908b1e94f Mon Sep 17 00:00:00 2001 From: Banajit Barman <113376372+BanajitBarman@users.noreply.github.com> Date: Fri, 15 May 2026 12:56:53 +0530 Subject: [PATCH 174/449] [PWGLF] MC Centralty: allow to turn on and off FT0M (#16236) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolò Jacazio --- PWGLF/TableProducer/Common/mcCentrality.cxx | 39 ++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/PWGLF/TableProducer/Common/mcCentrality.cxx b/PWGLF/TableProducer/Common/mcCentrality.cxx index e7ccd4d59fb..a55ac09ef44 100644 --- a/PWGLF/TableProducer/Common/mcCentrality.cxx +++ b/PWGLF/TableProducer/Common/mcCentrality.cxx @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -64,6 +65,7 @@ struct McCentrality { Service pdgDB; ConfigurableAxis binsPercentile{"binsPercentile", {VARIABLE_WIDTH, 0, 0.001, 0.01, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0}, "Binning of the percentile axis"}; ConfigurableAxis binsMultiplicity{"binsMultiplicity", {1000, 0, 5000}, "Binning of the multiplicity axis"}; + Configurable fillFt0M{"fillFt0M", true, "Fills the FT0M histogram"}; Configurable fillFt0A{"fillFt0A", false, "Fills the FT0A histogram"}; Configurable fillFt0C{"fillFt0C", false, "Fills the FT0C histogram"}; Configurable doNotCrashOnNull{"doNotCrashOnNull", false, "If ccdb object does not exist, fill with dummy values"}; @@ -89,8 +91,11 @@ struct McCentrality { mCounter.mPdgDatabase = pdgDB.service; mCounter.mSelectPrimaries = selectPrimaries.value; - histos.add("FT0M/percentile", "FT0M percentile.", HistType::kTH1D, {{binsPercentile, "FT0M percentile"}}); - histos.add("FT0M/percentilevsMult", "FT0M percentile.", HistType::kTH2D, {{binsPercentile, "FT0M percentile"}, {binsMultiplicity, "FT0M mult."}}); + + if (fillFt0M) { + histos.add("FT0M/percentile", "FT0M percentile.", HistType::kTH1D, {{binsPercentile, "FT0M percentile"}}); + histos.add("FT0M/percentilevsMult", "FT0M percentile.", HistType::kTH2D, {{binsPercentile, "FT0M percentile"}, {binsMultiplicity, "FT0M mult."}}); + } if (fillFt0A) { histos.add("FT0A/percentile", "FT0A percentile.", HistType::kTH1D, {{binsPercentile, "FT0A percentile"}}); histos.add("FT0A/percentilevsMult", "FT0A percentile.", HistType::kTH2D, {{binsPercentile, "FT0A percentile"}, {binsMultiplicity, "FT0A mult."}}); @@ -139,9 +144,12 @@ struct McCentrality { LOG(fatal) << "Could not open histogram " << name << " from TList"; } } + hist->SetDirectory(0); return hist; }; - h1dFT0M = getHist("h1dFT0M"); + if (fillFt0M) { + h1dFT0M = getHist("h1dFT0M"); + } if (fillFt0A) { h1dFT0A = getHist("h1dFT0A"); } @@ -159,27 +167,26 @@ struct McCentrality { const float nFT0M = nFT0A + nFT0C; // const float nFV0A = mCounter.countFV0A(mcParticles); - float valueCentFT0M = 105.0f; - if (h1dFT0M) - valueCentFT0M = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0M)); + if (fillFt0M) { + const float valueCentFT0M = h1dFT0M ? h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0M)) : 105.0f; + centFT0M(valueCentFT0M); + histos.fill(HIST("FT0M/percentile"), valueCentFT0M); + histos.fill(HIST("FT0M/percentilevsMult"), valueCentFT0M, nFT0M); + } if (fillFt0A) { - float valueCentFT0A = 105.0f; - if (h1dFT0A) - valueCentFT0A = h1dFT0A->GetBinContent(h1dFT0A->FindBin(nFT0A)); + const float valueCentFT0A = h1dFT0A ? h1dFT0A->GetBinContent(h1dFT0A->FindBin(nFT0A)) : 105.0f; centFT0A(valueCentFT0A); + histos.fill(HIST("FT0A/percentile"), valueCentFT0A); + histos.fill(HIST("FT0A/percentilevsMult"), valueCentFT0A, nFT0A); } if (fillFt0C) { - float valueCentFT0C = 105.0f; - if (h1dFT0C) - valueCentFT0C = h1dFT0C->GetBinContent(h1dFT0C->FindBin(nFT0C)); + const float valueCentFT0C = h1dFT0C ? h1dFT0C->GetBinContent(h1dFT0C->FindBin(nFT0C)) : 105.0f; centFT0C(valueCentFT0C); + histos.fill(HIST("FT0C/percentile"), valueCentFT0C); + histos.fill(HIST("FT0C/percentilevsMult"), valueCentFT0C, nFT0C); } // const float valueCentFV0A = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFV0A)); - - centFT0M(valueCentFT0M); // centFV0A(valueCentFV0A); - histos.fill(HIST("FT0M/percentile"), valueCentFT0M); - histos.fill(HIST("FT0M/percentilevsMult"), valueCentFT0M, nFT0M); } }; From e58d93d78e0f0867a63df2410bd48f20b0c3a616 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Fri, 15 May 2026 10:33:23 +0200 Subject: [PATCH 175/449] [ALICE3] Refactor OTF tracker (#16209) Co-authored-by: ALICE Action Bot --- ALICE3/DataModel/tracksAlice3.h | 4 +- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 2003 ++++++++--------- .../alice3TrackingTranslator.cxx | 3 +- 3 files changed, 975 insertions(+), 1035 deletions(-) diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 04cb2d1a9d4..374069de4cb 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -30,6 +30,7 @@ DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); //! is reconstructed DECLARE_SOA_COLUMN(NSiliconHits, nSiliconHits, int); //! number of silicon hits DECLARE_SOA_COLUMN(NTPCHits, nTPCHits, int); //! number of tpc hits DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); //! PDG code of the linked truth MC particle +DECLARE_SOA_COLUMN(TrackType, trackType, int); //! Type of the track } // namespace track_alice3 DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", track_alice3::IsReconstructed); @@ -41,7 +42,8 @@ using TrackAlice3Pdg = TracksAlice3Pdg::iterator; DECLARE_SOA_TABLE(TracksExtraA3, "AOD", "TracksExtraA3", track_alice3::NSiliconHits, - track_alice3::NTPCHits); + track_alice3::NTPCHits, + track_alice3::TrackType); using TrackExtraA3 = TracksExtraA3::iterator; namespace mcparticle_alice3 diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 7cb3139aaf1..6e2e7d0e0a7 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -116,6 +116,19 @@ using std::array; LOG(fatal) << "Histogram " << name << " not found!"; #define insertHist(name, ...) histPointers[name] = histos.add((name).c_str(), __VA_ARGS__); +enum TrackType { + kNone = 0, + kRecoPrimary, + kGhostPrimary, + kRecoV0Daug, + kGhostV0Daug, + kRecoCasc, + kGenCasc, + kRecoCascDaug, + kGenCascDaug, + kNTrackTypes, +}; + struct OnTheFlyTracker { Produces tableCollisions; Produces tableMcCollisionLabels; @@ -261,14 +274,16 @@ struct OnTheFlyTracker { bool weakDecayDauInput = false, int isUsedInCascadingInput = 0, int nSiliconHitsInput = 0, - int nTPCHitsInput = 0) : o2::track::TrackParCov(src), - mcLabel{label}, - timeEst{time, timeError}, - isDecayDau(decayDauInput), - isWeakDecayDau(weakDecayDauInput), - isUsedInCascading(isUsedInCascadingInput), - nSiliconHits(nSiliconHitsInput), - nTPCHits(nTPCHitsInput) {} + int nTPCHitsInput = 0, + TrackType trackTypeInput = TrackType::kRecoPrimary) : o2::track::TrackParCov(src), + mcLabel{label}, + timeEst{time, timeError}, + isDecayDau(decayDauInput), + isWeakDecayDau(weakDecayDauInput), + isUsedInCascading(isUsedInCascadingInput), + nSiliconHits(nSiliconHitsInput), + nTPCHits(nTPCHitsInput), + trackType(trackTypeInput) {} const TimeEst& getTimeMUS() const { return timeEst; } int64_t mcLabel; TimeEst timeEst; ///< time estimate in ns @@ -277,6 +292,7 @@ struct OnTheFlyTracker { int isUsedInCascading; // 0: not at all, 1: is a cascade, 2: is a bachelor, 3: is a pion, 4: is a proton int nSiliconHits; int nTPCHits; + TrackType trackType; }; // Helper struct to pass cascade information @@ -336,6 +352,9 @@ struct OnTheFlyTracker { o2::constants::physics::kHelium3, o2::constants::physics::kAlpha}; + // Primary vertexing QA + std::pair vertexReconstructionEfficiencyCounters = {0, 0}; // {nVerticesWithMoreThan2Contributors, nVerticesReconstructed} + // necessary for particle charges Service pdgDB; @@ -349,6 +368,10 @@ struct OnTheFlyTracker { std::vector> mSmearer; // For processing and vertexing + std::vector recoPrimaries; + std::vector ghostPrimaries; + std::vector recoV0Daugs; + std::vector recoCascDaugs; std::vector tracksAlice3; std::vector ghostTracksAlice3; std::vector bcData; @@ -364,6 +387,14 @@ struct OnTheFlyTracker { // Configuration defined at init time o2::fastsim::GeometryContainer mGeoContainer; float mMagneticField = 0.0f; + // Time resolution constants + const float timeResolutionNs = 100.f; // ns + const float nsToMus = 1e-3f; + const float timeResolutionUs = timeResolutionNs * nsToMus; // us + + o2::dataformats::DCA dcaInfo; + o2::dataformats::VertexBase vtx; + void init(o2::framework::InitContext& initContext) { LOG(info) << "Initializing OnTheFlyTracker task"; @@ -452,9 +483,9 @@ struct OnTheFlyTracker { insertHist(histPath + "hRecoMultiplicity", "hRecoMultiplicity;Reco Multiplicity;Counts", {kTH1D, {{axes.axisMultiplicity}}}); if (enablePrimaryVertexing) { - insertHist(histPath + "hDeltaXPVRecoGen", "hDeltaXPVRecoGen;Delta X (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); - insertHist(histPath + "hDeltaYPVRecoGen", "hDeltaYPVRecoGen;Delta Y (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); - insertHist(histPath + "hDeltaZPVRecoGen", "hDeltaZPVRecoGen;Delta Z (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); + insertHist(histPath + "hDeltaXPVRecoGen", "hDeltaXPVRecoGen;Delta X (reco - gen), cm", {kTH2D, {{axes.axisDeltaVtxCoord, axes.axisMultiplicity}}}); + insertHist(histPath + "hDeltaYPVRecoGen", "hDeltaYPVRecoGen;Delta Y (reco - gen), cm", {kTH2D, {{axes.axisDeltaVtxCoord, axes.axisMultiplicity}}}); + insertHist(histPath + "hDeltaZPVRecoGen", "hDeltaZPVRecoGen;Delta Z (reco - gen), cm", {kTH2D, {{axes.axisDeltaVtxCoord, axes.axisMultiplicity}}}); insertHist(histPath + "hDeltaMultPVRecoGen", "hDeltaMultPVRecoGen;Delta Multiplicity (reco - gen)", {kTH1D, {{axes.axisDeltaMultPVRecoGen}}}); insertHist(histPath + "hVtxMultGen", "hVtxMultGen;Generated Vertex Multiplicity", {kTH1D, {{axes.axisVtxMult}}}); insertHist(histPath + "hVtxMultReco", "hVtxMultReco;Reconstructed Vertex Multiplicity", {kTH1D, {{axes.axisVtxMult}}}); @@ -475,38 +506,48 @@ struct OnTheFlyTracker { if (cascadeDecaySettings.doXiQA) { insertHist(histPath + "hXiBuilding", "hXiBuilding", {kTH1F, {{10, -0.5f, 9.5f}}}); - - insertHist(histPath + "hGenXi", "hGenXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hRecoXi", "hRecoXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - - insertHist(histPath + "hGenPiFromXi", "hGenPiFromXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hGenPiFromLa", "hGenPiFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hGenPrFromLa", "hGenPrFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hRecoPiFromXi", "hRecoPiFromXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hRecoPiFromLa", "hRecoPiFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); - insertHist(histPath + "hRecoPrFromLa", "hRecoPrFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(1, "Generated"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(2, "Secondary smearing prong 0"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(3, "Secondary smearing prong 1"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(4, "Secondary smearing prong 2"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(5, "Not Nan"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(6, "Start Reco"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(7, "V0 fitter ok"); + getHist(TH1, histPath + "hXiBuilding")->GetXaxis()->SetBinLabel(8, "Kink fitter ok"); + + insertHist(histPath + "hGenXi", "hGenXi;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoXi", "hRecoXi;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + + insertHist(histPath + "hGenPiFromXi", "hGenPiFromXi;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hGenPiFromLa", "hGenPiFromLa;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hGenPrFromLa", "hGenPrFromLa;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPiFromXi", "hRecoPiFromXi;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPiFromLa", "hRecoPiFromLa;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPrFromLa", "hRecoPrFromLa;Decay Radius;#it{p}_{T}", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); // basic mass histograms to see if we're in business - insertHist(histPath + "hMassLambda", "hMassLambda", {kTH1F, {{axes.axisLambdaMass}}}); - insertHist(histPath + "hMassXi", "hMassXi", {kTH1F, {{axes.axisXiMass}}}); - insertHist(histPath + "h2dMassXi", "h2dMassXi", {kTH2F, {{axes.axisXiMass}, {axes.axisMomentum}}}); + insertHist(histPath + "hMassLambda", "hMassLambda;Mass;Counts", {kTH1F, {{axes.axisLambdaMass}}}); + insertHist(histPath + "hMassXi", "hMassXi;Mass;Counts", {kTH1F, {{axes.axisXiMass}}}); + insertHist(histPath + "h2dMassXi", "h2dMassXi;Mass;Counts", {kTH2F, {{axes.axisXiMass}, {axes.axisMomentum}}}); // OTF strangeness tracking QA - insertHist(histPath + "hFoundVsFindable", "hFoundVsFindable", {kTH2F, {{10, -0.5f, 9.5f}, {10, -0.5f, 9.5f}}}); + insertHist(histPath + "hFoundVsFindable", "hFoundVsFindable;Found;Findable", {kTH2F, {{10, -0.5f, 9.5f}, {10, -0.5f, 9.5f}}}); - insertHist(histPath + "h2dDCAxyCascade", "h2dDCAxyCascade", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAxyCascadeBachelor", "h2dDCAxyCascadeBachelor", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAxyCascadeNegative", "h2dDCAxyCascadeNegative", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAxyCascadePositive", "h2dDCAxyCascadePositive", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascade", "h2dDCAxyCascade;#it{p}_{T};DCA_{xy}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadeBachelor", "h2dDCAxyCascadeBachelor;#it{p}_{T};DCA_{xy}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadeNegative", "h2dDCAxyCascadeNegative;#it{p}_{T};DCA_{xy}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadePositive", "h2dDCAxyCascadePositive;#it{p}_{T};DCA_{xy}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAzCascade", "h2dDCAzCascade", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAzCascadeBachelor", "h2dDCAzCascadeBachelor", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAzCascadeNegative", "h2dDCAzCascadeNegative", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); - insertHist(histPath + "h2dDCAzCascadePositive", "h2dDCAzCascadePositive", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascade", "h2dDCAzCascade;#it{p}_{T};DCA_{z}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadeBachelor", "h2dDCAzCascadeBachelor;#it{p}_{T};DCA_{z}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadeNegative", "h2dDCAzCascadeNegative;#it{p}_{T};DCA_{z}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadePositive", "h2dDCAzCascadePositive;#it{p}_{T};DCA_{z}", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); insertHist(histPath + "h2dDeltaPtVsPt", "h2dDeltaPtVsPt;Gen p_{T};#Delta p_{T}", {kTH2F, {axes.axisMomentum, axes.axisDeltaPt}}); insertHist(histPath + "h2dDeltaEtaVsPt", "h2dDeltaEtaVsPt;Gen p_{T};#Delta #eta", {kTH2F, {axes.axisMomentum, axes.axisDeltaEta}}); + insertHist(histPath + "nSiliconHitsCascadeProngs", "nSiliconHitsCascadeProngs", {kTH1F, {{40, -0.5f, 39.5f}}}); + insertHist(histPath + "nTPCHitsCascadeProngs", "nTPCHitsCascadeProngs", {kTH1F, {{10, -0.5f, 9.5f}}}); insertHist(histPath + "hFastTrackerHits", "hFastTrackerHits", {kTH2F, {axes.axisZ, axes.axisRadius}}); insertHist(histPath + "hFastTrackerQA", "hFastTrackerQA", {kTH1F, {{8, -0.5f, 7.5f}}}); getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(1, "Negative eigenvalue"); @@ -517,12 +558,12 @@ struct OnTheFlyTracker { getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(6, "multiple scattering"); getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(7, "energy loss"); getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(8, "efficiency"); - getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(9, "no layers hit"); } } if (doExtraQA) { insertHist(histPath + "h2dPtRes", "h2dPtRes;Gen p_{T};#Delta p_{T} / Reco p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); + insertHist(histPath + "h2dPtResAbs", "h2dPtResAbs;Gen p_{T};#Delta p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); insertHist(histPath + "h2dDCAxy", "h2dDCAxy;p_{T};DCA_{xy}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); insertHist(histPath + "h2dDCAz", "h2dDCAz;p_{T};DCA_{z}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); } @@ -599,7 +640,6 @@ struct OnTheFlyTracker { insertHist(v0histPath + "K0/hRecoNegDaughterFromV0", "hRecoNegDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "K0/hRecoPosDaughterFromV0", "hRecoPosDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "K0/hMass", "hMass", kTH2F, {axes.axisK0Mass, axes.axisMomentum}); - insertHist(v0histPath + "K0/hFinalMass", "hFinalMass", kTH1F, {axes.axisK0Mass}); // Lambda insertHist(v0histPath + "Lambda/hGen", "hGen", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "Lambda/hReco", "hReco", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); @@ -608,8 +648,6 @@ struct OnTheFlyTracker { insertHist(v0histPath + "Lambda/hRecoNegDaughterFromV0", "hRecoNegDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "Lambda/hRecoPosDaughterFromV0", "hRecoPosDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "Lambda/hMass", "hMass", kTH2F, {axes.axisLambdaMass, axes.axisMomentum}); - insertHist(v0histPath + "Lambda/hFinalMass", "hFinalMass", kTH1F, {axes.axisLambdaMass}); - // AntiLambda insertHist(v0histPath + "AntiLambda/hGen", "hGen", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "AntiLambda/hReco", "hReco", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); @@ -618,7 +656,6 @@ struct OnTheFlyTracker { insertHist(v0histPath + "AntiLambda/hRecoNegDaughterFromV0", "hRecoNegDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "AntiLambda/hRecoPosDaughterFromV0", "hRecoPosDaughterFromV0", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "AntiLambda/hMass", "hMass", kTH2F, {axes.axisLambdaMass, axes.axisMomentum}); - insertHist(v0histPath + "AntiLambda/hFinalMass", "hFinalMass", kTH1F, {axes.axisLambdaMass}); } } @@ -806,30 +843,13 @@ struct OnTheFlyTracker { decayDaughters.push_back(*v0Decay.GetDecay(1)); } - float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation - std::pair vertexReconstructionEfficiencyCounters = {0, 0}; // {nVerticesWithMoreThan2Contributors, nVerticesReconstructed} - void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) + /// Function to compute dN/deta for a given set of MC particles + /// \param dNdEta the address of the variable to fill with the computed dN/deta value + /// \param mcParticles the set of MC particles to compute dN/deta from + /// \param histPath the path to the histogram where the computed dN/deta value will be stored for QA purposes + template + void computeDNDEta(float& dNdEta, McParticleType const& mcParticles, const std::string histPath) { - vertexReconstructionEfficiencyCounters.first += 1; - const int lastTrackIndex = tableStoredTracksCov.lastIndex() + 1; // bookkeep the last added track - const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - - tracksAlice3.clear(); - ghostTracksAlice3.clear(); - bcData.clear(); - cascadesAlice3.clear(); - v0sAlice3.clear(); - - o2::dataformats::DCA dcaInfo; - o2::dataformats::VertexBase vtx; - - // generate collision time - auto ir = irSampler.generateCollisionTime(); - const float eventCollisionTimeNS = ir.timeInBCNS; - - // First we compute the number of charged particles in the event - dNdEta = 0.f; - LOG(debug) << "Processing " << mcParticles.size() << " MC particles to compute dNch/deta"; for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.eta()) > multEtaRange) { continue; @@ -842,7 +862,7 @@ struct OnTheFlyTracker { const auto pdg = std::abs(mcParticle.pdgCode()); const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), pdg) != longLivedHandledPDGs.end(); const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), pdg) != nucleiPDGs.end(); - const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled) || (cascadeDecaySettings.decayXi && mcParticle.pdgCode() == kXiMinus); + const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled); if (!pdgsToBeHandled) { continue; } @@ -860,852 +880,826 @@ struct OnTheFlyTracker { LOG(debug) << "Computed dNch/deta before normalization: " << dNdEta; dNdEta /= (multEtaRange * 2.0f); - uint32_t multiplicityCounter = 0; getHist(TH1, histPath + "hLUTMultiplicity")->Fill(dNdEta); + } + + /// Function to study the cascade decay and fill the relevant histograms and output track vector + /// \param trackTableOffset the offset to apply to the global track indices when filling the output track vector + /// \param mcParticle the cascade MC particle to study + /// \param tracksCascadeProngs the address of the vector of output tracks to fill with the cascade daughters + /// \param primaryVertex the primary vertex of the event, needed for the track propagation in the cascade decay + /// \param icfg the index of the current configuration, needed for histogram filling + /// \param dNdEta the dN/deta of the event, needed for the track time smearing + /// \param eventCollisionTimeNS the collision time of the event in ns, needed for the track time smearing + template + void studyCascade(const int trackTableOffset, + const McParticleType& mcParticle, + std::vector& tracksCascadeProngs, + o2::vertexing::PVertex& primaryVertex, + int icfg, + int dNdEta, + float eventCollisionTimeNS) + { + o2::track::TrackParCov trackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - // Now that the multiplicity is known, we can process the particles to smear them - double xiDecayRadius2D = 0; - double laDecayRadius2D = 0; - double v0DecayRadius2D = 0; std::vector cascadeDecayProducts; - std::vector v0DecayProducts; - std::vector xiDecayVertex, laDecayVertex, v0DecayVertex; - for (const auto& mcParticle : mcParticles) { - xiDecayRadius2D = 0; - laDecayRadius2D = 0; - v0DecayRadius2D = 0; - xiDecayVertex.clear(); - laDecayVertex.clear(); - v0DecayVertex.clear(); - - cascadeDecayProducts.clear(); - v0DecayProducts.clear(); - const bool isCascade = mcParticle.pdgCode() == kXiMinus; - if (cascadeDecaySettings.decayXi && isCascade) { - o2::track::TrackParCov xiTrackParCov; - o2::upgrade::convertMCParticleToO2Track(mcParticle, xiTrackParCov, pdgDB); - decayCascade(mcParticle, xiTrackParCov, cascadeDecayProducts, xiDecayVertex, laDecayVertex); - if (cascadeDecayProducts.size() != 3) { - LOG(fatal) << "Xi decay did not produce 3 daughters as expected!"; + std::vector xiDecayVertex, laDecayVertex; + static constexpr int kCascProngs = 3; + std::array xiDaughterTrackParCovsPerfect; + std::array xiDaughterTrackParCovsTracked; + std::array isReco; + std::array nHitsCascadeProngs; // total + std::array nSiliconHitsCascadeProngs; // silicon type + std::array nTPCHitsCascadeProngs; // TPC type + + o2::track::TrackParCov xiTrackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, xiTrackParCov, pdgDB); + decayCascade(mcParticle, xiTrackParCov, cascadeDecayProducts, xiDecayVertex, laDecayVertex); + if (cascadeDecayProducts.size() != 3) { + LOG(fatal) << "Xi decay did not produce 3 daughters as expected!"; + } + double xiDecayRadius2D = std::hypot(xiDecayVertex[0], xiDecayVertex[1]); + double laDecayRadius2D = std::hypot(laDecayVertex[0], laDecayVertex[1]); + + if (cascadeDecaySettings.doXiQA) { + getHist(TH2, histPath + "hGenXi")->Fill(xiDecayRadius2D, mcParticle.pt()); + getHist(TH2, histPath + "hGenPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); + getHist(TH2, histPath + "hGenPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); + getHist(TH2, histPath + "hGenPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); + } + + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(0.0f); + } + + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[0], xiDecayVertex, xiDaughterTrackParCovsPerfect[0], pdgDB); + xiDaughterTrackParCovsPerfect[0].setPID(pdgCodeToPID(PDG_t::kPiMinus)); + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[1], laDecayVertex, xiDaughterTrackParCovsPerfect[1], pdgDB); + xiDaughterTrackParCovsPerfect[1].setPID(pdgCodeToPID(PDG_t::kPiMinus)); + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kProton, cascadeDecayProducts[2], laDecayVertex, xiDaughterTrackParCovsPerfect[2], pdgDB); + xiDaughterTrackParCovsPerfect[2].setPID(pdgCodeToPID(PDG_t::kProton)); + o2::track::TrackParCov perfectCascadeTrack; + o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectCascadeTrack, pdgDB); + perfectCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + + thisCascade.bachelorId = trackTableOffset + 1; + thisCascade.negativeId = trackTableOffset + 2; // Lambda daughters + thisCascade.positiveId = trackTableOffset + 3; // Lambda daughters + thisCascade.cascadeTrackId = trackTableOffset + 4; + + float trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksCascadeProngs.push_back(TrackAlice3{xiDaughterTrackParCovsPerfect[0], mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, 1, -1, -1, TrackType::kGenCascDaug}); + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksCascadeProngs.push_back(TrackAlice3{xiDaughterTrackParCovsPerfect[1], mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, 2, -1, -1, TrackType::kGenCascDaug}); + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksCascadeProngs.push_back(TrackAlice3{xiDaughterTrackParCovsPerfect[2], mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, 3, -1, -1, TrackType::kGenCascDaug}); + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksCascadeProngs.push_back(TrackAlice3{perfectCascadeTrack, mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, 3, -1, -1, TrackType::kGenCascDaug}); + + for (int i = 0; i < kCascProngs; i++) { + isReco[i] = false; + nHitsCascadeProngs[i] = 0; + nSiliconHitsCascadeProngs[i] = 0; + nTPCHitsCascadeProngs[i] = 0; + if (enableSecondarySmearing) { + nHitsCascadeProngs[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); + nSiliconHitsCascadeProngs[i] = fastTracker[icfg]->GetNSiliconPoints(); + nTPCHitsCascadeProngs[i] = fastTracker[icfg]->GetNGasPoints(); + + if (nHitsCascadeProngs[i] < 0 && cascadeDecaySettings.doXiQA) { // QA + getHist(TH1, histPath + "hFastTrackerQA")->Fill(o2::math_utils::abs(nHitsCascadeProngs[i])); } - xiDecayRadius2D = std::hypot(xiDecayVertex[0], xiDecayVertex[1]); - laDecayRadius2D = std::hypot(laDecayVertex[0], laDecayVertex[1]); - } - const bool isV0 = std::find(v0PDGs.begin(), v0PDGs.end(), mcParticle.pdgCode()) != v0PDGs.end(); - if (v0DecaySettings.decayV0 && isV0) { - decayV0Particle(mcParticle, v0DecayProducts, v0DecayVertex, mcParticle.pdgCode()); - if (v0DecayProducts.size() != 2) { - LOG(fatal) << "V0 decay did not produce 2 daughters as expected!"; + getHist(TH1, histPath + "nSiliconHitsCascadeProngs")->Fill(nSiliconHitsCascadeProngs[i]); + getHist(TH1, histPath + "nTPCHitsCascadeProngs")->Fill(nTPCHitsCascadeProngs[i]); + if (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHits || + (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && + nTPCHitsCascadeProngs[i] >= fastTrackerSettings.minTPCClusters)) { + isReco[i] = true; + } else { + continue; // extra sure } - v0DecayRadius2D = std::hypot(v0DecayVertex[0], v0DecayVertex[1]); - } + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(static_cast(i + 1)); + } + isReco[i] = true; - if (!mcParticle.isPhysicalPrimary()) { - continue; + for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits() && cascadeDecaySettings.doXiQA; ih++) { + getHist(TH2, histPath + "hFastTrackerHits")->Fill(fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); + } + } else { + isReco[i] = true; + xiDaughterTrackParCovsTracked[i] = xiDaughterTrackParCovsPerfect[i]; + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(static_cast(i + 1)); + } } - const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); - const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), std::abs(mcParticle.pdgCode())) != nucleiPDGs.end(); - const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled) || (cascadeDecaySettings.decayXi && isCascade) || (v0DecaySettings.decayV0 && isV0); - if (!pdgsToBeHandled) { + if (TMath::IsNaN(xiDaughterTrackParCovsTracked[i].getZ())) { + isReco[i] = false; continue; + } else { + getHist(TH1, histPath + "hXiBuilding")->Fill(4.0f); + histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); } + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + // TODO: add flag for whether it's a ghost track or not, currently assuming all are reconstructed tracks if they pass the fast tracker requirements + TrackType trackType = isReco[i] ? TrackType::kRecoCascDaug : TrackType::kGenCascDaug; + tracksCascadeProngs[i] = TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i], trackType}; + } - if (std::fabs(mcParticle.eta()) > maxEta) { - continue; - } - if (enablePrimarySmearing) { - getHist(TH1, histPath + "hPtGenerated")->Fill(mcParticle.pt()); - getHist(TH1, histPath + "hPhiGenerated")->Fill(mcParticle.phi()); - switch (std::abs(mcParticle.pdgCode())) { - case kElectron: - getHist(TH1, histPath + "hPtGeneratedEl")->Fill(mcParticle.pt()); - break; - case kPiPlus: - getHist(TH1, histPath + "hPtGeneratedPi")->Fill(mcParticle.pt()); - break; - case kKPlus: - getHist(TH1, histPath + "hPtGeneratedKa")->Fill(mcParticle.pt()); - break; - case kProton: - getHist(TH1, histPath + "hPtGeneratedPr")->Fill(mcParticle.pt()); - break; - } - } - if (cascadeDecaySettings.doXiQA && isCascade) { - getHist(TH2, histPath + "hGenXi")->Fill(xiDecayRadius2D, mcParticle.pt()); - getHist(TH2, histPath + "hGenPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); - getHist(TH2, histPath + "hGenPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); - getHist(TH2, histPath + "hGenPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); + bool tryKinkReco = false; + if (!isReco[1] || !isReco[2]) { + tryKinkReco = true; // Lambda outside acceptance, set flag for kink reco to be used if mode 1 + } + + bool reconstructedCascade = false; + if (isReco[0] && isReco[1] && isReco[2]) { + reconstructedCascade = true; + } + + bool fillCascadeTable{false}; + + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + // combine particles into actual Xi candidate + // cascade building starts here + if (cascadeDecaySettings.findXi && reconstructedCascade && cascadeDecaySettings.doKinkReco != 2) { + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(3.0f); } - if (v0DecaySettings.doV0QA && isV0) { - for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { - if (mcParticle.pdgCode() != v0PDGs[indexV0]) { - continue; - } - for (int indexDetector = 0; indexDetector < mGeoContainer.getNumberOfConfigurations(); indexDetector++) { - std::string path = Form("V0Building_Configuration_%i/%s/", indexDetector, NameV0s[indexV0].data()); - fillHist(TH2, path + "hGen", v0DecayRadius2D, mcParticle.pt()); - fillHist(TH2, path + "hGenNegDaughterFromV0", v0DecayRadius2D, v0DecayProducts[0].Pt()); - fillHist(TH2, path + "hGenPosDaughterFromV0", v0DecayRadius2D, v0DecayProducts[1].Pt()); - } - } + + // use DCA fitters + int nCand = 0; + bool dcaFitterV0Status = true; + try { + nCand = fitter.process(xiDaughterTrackParCovsTracked[1], xiDaughterTrackParCovsTracked[2]); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter for V0!"; + dcaFitterV0Status = false; } - if (mcParticle.pt() < minPt) { - continue; + if (nCand == 0) { + // LOG(info) << "No V0 candidate found in DCA fitter!"; + dcaFitterV0Status = false; } - o2::track::TrackParCov trackParCov; - o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); - - const bool isDecayDaughter = (mcParticle.getProcess() == TMCProcess::kPDecay); + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterV0Status = false; + } - multiplicityCounter++; - const float timeResolutionNs = 100.f; // ns - const float nsToMus = 1e-3f; - const float timeResolutionUs = timeResolutionNs * nsToMus; // us - const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; - static constexpr int kCascProngs = 3; - std::array xiDaughterTrackParCovsPerfect; - std::array xiDaughterTrackParCovsTracked; - std::array isReco; - std::array nHitsCascadeProngs; // total - std::array nSiliconHitsCascadeProngs; // silicon type - std::array nTPCHitsCascadeProngs; // TPC type - - bool tryKinkReco = false; - if (cascadeDecaySettings.decayXi && isCascade) { - bool reconstructedCascade = false; + // V0 found successfully + if (dcaFitterV0Status) { if (cascadeDecaySettings.doXiQA) { - getHist(TH1, histPath + "hXiBuilding")->Fill(0.0f); + getHist(TH1, histPath + "hXiBuilding")->Fill(4.0f); } - o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[0], xiDecayVertex, xiDaughterTrackParCovsPerfect[0], pdgDB); - xiDaughterTrackParCovsPerfect[0].setPID(pdgCodeToPID(PDG_t::kPiMinus)); - o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[1], laDecayVertex, xiDaughterTrackParCovsPerfect[1], pdgDB); - xiDaughterTrackParCovsPerfect[1].setPID(pdgCodeToPID(PDG_t::kPiMinus)); - o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kProton, cascadeDecayProducts[2], laDecayVertex, xiDaughterTrackParCovsPerfect[2], pdgDB); - xiDaughterTrackParCovsPerfect[2].setPID(pdgCodeToPID(PDG_t::kProton)); - - for (int i = 0; i < kCascProngs; i++) { - isReco[i] = false; - nHitsCascadeProngs[i] = 0; - nSiliconHitsCascadeProngs[i] = 0; - nTPCHitsCascadeProngs[i] = 0; - if (enableSecondarySmearing) { - nHitsCascadeProngs[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); - nSiliconHitsCascadeProngs[i] = fastTracker[icfg]->GetNSiliconPoints(); - nTPCHitsCascadeProngs[i] = fastTracker[icfg]->GetNGasPoints(); - - if (nHitsCascadeProngs[i] < 0 && cascadeDecaySettings.doXiQA) { // QA - getHist(TH1, histPath + "hFastTrackerQA")->Fill(o2::math_utils::abs(nHitsCascadeProngs[i])); - } - - if (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHitsCascadeProngs[i] >= fastTrackerSettings.minTPCClusters)) { - isReco[i] = true; - } else { - continue; // extra sure - } - for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits() && cascadeDecaySettings.doXiQA; ih++) { - getHist(TH2, histPath + "hFastTrackerHits")->Fill(fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); - } - } else { - isReco[i] = true; - xiDaughterTrackParCovsTracked[i] = xiDaughterTrackParCovsPerfect[i]; - } + std::array pos; + std::array posCascade; + std::array posP; + std::array negP; + std::array bachP; + + o2::track::TrackParCov pTrackAtPCA = fitter.getTrack(1); // proton (positive) + o2::track::TrackParCov nTrackAtPCA = fitter.getTrack(0); // pion (negative) + pTrackAtPCA.getPxPyPzGlo(posP); + nTrackAtPCA.getPxPyPzGlo(negP); + + // get decay vertex coordinates + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + pos[i] = vtx[i]; + } - if (TMath::IsNaN(xiDaughterTrackParCovsTracked[i].getZ())) { - continue; - } else { - histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); - } - if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); - } else { - ghostTracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); - } + // calculate basic V0 properties here + // DCA to PV taken care of in daughter tracks already, not necessary + thisCascade.dcaV0dau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.v0radius = std::hypot(pos[0], pos[1]); + thisCascade.mLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, + std::array{negP[0], negP[1], negP[2]}}, + std::array{o2::constants::physics::MassProton, + o2::constants::physics::MassPionCharged}); + + // go for cascade: create V0 (pseudo)track from reconstructed V0 + std::array covV = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV[MomInd[i]] = 1e-6; + covV[i] = 1e-6; } - if (!isReco[1] || !isReco[2]) { - tryKinkReco = true; // Lambda outside acceptance, set flag for kink reco to be used if mode 1 + o2::track::TrackParCov v0Track = o2::track::TrackParCov( + {pos[0], pos[1], pos[2]}, + {posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}, + covV, 0, true); + v0Track.setAbsCharge(0); + v0Track.setPID(pdgCodeToPID(PDG_t::kLambda0)); + + // dca fitter step + nCand = 0; + bool dcaFitterCascadeStatus = true; + try { + nCand = fitter.process(v0Track, xiDaughterTrackParCovsTracked[0]); + } catch (...) { + // LOG(error) << "Exception caught in DCA fitter cascade!"; + dcaFitterCascadeStatus = false; + } + if (nCand == 0) { + dcaFitterCascadeStatus = false; } - if (isReco[0] && isReco[1] && isReco[2]) { - reconstructedCascade = true; + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterCascadeStatus = false; } - // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ - // combine particles into actual Xi candidate - // cascade building starts here - if (cascadeDecaySettings.findXi && isReco[0] && isReco[1] && isReco[2] && cascadeDecaySettings.doKinkReco != 2) { + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + // Cascade found successfully + if (dcaFitterCascadeStatus) { if (cascadeDecaySettings.doXiQA) { - getHist(TH1, histPath + "hXiBuilding")->Fill(3.0f); - } - // assign indices of the particles we've used - // they should be the last ones to be filled, in order: - // n-1: proton from lambda - // n-2: pion from lambda - // n-3: pion from xi - thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; - thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 2; - thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - 3; - - // use DCA fitters - int nCand = 0; - bool dcaFitterOK_V0 = true; - try { - nCand = fitter.process(xiDaughterTrackParCovsTracked[1], xiDaughterTrackParCovsTracked[2]); - } catch (...) { - // LOG(error) << "Exception caught in DCA fitter process call!"; - dcaFitterOK_V0 = false; - } - if (nCand == 0) { - dcaFitterOK_V0 = false; + getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f); } - fitter.propagateTracksToVertex(); - if (!fitter.isPropagateTracksToVertexDone()) { - dcaFitterOK_V0 = false; + o2::track::TrackParCov bachelorTrackAtPCA = fitter.getTrack(1); + const auto& vtxCascade = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + posCascade[i] = vtxCascade[i]; } - // V0 found successfully - if (dcaFitterOK_V0) { - if (cascadeDecaySettings.doXiQA) { - getHist(TH1, histPath + "hXiBuilding")->Fill(4.0f); - } - - std::array pos; - std::array posCascade; - std::array posP; - std::array negP; - std::array bachP; - - o2::track::TrackParCov pTrackAtPCA = fitter.getTrack(1); // proton (positive) - o2::track::TrackParCov nTrackAtPCA = fitter.getTrack(0); // pion (negative) - pTrackAtPCA.getPxPyPzGlo(posP); - nTrackAtPCA.getPxPyPzGlo(negP); - - // get decay vertex coordinates - const auto& vtx = fitter.getPCACandidate(); - for (int i = 0; i < 3; i++) { - pos[i] = vtx[i]; - } + // basic properties of the cascade + thisCascade.dcacascdau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.cascradius = std::hypot(posCascade[0], posCascade[1]); + bachelorTrackAtPCA.getPxPyPzGlo(bachP); + + thisCascade.mXi = RecoDecay::m(std::array{std::array{bachP[0], bachP[1], bachP[2]}, + std::array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}}, + std::array{o2::constants::physics::MassPionCharged, + o2::constants::physics::MassLambda}); + + // initialize cascade track + o2::track::TrackParCov cascadeTrack = fitter.createParentTrackParCov(); + cascadeTrack.setAbsCharge(-1); // may require more adjustments + cascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + + thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.pt = cascadeTrack.getPt(); + thisCascade.eta = cascadeTrack.getEta(); + thisCascade.findableClusters = 0; + thisCascade.foundClusters = 0; + + if (cascadeDecaySettings.trackXi) { + // optionally, add the points in the layers before the decay of the Xi + // will back-track the perfect MC cascade to relevant layers, find hit, smear and add to smeared cascade + for (int i = fastTracker[icfg]->GetLayers().size() - 1; i >= 0; --i) { + o2::fastsim::DetLayer layer = fastTracker[icfg]->GetLayer(i); + if (layer.isInert()) { + continue; // Not an active tracking layer + } - // calculate basic V0 properties here - // DCA to PV taken care of in daughter tracks already, not necessary - thisCascade.dcaV0dau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - thisCascade.v0radius = std::hypot(pos[0], pos[1]); - thisCascade.mLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, - std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassProton, - o2::constants::physics::MassPionCharged}); - - // go for cascade: create V0 (pseudo)track from reconstructed V0 - std::array covV = {0.}; - constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component - for (int i = 0; i < 6; i++) { - covV[MomInd[i]] = 1e-6; - covV[i] = 1e-6; - } + if (thisCascade.cascradiusMC < layer.getRadius()) { + continue; // Cascade did not reach this layer + } - o2::track::TrackParCov v0Track = o2::track::TrackParCov( - {pos[0], pos[1], pos[2]}, - {posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}, - covV, 0, true); - v0Track.setAbsCharge(0); - v0Track.setPID(pdgCodeToPID(PDG_t::kLambda0)); - - // dca fitter step - nCand = 0; - bool dcaFitterOK_Cascade = true; - try { - nCand = fitter.process(v0Track, xiDaughterTrackParCovsTracked[0]); - } catch (...) { - // LOG(error) << "Exception caught in DCA fitter process call!"; - dcaFitterOK_Cascade = false; - } - if (nCand == 0) { - dcaFitterOK_Cascade = false; - } + // cascade decayed after the corresponding radius + thisCascade.findableClusters++; // add to findable - fitter.propagateTracksToVertex(); - if (!fitter.isPropagateTracksToVertexDone()) { - dcaFitterOK_Cascade = false; - } + // find perfect intercept XYZ + float targetX = 1e+3; + xiTrackParCov.getXatLabR(layer.getRadius(), targetX, mMagneticField); + if (targetX > 999) { + continue; // failed to find intercept + } - const u_int8_t fitterStatusCode = fitter.getFitStatus(); - histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); - // Cascade found successfully - if (dcaFitterOK_Cascade) { - if (cascadeDecaySettings.doXiQA) { - getHist(TH1, histPath + "hXiBuilding")->Fill(5.0f); + if (!xiTrackParCov.propagateTo(targetX, mMagneticField)) { + continue; // failed to propagate } - o2::track::TrackParCov bachelorTrackAtPCA = fitter.getTrack(1); - const auto& vtxCascade = fitter.getPCACandidate(); - for (int i = 0; i < 3; i++) { - posCascade[i] = vtxCascade[i]; + // get potential cluster position + std::array posClusterCandidate; + xiTrackParCov.getXYZGlo(posClusterCandidate); + float r{std::hypot(posClusterCandidate[0], posClusterCandidate[1])}; + float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::constants::math::PI}; + + if (layer.getResolutionRPhi() > 1e-8 && layer.getResolutionZ() > 1e-8) { // catch zero (though should not really happen...) + phi = gRandom->Gaus(phi, std::asin(layer.getResolutionRPhi() / r)); + posClusterCandidate[0] = r * std::cos(phi); + posClusterCandidate[1] = r * std::sin(phi); + posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], layer.getResolutionZ()); } - // basic properties of the cascade - thisCascade.dcacascdau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - thisCascade.cascradius = std::hypot(posCascade[0], posCascade[1]); - bachelorTrackAtPCA.getPxPyPzGlo(bachP); - - thisCascade.mXi = RecoDecay::m(std::array{std::array{bachP[0], bachP[1], bachP[2]}, - std::array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}}, - std::array{o2::constants::physics::MassPionCharged, - o2::constants::physics::MassLambda}); - - // initialize cascade track - o2::track::TrackParCov cascadeTrack = fitter.createParentTrackParCov(); - cascadeTrack.setAbsCharge(-1); // may require more adjustments - cascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas - - thisCascade.cascradiusMC = xiDecayRadius2D; - thisCascade.pt = cascadeTrack.getPt(); - thisCascade.eta = cascadeTrack.getEta(); - thisCascade.findableClusters = 0; - thisCascade.foundClusters = 0; - - if (cascadeDecaySettings.trackXi) { - // optionally, add the points in the layers before the decay of the Xi - // will back-track the perfect MC cascade to relevant layers, find hit, smear and add to smeared cascade - for (int i = fastTracker[icfg]->GetLayers().size() - 1; i >= 0; --i) { - o2::fastsim::DetLayer layer = fastTracker[icfg]->GetLayer(i); - if (layer.isInert()) { - continue; // Not an active tracking layer - } - - if (thisCascade.cascradiusMC < layer.getRadius()) { - continue; // Cascade did not reach this layer - } - - // cascade decayed after the corresponding radius - thisCascade.findableClusters++; // add to findable - - // find perfect intercept XYZ - float targetX = 1e+3; - trackParCov.getXatLabR(layer.getRadius(), targetX, mMagneticField); - if (targetX > 999) { - continue; // failed to find intercept - } - - if (!trackParCov.propagateTo(targetX, mMagneticField)) { - continue; // failed to propagate - } - - // get potential cluster position - std::array posClusterCandidate; - trackParCov.getXYZGlo(posClusterCandidate); - float r{std::hypot(posClusterCandidate[0], posClusterCandidate[1])}; - float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::constants::math::PI}; - - if (layer.getResolutionRPhi() > 1e-8 && layer.getResolutionZ() > 1e-8) { // catch zero (though should not really happen...) - phi = gRandom->Gaus(phi, std::asin(layer.getResolutionRPhi() / r)); - posClusterCandidate[0] = r * std::cos(phi); - posClusterCandidate[1] = r * std::sin(phi); - posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], layer.getResolutionZ()); - } - - if (std::isnan(phi)) { - continue; // Catch when getXatLabR misses layer[i] - } - - // towards adding cluster: move to track alpha - double alpha = cascadeTrack.getAlpha(); - double xyz1[3]{ - TMath::Cos(alpha) * posClusterCandidate[0] + TMath::Sin(alpha) * posClusterCandidate[1], - -TMath::Sin(alpha) * posClusterCandidate[0] + TMath::Cos(alpha) * posClusterCandidate[1], - posClusterCandidate[2]}; - - if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) { - continue; - } - - const o2::track::TrackParametrization::dim2_t hitpoint = {static_cast(xyz1[1]), static_cast(xyz1[2])}; - const o2::track::TrackParametrization::dim3_t hitpointcov = {layer.getResolutionRPhi() * layer.getResolutionRPhi(), 0.f, layer.getResolutionZ() * layer.getResolutionZ()}; - if (layer.isInDeadPhiRegion(phi)) { - continue; // No hit for strangeness tracking update - } - - cascadeTrack.update(hitpoint, hitpointcov); - thisCascade.foundClusters++; // add to findable - } - - if (thisCascade.foundClusters < cascadeDecaySettings.minStraTrackHits) { - continue; // We didn't find enough hits for strangeness tracking - } + if (std::isnan(phi)) { + continue; // Catch when getXatLabR misses layer[i] } - // add cascade track - thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this is the next index to be filled -> should be it - tracksAlice3.push_back(TrackAlice3{cascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); + // towards adding cluster: move to track alpha + double alpha = cascadeTrack.getAlpha(); + double xyz1[3]{ + TMath::Cos(alpha) * posClusterCandidate[0] + TMath::Sin(alpha) * posClusterCandidate[1], + -TMath::Sin(alpha) * posClusterCandidate[0] + TMath::Cos(alpha) * posClusterCandidate[1], + posClusterCandidate[2]}; - // add this cascade to vector (will fill cursor later with collision ID) - cascadesAlice3.push_back(thisCascade); - } - } - } // end cascade building + if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) { + continue; + } - if (isReco[0] && ((cascadeDecaySettings.doKinkReco == 1 && tryKinkReco) || cascadeDecaySettings.doKinkReco == 2)) { // mode 1 or 2 - o2::track::TrackParCov prefectCascadeTrack, trackedCascade; - const o2::track::TrackParCov& trackedBach = xiDaughterTrackParCovsTracked[0]; - o2::upgrade::convertMCParticleToO2Track(mcParticle, prefectCascadeTrack, pdgDB); + const o2::track::TrackParametrization::dim2_t hitpoint = {static_cast(xyz1[1]), static_cast(xyz1[2])}; + const o2::track::TrackParametrization::dim3_t hitpointcov = {layer.getResolutionRPhi() * layer.getResolutionRPhi(), 0.f, layer.getResolutionZ() * layer.getResolutionZ()}; + if (layer.isInDeadPhiRegion(phi)) { + continue; // No hit for strangeness tracking update + } - // back track is already smeared - prefectCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas - const int nCascHits = fastTracker[icfg]->FastTrack(prefectCascadeTrack, trackedCascade, dNdEta, xiDecayRadius2D); - reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? true : false; - if (reconstructedCascade) { - std::array pCasc; - std::array pBach; - std::array pV0; - trackedCascade.getPxPyPzGlo(pCasc); - trackedBach.getPxPyPzGlo(pBach); - for (size_t i = 0; i < pCasc.size(); ++i) { - pV0[i] = pCasc[i] - pBach[i]; + cascadeTrack.update(hitpoint, hitpointcov); + thisCascade.foundClusters++; // add to findable } - if (isReco[1] && !isReco[2]) { - thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 1; - thisCascade.positiveId = -1; - } else if (!isReco[1] && isReco[2]) { - thisCascade.negativeId = -1; - thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; - } else if (isReco[1] && isReco[2]) { - thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; - thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 2; - } else { - thisCascade.positiveId = -1; - thisCascade.negativeId = -1; + if (thisCascade.foundClusters < cascadeDecaySettings.minStraTrackHits) { + return; // We didn't find enough hits for strangeness tracking } + } + tracksCascadeProngs[kCascProngs] = TrackAlice3{cascadeTrack, mcParticle.globalIndex(), trackTime, timeResolutionUs, false, false, 1, thisCascade.foundClusters, TrackType::kGenCascDaug}; + fillCascadeTable = true; + } + } + } // end cascade building + + if (isReco[0] && ((cascadeDecaySettings.doKinkReco == 1 && tryKinkReco) || cascadeDecaySettings.doKinkReco == 2)) { // mode 1 or 2 + o2::track::TrackParCov trackedCascade; + const o2::track::TrackParCov& trackedBach = xiDaughterTrackParCovsTracked[0]; + const int nCascHits = fastTracker[icfg]->FastTrack(perfectCascadeTrack, trackedCascade, dNdEta, xiDecayRadius2D); + reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? true : false; + if (reconstructedCascade) { + std::array pCasc; + std::array pBach; + std::array pV0; + trackedCascade.getPxPyPzGlo(pCasc); + trackedBach.getPxPyPzGlo(pBach); + for (size_t i = 0; i < pCasc.size(); ++i) { + pV0[i] = pCasc[i] - pBach[i]; + } - int nCand = 0; - bool kinkFitterOK = true; - try { - nCand = fitter.process(trackedCascade, trackedBach); - } catch (...) { - kinkFitterOK = false; - } + // Reset indices + if (!isReco[1]) { + thisCascade.negativeId = -1; + } + if (!isReco[2]) { + thisCascade.positiveId = -1; + } - if (nCand == 0) { - kinkFitterOK = false; - } + int nCand = 0; + bool kinkFitterOK = true; + try { + nCand = fitter.process(trackedCascade, trackedBach); + } catch (...) { + kinkFitterOK = false; + } - fitter.propagateTracksToVertex(); - if (!fitter.isPropagateTracksToVertexDone()) { - kinkFitterOK = false; - } + if (nCand == 0) { + kinkFitterOK = false; + } - const u_int8_t fitterStatusCode = fitter.getFitStatus(); - histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); - if (kinkFitterOK) { - if (cascadeDecaySettings.doXiQA) { - getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f); - } + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + kinkFitterOK = false; + } - o2::track::TrackParCov newCascadeTrack = fitter.getTrack(0); // (cascade) - std::array kinkVtx = {-999, -999, -999}; - kinkVtx = fitter.getPCACandidatePos(); - thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - isReco.size(); - thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this should be ok - thisCascade.dcaV0dau = -1.f; // unknown - thisCascade.v0radius = -1.f; // unknown - thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate()); - thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]); - thisCascade.cascradiusMC = xiDecayRadius2D; - thisCascade.mLambda = o2::constants::physics::MassLambda; - thisCascade.findableClusters = nCascHits; - thisCascade.foundClusters = nCascHits; - thisCascade.pt = newCascadeTrack.getPt(); - thisCascade.eta = newCascadeTrack.getEta(); - thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]}, std::array{pV0[0], pV0[1], pV0[2]}}, - std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); - - newCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas - tracksAlice3.push_back(TrackAlice3{newCascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); - - // add this cascade to vector (will fill cursor later with collision ID) - cascadesAlice3.push_back(thisCascade); - } // end fitter OK - } // end cascade found - } // end cascade kink building - - // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ - if (cascadeDecaySettings.doXiQA) { - if (reconstructedCascade) { - getHist(TH2, histPath + "hRecoXi")->Fill(xiDecayRadius2D, mcParticle.pt()); - getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda); - getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi); - getHist(TH2, histPath + "h2dMassXi")->Fill(thisCascade.mXi, thisCascade.pt); - getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(thisCascade.pt, (mcParticle.pt() - thisCascade.pt) / thisCascade.pt); - getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(thisCascade.pt, mcParticle.eta() - thisCascade.eta); - getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters); - } - if (isReco[0]) { - getHist(TH2, histPath + "hRecoPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); - } - if (isReco[1]) { - getHist(TH2, histPath + "hRecoPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + if (kinkFitterOK) { + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(7.0f); } - if (isReco[2]) { - getHist(TH2, histPath + "hRecoPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); + + o2::track::TrackParCov newCascadeTrack = fitter.getTrack(0); // (cascade) + std::array kinkVtx = {-999, -999, -999}; + kinkVtx = fitter.getPCACandidatePos(); + thisCascade.dcaV0dau = -1.f; // unknown + thisCascade.v0radius = -1.f; // unknown + thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]); + thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.mLambda = o2::constants::physics::MassLambda; + thisCascade.findableClusters = nCascHits; + thisCascade.foundClusters = nCascHits; + thisCascade.pt = newCascadeTrack.getPt(); + thisCascade.eta = newCascadeTrack.getEta(); + thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]}, std::array{pV0[0], pV0[1], pV0[2]}}, + std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); + newCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + float trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + if (reconstructedCascade) { + tracksCascadeProngs[kCascProngs + 1] = TrackAlice3{newCascadeTrack, mcParticle.globalIndex(), trackTime, timeResolutionUs, false, false, 1, thisCascade.foundClusters, TrackType::kRecoCascDaug}; } + fillCascadeTable = true; + } // end fitter OK + } // end cascade found + } // end cascade kink building + + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + if (cascadeDecaySettings.doXiQA) { + double dcaXY{-1.}, dcaZ{-1.}; + if (reconstructedCascade) { + getHist(TH2, histPath + "hRecoXi")->Fill(xiDecayRadius2D, mcParticle.pt()); + getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda); + getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi); + getHist(TH2, histPath + "h2dMassXi")->Fill(thisCascade.mXi, thisCascade.pt); + getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(thisCascade.pt, (mcParticle.pt() - thisCascade.pt) / thisCascade.pt); + getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(thisCascade.pt, mcParticle.eta() - thisCascade.eta); + getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters); + + o2::track::TrackParCov trackParametrization(xiTrackParCov); + trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo); + getHist(TH2, histPath + "h2dDCAxyCascade")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascade")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please + } + if (isReco[0]) { + getHist(TH2, histPath + "hRecoPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); + o2::track::TrackParCov trackParametrizationCascProng0(xiTrackParCov); + if (populateTracksDCA && xiTrackParCov.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { // FIXME: this is not the right trackParametrization, need to propagate the bachelor track + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + getHist(TH2, histPath + "h2dDCAxyCascadeBachelor")->Fill(trackParametrizationCascProng0.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadeBachelor")->Fill(trackParametrizationCascProng0.getPt(), dcaZ * 1e+4); // in microns, please + } + } + if (isReco[1]) { + getHist(TH2, histPath + "hRecoPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); + o2::track::TrackParCov trackParametrizationCascProng1(xiTrackParCov); + if (populateTracksDCA && xiTrackParCov.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { // FIXME: this is not the right trackParametrization, need to propagate the negative pion track + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + getHist(TH2, histPath + "h2dDCAxyCascadeNegative")->Fill(trackParametrizationCascProng1.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadeNegative")->Fill(trackParametrizationCascProng1.getPt(), dcaZ * 1e+4); // in microns, please + } + } + if (isReco[2]) { + getHist(TH2, histPath + "hRecoPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); + o2::track::TrackParCov trackParametrizationCascProng2(xiTrackParCov); + if (populateTracksDCA && xiTrackParCov.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { // FIXME: this is not the right trackParametrization, need to propagate the positive proton track + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + getHist(TH2, histPath + "h2dDCAxyCascadePositive")->Fill(trackParametrizationCascProng2.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadePositive")->Fill(trackParametrizationCascProng2.getPt(), dcaZ * 1e+4); // in microns, please } - - continue; // Cascade handling done, should not be considered anymore } + } - // V0 handling - std::vector v0DaughterTrackParCovsPerfect(2); - std::vector v0DaughterTrackParCovsTracked(2); - std::vector isV0Reco(kv0Prongs); - std::vector nV0Hits(kv0Prongs); // total - std::vector nV0SiliconHits(kv0Prongs); // silicon type - std::vector nV0TPCHits(kv0Prongs); // TPC type - if (v0DecaySettings.decayV0 && isV0) { - if (v0DecaySettings.doV0QA) { - fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 0.0f); + if (!fillCascadeTable) { + tracksCascadeProngs.clear(); // clear the tracks added for this cascade since we won't be filling the table + return; + } + + // populate Cascades + tableUpgradeCascades(tableCollisions.lastIndex(), + thisCascade.cascadeTrackId, + thisCascade.positiveId, + thisCascade.negativeId, + thisCascade.bachelorId, + thisCascade.dcaV0dau, + thisCascade.dcacascdau, + thisCascade.v0radius, + thisCascade.cascradius, + thisCascade.cascradiusMC, + thisCascade.mLambda, + thisCascade.mXi, + thisCascade.findableClusters, + thisCascade.foundClusters); + } + + /// Function to study V0s and fill the relevant histograms + /// \param trackTableOffset offset to be added to the indices of the daughter tracks when filling the V0 table + /// \param mcParticle the MC particle corresponding to the V0 to be studied + /// \param tracksV0Daugs vector of tracks to which the V0 daughters will be added + /// \param icfg index of the current configuration, used for histogram filling + /// \param dNdEta multiplicity of the event, used for fast tracker smearing + /// \param eventCollisionTimeNS collision time of the event in nanoseconds, used for track time smearing + template + void studyV0(const int trackTableOffset, + const McParticleType& mcParticle, + std::vector& tracksV0Daugs, + int icfg, + int dNdEta, + float eventCollisionTimeNS) + { + o2::track::TrackParCov trackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + + std::vector v0DecayProducts; + std::vector laDecayVertex, v0DecayVertex; + decayV0Particle(mcParticle, v0DecayProducts, v0DecayVertex, mcParticle.pdgCode()); + if (v0DecayProducts.size() != 2) { + LOG(fatal) << "V0 decay did not produce 2 daughters as expected!"; + } + double v0DecayRadius2D = std::hypot(v0DecayVertex[0], v0DecayVertex[1]); + + if (v0DecaySettings.doV0QA) { + for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { + if (mcParticle.pdgCode() != v0PDGs[indexV0]) { + continue; } - switch (mcParticle.pdgCode()) { - case kK0Short: - o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); - o2::upgrade::convertTLorentzVectorToO2Track(kPiPlus, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); - break; - case kLambda0: - o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); - o2::upgrade::convertTLorentzVectorToO2Track(kProton, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); - break; - case kLambda0Bar: - o2::upgrade::convertTLorentzVectorToO2Track(kProtonBar, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); - o2::upgrade::convertTLorentzVectorToO2Track(kPiPlus, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); - break; - default: - LOG(fatal) << "Unhandled V0 PDG code " << mcParticle.pdgCode(); + for (int indexDetector = 0; indexDetector < mGeoContainer.getNumberOfConfigurations(); indexDetector++) { + std::string path = Form("V0Building_Configuration_%i/%s/", indexDetector, NameV0s[indexV0].data()); + fillHist(TH2, path + "hGen", v0DecayRadius2D, mcParticle.pt()); + fillHist(TH2, path + "hGenNegDaughterFromV0", v0DecayRadius2D, v0DecayProducts[0].Pt()); + fillHist(TH2, path + "hGenPosDaughterFromV0", v0DecayRadius2D, v0DecayProducts[1].Pt()); } - for (int i = 0; i < kv0Prongs; i++) { - isV0Reco[i] = false; - nV0Hits[i] = 0; - nV0SiliconHits[i] = 0; - nV0TPCHits[i] = 0; - if (enableSecondarySmearing) { - nV0Hits[i] = fastTracker[icfg]->FastTrack(v0DaughterTrackParCovsPerfect[i], v0DaughterTrackParCovsTracked[i], dNdEta); - nV0SiliconHits[i] = fastTracker[icfg]->GetNSiliconPoints(); - nV0TPCHits[i] = fastTracker[icfg]->GetNGasPoints(); - - if (nV0Hits[i] < 0 && v0DecaySettings.doV0QA) { // QA - fillHist(TH1, Form("V0Building_Configuration_%i/hFastTrackerQA", icfg), o2::math_utils::abs(nV0Hits[i])); - } + } + } - if (nV0SiliconHits[i] >= fastTrackerSettings.minSiliconHits || (nV0SiliconHits[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nV0TPCHits[i] >= fastTrackerSettings.minTPCClusters)) { - isReco[i] = true; - } else { - continue; // extra sure - } - for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits() && v0DecaySettings.doV0QA; ih++) { - fillHist(TH2, Form("V0Building_Configuration_%i/hFastTrackerHits", icfg), fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); - } - } else { - isReco[i] = true; - v0DaughterTrackParCovsTracked[i] = v0DaughterTrackParCovsPerfect[i]; - } + // V0 handling + std::vector v0DaughterTrackParCovsPerfect(2); + std::vector v0DaughterTrackParCovsTracked(2); + std::vector isV0Reco(kv0Prongs); + std::vector nV0Hits(kv0Prongs); // total + std::vector nV0SiliconHits(kv0Prongs); // silicon type + std::vector nV0TPCHits(kv0Prongs); // TPC type + if (v0DecaySettings.doV0QA) { + fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 0.0f); + } + switch (mcParticle.pdgCode()) { + case kK0Short: + o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); + o2::upgrade::convertTLorentzVectorToO2Track(kPiPlus, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); + break; + case kLambda0: + o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); + o2::upgrade::convertTLorentzVectorToO2Track(kProton, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); + break; + case kLambda0Bar: + o2::upgrade::convertTLorentzVectorToO2Track(kProtonBar, v0DecayProducts[0], v0DecayVertex, v0DaughterTrackParCovsPerfect[0], pdgDB); + o2::upgrade::convertTLorentzVectorToO2Track(kPiPlus, v0DecayProducts[1], v0DecayVertex, v0DaughterTrackParCovsPerfect[1], pdgDB); + break; + default: + LOG(fatal) << "Unhandled V0 PDG code " << mcParticle.pdgCode(); + } - // if (TMath::IsNaN(v0DaughterTrackParCovsTracked[i].getZ())) { - // continue; - // } else { - // histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); - // } - if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); - } else { - ghostTracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); - } + // Store not reconstructed daughters, will update them in case reconstruction is successful + float trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksV0Daugs.push_back(TrackAlice3{v0DaughterTrackParCovsPerfect[0], mcParticle.globalIndex(), 0.f, timeResolutionUs, true, true, 1, TrackType::kGhostV0Daug}); + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + tracksV0Daugs.push_back(TrackAlice3{v0DaughterTrackParCovsPerfect[1], mcParticle.globalIndex(), 0.f, timeResolutionUs, true, true, 1, TrackType::kGhostV0Daug}); + + bool fillV0Table{false}; + for (int i = 0; i < kv0Prongs; i++) { + isV0Reco[i] = false; + nV0Hits[i] = 0; + nV0SiliconHits[i] = 0; + nV0TPCHits[i] = 0; + if (enableSecondarySmearing) { + nV0Hits[i] = fastTracker[icfg]->FastTrack(v0DaughterTrackParCovsPerfect[i], v0DaughterTrackParCovsTracked[i], dNdEta); + nV0SiliconHits[i] = fastTracker[icfg]->GetNSiliconPoints(); + nV0TPCHits[i] = fastTracker[icfg]->GetNGasPoints(); + + if (nV0SiliconHits[i] >= fastTrackerSettings.minSiliconHits || + (nV0SiliconHits[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && + nV0TPCHits[i] >= fastTrackerSettings.minTPCClusters)) { + isV0Reco[i] = true; + } else { + continue; // extra sure } - if (v0DecaySettings.doV0QA) { - if (isReco[0] && isReco[1]) { - fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 1.0f); - for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { - if (mcParticle.pdgCode() == v0PDGs[indexV0]) { - fillHist(TH2, Form("V0Building_Configuration_%i/%s/hReco", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, mcParticle.pt()); - } - } - } - if (isReco[0]) { - for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { - if (mcParticle.pdgCode() == v0PDGs[indexV0]) { - fillHist(TH2, Form("V0Building_Configuration_%i/%s/hRecoNegDaughterFromV0", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, v0DecayProducts[0].Pt()); - } - } + + if (v0DecaySettings.doV0QA) { // QA + if (nV0Hits[i] < 0) { + fillHist(TH1, Form("V0Building_Configuration_%i/hFastTrackerQA", icfg), o2::math_utils::abs(nV0Hits[i])); } - if (isReco[1]) { - for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { - if (mcParticle.pdgCode() == v0PDGs[indexV0]) { - fillHist(TH2, Form("V0Building_Configuration_%i/%s/hRecoPosDaughterFromV0", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, v0DecayProducts[1].Pt()); - } - } + for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits(); ih++) { + fillHist(TH2, Form("V0Building_Configuration_%i/hFastTrackerHits", icfg), fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); } } + } else { + isV0Reco[i] = true; + v0DaughterTrackParCovsTracked[i] = v0DaughterTrackParCovsPerfect[i]; + } - // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ - // combine particles into actual V0 candidate - // V0 building starts here - if (v0DecaySettings.findV0 && isReco[0] && isReco[1]) { - if (v0DecaySettings.doV0QA) { - fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 2.0f); + trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + // TODO: flag to separate ghost and reco tracks + TrackType trackType = isV0Reco[i] ? TrackType::kRecoV0Daug : TrackType::kGhostV0Daug; + tracksV0Daugs[i] = TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), trackTime, timeResolutionUs, true, true, i + 2, trackType}; + } + if (v0DecaySettings.doV0QA) { + if (isV0Reco[0] && isV0Reco[1]) { + fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 1.0f); + for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { + if (mcParticle.pdgCode() == v0PDGs[indexV0]) { + fillHist(TH2, Form("V0Building_Configuration_%i/%s/hReco", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, mcParticle.pt()); } - - // assign indices of the particles we've used - // they should be the last ones to be filled, in order: - // n-1: positive Track from V0 - // n-2: negative Track from V0 - thisV0.positiveId = lastTrackIndex + tracksAlice3.size() - 1; - thisV0.negativeId = lastTrackIndex + tracksAlice3.size() - 2; - thisV0.mcParticleId = mcParticle.globalIndex(); - // use DCA fitters - int nCand = 0; - bool dcaFitterOK_V0 = true; - try { - nCand = fitter.process(v0DaughterTrackParCovsTracked[0], v0DaughterTrackParCovsTracked[1]); - } catch (...) { - // LOG(error) << "Exception caught in DCA fitter process call!"; - dcaFitterOK_V0 = false; + } + } + if (isV0Reco[0]) { + for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { + if (mcParticle.pdgCode() == v0PDGs[indexV0]) { + fillHist(TH2, Form("V0Building_Configuration_%i/%s/hRecoNegDaughterFromV0", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, v0DecayProducts[0].Pt()); } - if (nCand == 0) { - dcaFitterOK_V0 = false; + } + } + if (isV0Reco[1]) { + for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { + if (mcParticle.pdgCode() == v0PDGs[indexV0]) { + fillHist(TH2, Form("V0Building_Configuration_%i/%s/hRecoPosDaughterFromV0", icfg, NameV0s[indexV0].data()), v0DecayRadius2D, v0DecayProducts[1].Pt()); } + } + } + } - fitter.propagateTracksToVertex(); - if (!fitter.isPropagateTracksToVertexDone()) { - dcaFitterOK_V0 = false; - } + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + // combine particles into actual V0 candidate + // V0 building starts here + if (v0DecaySettings.findV0 && isV0Reco[0] && isV0Reco[1]) { + if (v0DecaySettings.doV0QA) { + fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 2.0f); + } - const u_int8_t fitterStatusCode = fitter.getFitStatus(); - histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); - // V0 found successfully - if (dcaFitterOK_V0) { - if (v0DecaySettings.doV0QA) { - fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 3.0f); - } + // assign indices of the daughter particles + thisV0.mcParticleId = mcParticle.globalIndex(); + thisV0.negativeId = trackTableOffset + 1; + thisV0.positiveId = trackTableOffset + 2; + + // use DCA fitters + int nCand = 0; + bool dcaFitterV0Status = true; + try { + nCand = fitter.process(v0DaughterTrackParCovsTracked[0], v0DaughterTrackParCovsTracked[1]); + } catch (...) { + // LOG(error) << "Exception caught in DCA fitter process call!"; + dcaFitterV0Status = false; + } + if (nCand == 0) { + dcaFitterV0Status = false; + } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterV0Status = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + // V0 found successfully + if (dcaFitterV0Status) { + if (v0DecaySettings.doV0QA) { + fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 3.0f); + } - std::array pos; - std::array posP; - std::array negP; + std::array pos; + std::array posP; + std::array negP; - o2::track::TrackParCov pTrackAtPCA = fitter.getTrack(1); // (positive) - o2::track::TrackParCov nTrackAtPCA = fitter.getTrack(0); // (negative) - pTrackAtPCA.getPxPyPzGlo(posP); - nTrackAtPCA.getPxPyPzGlo(negP); + o2::track::TrackParCov pTrackAtPCA = fitter.getTrack(1); // (positive) + o2::track::TrackParCov nTrackAtPCA = fitter.getTrack(0); // (negative) + pTrackAtPCA.getPxPyPzGlo(posP); + nTrackAtPCA.getPxPyPzGlo(negP); - // get decay vertex coordinates - const auto& vtx = fitter.getPCACandidate(); - for (int i = 0; i < 3; i++) { - pos[i] = vtx[i]; - } + // get decay vertex coordinates + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + pos[i] = vtx[i]; + } - // calculate basic V0 properties here - // DCA to PV taken care of in daughter tracks already, not necessary - thisV0.dcaV0dau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - thisV0.v0radius = std::hypot(pos[0], pos[1]); - thisV0.pt = std::hypot(std::cos(v0DaughterTrackParCovsTracked[0].getPhi()) * v0DaughterTrackParCovsTracked[0].getPt() + std::cos(v0DaughterTrackParCovsTracked[1].getPhi()) * v0DaughterTrackParCovsTracked[1].getPt(), - std::sin(v0DaughterTrackParCovsTracked[0].getPhi()) * v0DaughterTrackParCovsTracked[0].getPt() + std::sin(v0DaughterTrackParCovsTracked[1].getPhi()) * v0DaughterTrackParCovsTracked[1].getPt()); - if (std::abs(mcParticle.pdgCode()) == kK0Short) { - thisV0.mK0 = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, + // calculate basic V0 properties here + // DCA to PV taken care of in daughter tracks already, not necessary + thisV0.dcaV0dau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + thisV0.v0radius = std::hypot(pos[0], pos[1]); + thisV0.pt = std::hypot(std::cos(v0DaughterTrackParCovsTracked[0].getPhi()) * v0DaughterTrackParCovsTracked[0].getPt() + std::cos(v0DaughterTrackParCovsTracked[1].getPhi()) * v0DaughterTrackParCovsTracked[1].getPt(), + std::sin(v0DaughterTrackParCovsTracked[0].getPhi()) * v0DaughterTrackParCovsTracked[0].getPt() + std::sin(v0DaughterTrackParCovsTracked[1].getPhi()) * v0DaughterTrackParCovsTracked[1].getPt()); + + thisV0.mK0 = -1, thisV0.mLambda = -1, thisV0.mAntiLambda = -1; // initialize to unphysical values + if (std::abs(mcParticle.pdgCode()) == kK0Short) { + thisV0.mK0 = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, + std::array{negP[0], negP[1], negP[2]}}, + std::array{o2::constants::physics::MassPionCharged, + o2::constants::physics::MassPionCharged}); + } + + if (mcParticle.pdgCode() == kLambda0) { + thisV0.mLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassPionCharged, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - } else { - thisV0.mK0 = -1; - } + } - if (mcParticle.pdgCode() == kLambda0) { - thisV0.mLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, + if (mcParticle.pdgCode() == kLambda0Bar) { + thisV0.mAntiLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassProton, - o2::constants::physics::MassPionCharged}); - } else { - thisV0.mLambda = -1; - } - - if (mcParticle.pdgCode() == kLambda0Bar) { - thisV0.mAntiLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, - std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassPionCharged, - o2::constants::physics::MassProton}); - } else { - thisV0.mAntiLambda = -1; - } - - if (v0DecaySettings.doV0QA) { - fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 4.0f); - if (std::abs(mcParticle.pdgCode()) == kK0Short) { - fillHist(TH2, Form("V0Building_Configuration_%i/K0/hMass", icfg), thisV0.mK0, thisV0.pt); - } - if (mcParticle.pdgCode() == kLambda0) { - fillHist(TH2, Form("V0Building_Configuration_%i/Lambda/hMass", icfg), thisV0.mLambda, thisV0.pt); - } - if (mcParticle.pdgCode() == kLambda0Bar) { - fillHist(TH2, Form("V0Building_Configuration_%i/AntiLambda/hMass", icfg), thisV0.mAntiLambda, thisV0.pt); - } - } + std::array{o2::constants::physics::MassPionCharged, + o2::constants::physics::MassProton}); + } - // add this V0 to vector (will fill cursor later with collision ID) - v0sAlice3.push_back(thisV0); + if (v0DecaySettings.doV0QA) { + fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 4.0f); + if (std::abs(mcParticle.pdgCode()) == kK0Short) { + fillHist(TH2, Form("V0Building_Configuration_%i/K0/hMass", icfg), thisV0.mK0, thisV0.pt); + } + if (mcParticle.pdgCode() == kLambda0) { + fillHist(TH2, Form("V0Building_Configuration_%i/Lambda/hMass", icfg), thisV0.mLambda, thisV0.pt); + } + if (mcParticle.pdgCode() == kLambda0Bar) { + fillHist(TH2, Form("V0Building_Configuration_%i/AntiLambda/hMass", icfg), thisV0.mAntiLambda, thisV0.pt); } } - } - if (doExtraQA) { - histos.fill(HIST("hSimTrackX"), trackParCov.getX()); - } - if (isV0) { - continue; // V0 handling done, should not be considered anymore + LOG(info) << "Will fill V0 table for MC particle with PDG " << mcParticle.pdgCode() << " and global index " << mcParticle.globalIndex(); + fillV0Table = true; } + } - bool reconstructed = true; - int nTrkHits = 0; - if (enablePrimarySmearing && !fastPrimaryTrackerSettings.fastTrackPrimaries) { - reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); - nTrkHits = fastTrackerSettings.minSiliconHits; - } else if (fastPrimaryTrackerSettings.fastTrackPrimaries) { - o2::track::TrackParCov o2Track; - o2::upgrade::convertMCParticleToO2Track(mcParticle, o2Track, pdgDB); - o2Track.setPID(pdgCodeToPID(mcParticle.pdgCode())); - nTrkHits = fastTracker[icfg]->FastTrack(o2Track, trackParCov, dNdEta); - if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { - reconstructed = false; - } - } + if (!fillV0Table) { + tracksV0Daugs.clear(); // clear the tracks added for this V0 since we won't be filling the table + return; // don't fill the table if we didn't find a V0 candidate + } - if (!reconstructed && !processUnreconstructedTracks) { - continue; - } - if (TMath::IsNaN(trackParCov.getZ())) { - // capture rare smearing mistakes / corrupted tracks - histos.fill(HIST("hNaNBookkeeping"), 0.0f, 0.0f); - continue; - } else { - histos.fill(HIST("hNaNBookkeeping"), 0.0f, 1.0f); // ok! - } + // populate V0s + tableUpgradeV0s(tableCollisions.lastIndex(), // now we know the collision index -> populate table + thisV0.mcParticleId, + thisV0.positiveId, + thisV0.negativeId, + thisV0.dcaV0dau, + thisV0.v0radius, + thisV0.mLambda, + thisV0.mAntiLambda, + thisV0.mK0, + thisV0.pt); + } - // Base QA (note: reco pT here) - if (enablePrimarySmearing) { - getHist(TH1, histPath + "hPtReconstructed")->Fill(trackParCov.getPt()); - if (std::abs(mcParticle.pdgCode()) == kElectron) - getHist(TH1, histPath + "hPtReconstructedEl")->Fill(trackParCov.getPt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) - getHist(TH1, histPath + "hPtReconstructedPi")->Fill(trackParCov.getPt()); - if (std::abs(mcParticle.pdgCode()) == kKPlus) - getHist(TH1, histPath + "hPtReconstructedKa")->Fill(trackParCov.getPt()); - if (std::abs(mcParticle.pdgCode()) == kProton) - getHist(TH1, histPath + "hPtReconstructedPr")->Fill(trackParCov.getPt()); - } - if (doExtraQA) { - getHist(TH2, histPath + "h2dPtRes")->Fill(trackParCov.getPt(), (trackParCov.getPt() - mcParticle.pt()) / trackParCov.getPt()); - histos.fill(HIST("hRecoTrackX"), trackParCov.getX()); - } + /// Function to compute the primary vertex position using the provided tracks and MC collision information + /// \param mcCollision the MC collision information, used to get the true vertex position for comparison + /// \param prmTrks the vector of tracks to be used for vertex reconstruction + /// \param primaryVertex the output variable where the computed primary vertex will be stored + /// \param icfg index of the current configuration, used for histogram filling + template + void computeVertex(McCollisionType& mcCollision, const std::vector& prmTrks, o2::vertexing::PVertex& primaryVertex, const int icfg) + { - // populate vector with track if we reco-ed it - if (reconstructed) { - tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); - } else { - ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); - } + if (!enablePrimaryVertexing) { + primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + return; + } + vertexReconstructionEfficiencyCounters.first += 1; + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + fillHist(TH1, histPath + "hVtxMultGen", prmTrks.size()); + std::vector lblTracks; + std::vector vertices; + std::vector vertexTrackIDs; + std::vector v2tRefs; + std::vector lblVtx; + lblVtx.emplace_back(mcCollision.globalIndex(), 1); + std::vector idxVec; // store IDs + + idxVec.reserve(prmTrks.size()); + for (unsigned i = 0; i < prmTrks.size(); i++) { + lblTracks.emplace_back(prmTrks[i].mcLabel, mcCollision.globalIndex(), 1, false); + idxVec.emplace_back(i, o2::dataformats::GlobalTrackID::ITS); // let's say ITS } - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - // Calculate primary vertex with tracks from this collision - // data preparation - o2::vertexing::PVertex primaryVertex; - if (enablePrimaryVertexing) { - LOG(debug) << "Starting primary vertexing with " << tracksAlice3.size() << " tracks."; - fillHist(TH1, histPath + "hVtxMultGen", tracksAlice3.size()); - std::vector lblTracks; - std::vector vertices; - std::vector vertexTrackIDs; - std::vector v2tRefs; - std::vector lblVtx; - lblVtx.emplace_back(mcCollision.globalIndex(), 1); - std::vector idxVec; // store IDs - - idxVec.reserve(tracksAlice3.size()); - for (unsigned i = 0; i < tracksAlice3.size(); i++) { - lblTracks.emplace_back(tracksAlice3[i].mcLabel, mcCollision.globalIndex(), 1, false); - idxVec.emplace_back(i, o2::dataformats::GlobalTrackID::ITS); // let's say ITS - } + getHist(TH1, histPath + "hVtxTrials")->Fill(0); // Tried vertexing - getHist(TH1, histPath + "hVtxTrials")->Fill(0); // Tried vertexing - - // Calculate vertices - const int n_vertices = vertexer.process(tracksAlice3, // track array - idxVec, - gsl::span{bcData}, - vertices, - vertexTrackIDs, - v2tRefs, - gsl::span{lblTracks}, - lblVtx); - - LOG(debug) << "Vertex reconstruction efficiency " << vertexReconstructionEfficiencyCounters.second << "/" << vertexReconstructionEfficiencyCounters.first << "=" << vertexReconstructionEfficiencyCounters.second / vertexReconstructionEfficiencyCounters.first; - if (n_vertices < 1) { - LOG(debug) << "Vertexing completed, no vtx found."; - if (doExtraQA) { - histos.fill(HIST("h1dVerticesNotReco"), tracksAlice3.size()); - } - return; // primary vertex not reconstructed - } - vertexReconstructionEfficiencyCounters.second += 1; - getHist(TH1, histPath + "hVtxTrials")->Fill(1); // Succeeded vertexing - LOG(debug) << "Vertexing completed with " << n_vertices << " vertices found."; - - // Find largest vertex - int largestVertex = 0; - for (Int_t iv = 1; iv < n_vertices; iv++) { - if (vertices[iv].getNContributors() > vertices[largestVertex].getNContributors()) { - largestVertex = iv; - } - } - primaryVertex = vertices[largestVertex]; + // Calculate vertices + const int n_vertices = vertexer.process(prmTrks, // track array + idxVec, + gsl::span{bcData}, + vertices, + vertexTrackIDs, + v2tRefs, + gsl::span{lblTracks}, + lblVtx); + + if (n_vertices < 1) { if (doExtraQA) { - histos.fill(HIST("h2dVerticesVsContributors"), primaryVertex.getNContributors(), n_vertices); + histos.fill(HIST("h1dVerticesNotReco"), prmTrks.size()); } - fillHist(TH1, histPath + "hVtxMultReco", primaryVertex.getNContributors()); - fillHist(TH1, histPath + "hDeltaMultPVRecoGen", static_cast(primaryVertex.getNContributors()) - static_cast(tracksAlice3.size())); - fillHist(TH1, histPath + "hDeltaXPVRecoGen", primaryVertex.getX() - mcCollision.posX()); - fillHist(TH1, histPath + "hDeltaYPVRecoGen", primaryVertex.getY() - mcCollision.posY()); - fillHist(TH1, histPath + "hDeltaZPVRecoGen", primaryVertex.getZ() - mcCollision.posZ()); - } else { - primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + return; // primary vertex not reconstructed } - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - - // debug / informational - getHist(TH1, histPath + "hSimMultiplicity")->Fill(multiplicityCounter); - getHist(TH1, histPath + "hRecoMultiplicity")->Fill(tracksAlice3.size()); - getHist(TH1, histPath + "hPVz")->Fill(primaryVertex.getZ()); - + vertexReconstructionEfficiencyCounters.second += 1; + getHist(TH1, histPath + "hVtxTrials")->Fill(1); // Succeeded vertexing + + // Find largest vertex + int largestVertex = 0; + for (Int_t iv = 1; iv < n_vertices; iv++) { + if (vertices[iv].getNContributors() > vertices[largestVertex].getNContributors()) { + largestVertex = iv; + } + } + primaryVertex = vertices[largestVertex]; if (doExtraQA) { - histos.fill(HIST("hRecoVsSimMultiplicity"), multiplicityCounter, tracksAlice3.size()); + histos.fill(HIST("h2dVerticesVsContributors"), primaryVertex.getNContributors(), n_vertices); } + fillHist(TH1, histPath + "hVtxMultReco", primaryVertex.getNContributors()); + fillHist(TH1, histPath + "hDeltaMultPVRecoGen", static_cast(primaryVertex.getNContributors()) - static_cast(prmTrks.size())); + fillHist(TH2, histPath + "hDeltaXPVRecoGen", primaryVertex.getX() - mcCollision.posX(), primaryVertex.getNContributors()); + fillHist(TH2, histPath + "hDeltaYPVRecoGen", primaryVertex.getY() - mcCollision.posY(), primaryVertex.getNContributors()); + fillHist(TH2, histPath + "hDeltaZPVRecoGen", primaryVertex.getZ() - mcCollision.posZ(), primaryVertex.getNContributors()); + } - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - // populate collisions - tableCollisions(-1, // BC is irrelevant in synthetic MC tests for now, could be adjusted in future - primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), - primaryVertex.getSigmaX2(), primaryVertex.getSigmaXY(), primaryVertex.getSigmaY2(), - primaryVertex.getSigmaXZ(), primaryVertex.getSigmaYZ(), primaryVertex.getSigmaZ2(), - 0, primaryVertex.getChi2(), primaryVertex.getNContributors(), - eventCollisionTimeNS, 0.f); // For the moment the event collision time is taken as the "GEANT" time, the computation of the event time is done a posteriori from the tracks in the OTF TOF PID task - tableMcCollisionLabels(mcCollision.globalIndex(), 0); - tableCollisionsAlice3(dNdEta); - tableOTFLUTConfigId(icfg); // Populate OTF LUT configuration ID - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + /// Function to fill track information into the relevant tables and histograms + /// \param tracks the vector of tracks to be processed + /// \param primaryVertex the primary vertex position, used for DCA calculation + /// \param icfg index of the current configuration, used for histogram filling + void fillTracksInfo(std::vector const& tracks, o2::vertexing::PVertex const& primaryVertex, const int icfg) + { + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - // populate tracks - LOG(debug) << "Populating " << tracksAlice3.size() << " tracks."; - for (const auto& trackParCov : tracksAlice3) { + for (const auto& trackParCov : tracks) { // Fixme: collision index could be changeable aod::track::TrackTypeEnum trackType = aod::track::Track; @@ -1721,24 +1715,6 @@ struct OnTheFlyTracker { getHist(TH2, histPath + "h2dDCAz")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); } - if (cascadeDecaySettings.doXiQA) { - if (trackParCov.isUsedInCascading == 1) { - getHist(TH2, histPath + "h2dDCAxyCascade")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - getHist(TH2, histPath + "h2dDCAzCascade")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please - } - if (trackParCov.isUsedInCascading == 2) { - getHist(TH2, histPath + "h2dDCAxyCascadeBachelor")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - getHist(TH2, histPath + "h2dDCAzCascadeBachelor")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please - } - if (trackParCov.isUsedInCascading == 3) { - getHist(TH2, histPath + "h2dDCAxyCascadeNegative")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - getHist(TH2, histPath + "h2dDCAzCascadeNegative")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please - } - if (trackParCov.isUsedInCascading == 4) { - getHist(TH2, histPath + "h2dDCAxyCascadePositive")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - getHist(TH2, histPath + "h2dDCAzCascadePositive")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please - } - } tableTracksDCA(dcaXY, dcaZ); if (populateTracksDCACov) { tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); @@ -1755,7 +1731,7 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tableMcTrackLabels(trackParCov.mcLabel, 0); - tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); + tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits, trackParCov.trackType); // populate extra tables if required to do so if (populateTracksExtra) { @@ -1770,97 +1746,181 @@ struct OnTheFlyTracker { } tableTracksAlice3(true); } + } - // populate ghost tracks - LOG(debug) << "Populating " << ghostTracksAlice3.size() << " ghost tracks."; - for (const auto& trackParCov : ghostTracksAlice3) { - // Fixme: collision index could be changeable - aod::track::TrackTypeEnum trackType = aod::track::Track; + void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) + { + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - if (populateTracksDCA) { - float dcaXY = 1e+10, dcaZ = 1e+10; - o2::track::TrackParCov trackParametrization(trackParCov); - if (trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { - dcaXY = dcaInfo.getY(); - dcaZ = dcaInfo.getZ(); - } - if (doExtraQA && (!extraQAwithoutDecayDaughters || (extraQAwithoutDecayDaughters && !trackParCov.isDecayDau))) { - histos.fill(HIST("h2dDCAxy"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - histos.fill(HIST("h2dDCAz"), trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please - histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); - } - tableTracksDCA(dcaXY, dcaZ); - if (populateTracksDCACov) { - tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); - } + std::vector genCascades; + std::vector genV0s; + bcData.clear(); + recoPrimaries.clear(); + ghostPrimaries.clear(); + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // Study collision and perform vertexing + float dNdEta{0.f}; // Charged particle multiplicity to use in the efficiency evaluation + computeDNDEta(dNdEta, mcParticles, histPath); + auto ir = irSampler.generateCollisionTime(); + const float eventCollisionTimeNS = ir.timeInBCNS; + + uint32_t multiplicityCounter = 0; + // Now that the multiplicity is known, we can process the particles to smear them + for (const auto& mcParticle : mcParticles) { + + if (!mcParticle.isPhysicalPrimary()) { + continue; } - tableStoredTracks(tableCollisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); - tableTracksExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); + if ((std::fabs(mcParticle.eta()) > maxEta) || (mcParticle.pt() < minPt)) { + continue; + } - // TODO do we keep the rho as 0? Also the sigma's are duplicated information - tableStoredTracksCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), - std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - tableTracksCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), - trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), - trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), - trackParCov.getSigma1Pt2()); - tableMcTrackLabels(trackParCov.mcLabel, 0); - tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); + const bool isCascadeToDecay = (mcParticle.pdgCode() == kXiMinus) && cascadeDecaySettings.decayXi; + const bool isV0ToDecay = std::find(v0PDGs.begin(), v0PDGs.end(), mcParticle.pdgCode()) != v0PDGs.end() && v0DecaySettings.decayV0; - // populate extra tables if required to do so - if (populateTracksExtra) { - tableStoredTracksExtra(0.0f, static_cast(0), static_cast(0), static_cast(0), static_cast(0), - static_cast(0), static_cast(0), static_cast(0), static_cast(0), - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); + const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), std::abs(mcParticle.pdgCode())) != nucleiPDGs.end(); + const bool pdgsToBeHandled = longLivedToBeHandled || + (enableNucleiSmearing && nucleiToBeHandled) || + (isCascadeToDecay) || (isV0ToDecay); + if (!pdgsToBeHandled) { + continue; } - if (populateTrackSelection) { - tableTrackSelection(static_cast(0), false, false, false, false, false, false); - tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + + if (isCascadeToDecay) { + genCascades.push_back(mcParticle.globalIndex()); + } + if (isV0ToDecay) { + genV0s.push_back(mcParticle.globalIndex()); + } + + multiplicityCounter++; + o2::track::TrackParCov trackParCov; + const bool isDecayDaughter = (mcParticle.getProcess() == TMCProcess::kPDecay); + if (doExtraQA) { + histos.fill(HIST("hSimTrackX"), trackParCov.getX()); + } + + bool reconstructed = true; + int nTrkHits = 0; + if (enablePrimarySmearing) { + if (fastPrimaryTrackerSettings.fastTrackPrimaries) { + o2::track::TrackParCov perfectTrackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); + perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); + nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); + if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { + reconstructed = false; + } + } else { + o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + nTrkHits = fastTrackerSettings.minSiliconHits; + } + getHist(TH1, histPath + "hPtGenerated")->Fill(mcParticle.pt()); + getHist(TH1, histPath + "hPhiGenerated")->Fill(mcParticle.phi()); + if (std::abs(mcParticle.pdgCode()) == kElectron) + getHist(TH1, histPath + "hPtGeneratedEl")->Fill(mcParticle.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) + getHist(TH1, histPath + "hPtGeneratedPi")->Fill(mcParticle.pt()); + if (std::abs(mcParticle.pdgCode()) == kKPlus) + getHist(TH1, histPath + "hPtGeneratedKa")->Fill(mcParticle.pt()); + if (std::abs(mcParticle.pdgCode()) == kProton) + getHist(TH1, histPath + "hPtGeneratedPr")->Fill(mcParticle.pt()); + + if (!reconstructed && !processUnreconstructedTracks) { + continue; + } + + getHist(TH1, histPath + "hPtReconstructed")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kElectron) + getHist(TH1, histPath + "hPtReconstructedEl")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) + getHist(TH1, histPath + "hPtReconstructedPi")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kKPlus) + getHist(TH1, histPath + "hPtReconstructedKa")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kProton) + getHist(TH1, histPath + "hPtReconstructedPr")->Fill(trackParCov.getPt()); + } + if (doExtraQA) { + getHist(TH2, histPath + "h2dPtRes")->Fill(trackParCov.getPt(), (trackParCov.getPt() - mcParticle.pt()) / trackParCov.getPt()); + getHist(TH2, histPath + "h2dPtResAbs")->Fill(trackParCov.getPt(), trackParCov.getPt() - mcParticle.pt()); + histos.fill(HIST("hRecoTrackX"), trackParCov.getX()); + } + + if (TMath::IsNaN(trackParCov.getZ())) { + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 0.0f); + continue; // capture smearing mistakes + } + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 1.0f); // ok! + + // Time associated to the mcParticle: collision time + smearing + float trackTime = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + TrackType trackType = reconstructed ? TrackType::kRecoPrimary : TrackType::kGhostPrimary; + if (reconstructed) { + recoPrimaries.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), trackTime, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits, trackType}); + } else { + ghostPrimaries.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), trackTime, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits, trackType}); } - tableTracksAlice3(false); } - // populate Cascades - LOG(debug) << "Populating " << cascadesAlice3.size() << " cascades."; - for (const auto& cascade : cascadesAlice3) { - tableUpgradeCascades(tableCollisions.lastIndex(), // now we know the collision index -> populate table - cascade.cascadeTrackId, - cascade.positiveId, - cascade.negativeId, - cascade.bachelorId, - cascade.dcaV0dau, - cascade.dcacascdau, - cascade.v0radius, - cascade.cascradius, - cascade.cascradiusMC, - cascade.mLambda, - cascade.mXi, - cascade.findableClusters, - cascade.foundClusters); + // Compute primary vertex with primary tracks + o2::vertexing::PVertex primaryVertex; + if (enablePrimaryVertexing && recoPrimaries.size() <= 2) { + LOG(info) << "Not enough primary tracks (" << recoPrimaries.size() << ") to compute vertex, skipping vertexing and collision population."; + return; + } + computeVertex(mcCollision, recoPrimaries, primaryVertex, icfg); + getHist(TH1, histPath + "hPVz")->Fill(primaryVertex.getZ()); + // populate collisions + tableCollisions(-1, // BC is irrelevant in synthetic MC tests for now, could be adjusted in future + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + primaryVertex.getSigmaX2(), primaryVertex.getSigmaXY(), primaryVertex.getSigmaY2(), + primaryVertex.getSigmaXZ(), primaryVertex.getSigmaYZ(), primaryVertex.getSigmaZ2(), + 0, primaryVertex.getChi2(), primaryVertex.getNContributors(), + eventCollisionTimeNS, 0.f); // For the moment the event collision time is taken as the "GEANT" time, the computation of the event time is done a posteriori from the tracks in the OTF TOF PID task + tableMcCollisionLabels(mcCollision.globalIndex(), 0); + tableCollisionsAlice3(dNdEta); + tableOTFLUTConfigId(icfg); // Populate OTF LUT configuration ID + + // Study V0s and cascades + int trackTableOffset = tableStoredTracks.lastIndex(); + std::vector tracksCascadeProngs; + for (size_t iCasc = 0; iCasc < genCascades.size(); iCasc++) { + auto genCasc = mcParticles.rawIteratorAt(genCascades[iCasc] - mcParticles.offset()); + studyCascade(trackTableOffset, genCasc, tracksCascadeProngs, primaryVertex, icfg, dNdEta, eventCollisionTimeNS); + fillTracksInfo(tracksCascadeProngs, primaryVertex, icfg); + trackTableOffset += tracksCascadeProngs.size(); // each cascade takes 4 tracks in the table (cascade + 3 daughters) + tracksCascadeProngs.clear(); } - // populate V0s - LOG(debug) << "Populating " << v0sAlice3.size() << " V0s."; - for (const auto& v0 : v0sAlice3) { - tableUpgradeV0s(tableCollisions.lastIndex(), // now we know the collision index -> populate table - v0.mcParticleId, - v0.positiveId, - v0.negativeId, - v0.dcaV0dau, - v0.v0radius, - v0.mLambda, - v0.mAntiLambda, - v0.mK0, - v0.pt); + std::vector tracksV0Daugs; + for (size_t iV0 = 0; iV0 < genV0s.size(); iV0++) { + auto genV0 = mcParticles.rawIteratorAt(genV0s[iV0] - mcParticles.offset()); + studyV0(trackTableOffset, genV0, tracksV0Daugs, icfg, dNdEta, eventCollisionTimeNS); + fillTracksInfo(tracksV0Daugs, primaryVertex, icfg); + trackTableOffset += tracksV0Daugs.size(); // each V0 takes 2 tracks in the table (2 daughters) + tracksV0Daugs.clear(); } + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate tracks + fillTracksInfo(recoPrimaries, primaryVertex, icfg); + fillTracksInfo(ghostPrimaries, primaryVertex, icfg); + // do bookkeeping of fastTracker tracking if (enableSecondarySmearing) { histos.fill(HIST("hCovMatOK"), 0.0f, fastTracker[icfg]->GetCovMatNotOK()); histos.fill(HIST("hCovMatOK"), 1.0f, fastTracker[icfg]->GetCovMatOK()); } + if (doExtraQA) { + histos.fill(HIST("hRecoVsSimMultiplicity"), multiplicityCounter, recoPrimaries.size()); + getHist(TH1, histPath + "hSimMultiplicity")->Fill(multiplicityCounter); + getHist(TH1, histPath + "hRecoMultiplicity")->Fill(recoPrimaries.size()); + } + LOG(debug) << " <- Finished processing OTF tracking with LUT configuration ID " << icfg; } // end process @@ -1874,7 +1934,6 @@ struct OnTheFlyTracker { void processConfigurationDev(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles, const int icfg) { - // const int lastTrackIndex = tableStoredTracksCov.lastIndex() + 1; // bookkeep the last added track const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; tracksAlice3.clear(); ghostTracksAlice3.clear(); @@ -1882,47 +1941,15 @@ struct OnTheFlyTracker { cascadesAlice3.clear(); v0sAlice3.clear(); - o2::dataformats::DCA dcaInfo; - o2::dataformats::VertexBase vtx; - // generate collision time auto ir = irSampler.generateCollisionTime(); const float eventCollisionTimeNS = ir.timeInBCNS; // First we compute the number of charged particles in the event - dNdEta = 0.f; - for (const auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.eta()) > multEtaRange) { - continue; - } - - if (!mcParticle.isPhysicalPrimary()) { - continue; - } - - const auto pdg = std::abs(mcParticle.pdgCode()); - const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), pdg) != longLivedHandledPDGs.end(); - const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), pdg) != nucleiPDGs.end(); - const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled); - if (!pdgsToBeHandled) { - continue; - } - - const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); - if (!pdgInfo) { - LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; - continue; - } - if (pdgInfo->Charge() == 0) { - continue; - } - dNdEta += 1.f; - } + float dNdEta{0.f}; + computeDNDEta(dNdEta, mcParticles, histPath); - dNdEta /= (multEtaRange * 2.0f); uint32_t multiplicityCounter = 0; - getHist(TH1, histPath + "hLUTMultiplicity")->Fill(dNdEta); - // Now that the multiplicity is known, we can process the particles to smear them for (const auto& mcParticle : mcParticles) { const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); @@ -1962,9 +1989,6 @@ struct OnTheFlyTracker { multiplicityCounter++; o2::track::TrackParCov trackParCov; const bool isDecayDaughter = (mcParticle.getProcess() == TMCProcess::kPDecay); - const float timeResolutionNs = 100.f; // ns - const float nsToMus = 1e-3f; - const float timeResolutionUs = timeResolutionNs * nsToMus; // us const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; bool reconstructed = false; @@ -2008,18 +2032,18 @@ struct OnTheFlyTracker { } if (reconstructed) { - tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits, kRecoPrimary}); } else { - ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); + ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits, kGhostPrimary}); } } o2::vertexing::PVertex primaryVertex; - if (enablePrimaryVertexing) { // disabled for now - primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); - } else { - primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + if (enablePrimaryVertexing && recoPrimaries.size() <= 2) { + LOG(info) << "Not enough primary tracks (" << recoPrimaries.size() << ") to compute vertex, skipping vertexing and collision population."; + return; } + computeVertex(mcCollision, tracksAlice3, primaryVertex, icfg); getHist(TH1, histPath + "hSimMultiplicity")->Fill(multiplicityCounter); getHist(TH1, histPath + "hRecoMultiplicity")->Fill(tracksAlice3.size()); @@ -2039,95 +2063,8 @@ struct OnTheFlyTracker { // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* // populate tracks - for (const auto& trackParCov : tracksAlice3) { - aod::track::TrackTypeEnum trackType = aod::track::Track; - - if (populateTracksDCA) { - float dcaXY = 1e+10, dcaZ = 1e+10; - o2::track::TrackParCov trackParametrization(trackParCov); - if (trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { - dcaXY = dcaInfo.getY(); - dcaZ = dcaInfo.getZ(); - } - - tableTracksDCA(dcaXY, dcaZ); - if (populateTracksDCACov) { - tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); - } - } - - tableStoredTracks(tableCollisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); - tableTracksExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); - - // TODO do we keep the rho as 0? Also the sigma's are duplicated information - tableStoredTracksCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), - std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - tableTracksCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), - trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), - trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), - trackParCov.getSigma1Pt2()); - tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); - tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); - - // populate extra tables if required to do so - if (populateTracksExtra) { - tableStoredTracksExtra(0.0f, static_cast(0), static_cast(0), static_cast(0), static_cast(0), - static_cast(0), static_cast(0), static_cast(0), static_cast(0), - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); - } - if (populateTrackSelection) { - tableTrackSelection(static_cast(0), false, false, false, false, false, false); - tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); - } - tableTracksAlice3(true); - } - - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - // populate ghost tracks - for (const auto& trackParCov : ghostTracksAlice3) { - aod::track::TrackTypeEnum trackType = aod::track::Track; - - if (populateTracksDCA) { - float dcaXY = 1e+10, dcaZ = 1e+10; - o2::track::TrackParCov trackParametrization(trackParCov); - if (trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { - dcaXY = dcaInfo.getY(); - dcaZ = dcaInfo.getZ(); - } - - tableTracksDCA(dcaXY, dcaZ); - if (populateTracksDCACov) { - tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); - } - } - - tableStoredTracks(tableCollisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); - tableTracksExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); - - // TODO do we keep the rho as 0? Also the sigma's are duplicated information - tableStoredTracksCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), - std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - tableTracksCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), - trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), - trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), - trackParCov.getSigma1Pt2()); - tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); - tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); - - // populate extra tables if required to do so - if (populateTracksExtra) { - tableStoredTracksExtra(0.0f, static_cast(0), static_cast(0), static_cast(0), static_cast(0), - static_cast(0), static_cast(0), static_cast(0), static_cast(0), - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); - } - if (populateTrackSelection) { - tableTrackSelection(static_cast(0), false, false, false, false, false, false); - tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); - } - tableTracksAlice3(false); - } + fillTracksInfo(tracksAlice3, primaryVertex, icfg); + fillTracksInfo(ghostTracksAlice3, primaryVertex, icfg); } void processDecayer(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles) diff --git a/ALICE3/TableProducer/alice3TrackingTranslator.cxx b/ALICE3/TableProducer/alice3TrackingTranslator.cxx index c68cb2adbe3..d9b2d3874f6 100644 --- a/ALICE3/TableProducer/alice3TrackingTranslator.cxx +++ b/ALICE3/TableProducer/alice3TrackingTranslator.cxx @@ -582,7 +582,8 @@ struct Alice3TrackingTranslator { tableTracksAlice3Pdg(pdgCode); // PdgCode to the linked MC truth particle tableTracksExtraA3(m_nMeasurements, // nSiliconHits (using m_nMeasurements as proxy) - 0); // nTPCHits + 0, // nTPCHits + 0); // trackType // Fill extra track info tableStoredTracksExtra(0.f, // TPCInnerParam From dd27033dd5295d0ead135ffe1a65b73e84210233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 15 May 2026 10:52:40 +0200 Subject: [PATCH 176/449] [Infrastructure] Add @jesgum as code owner for ALICE3 (#16161) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index a24c1eefbb0..23e54377bb6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -14,7 +14,7 @@ * @AliceO2Group/core @alibuild @jgrosseo @iarsene @ktf @ddobrigk @dsekihat /Common/CCDB @alibuild @jgrosseo @iarsene @ekryshen @ddobrigk /Common/Tools/Multiplicity @alibuild @ddobrigk @victor-gonzalez -/ALICE3 @alibuild @njacazio @hscheid +/ALICE3 @alibuild @njacazio @hscheid @jesgum /DPG @alibuild @chiarazampolli @alcaliva @catalinristea /DPG/Tasks/AOTEvent @alibuild @ekryshen @strogolo @altsybee /DPG/Tasks/AOTTrack @alibuild @mfaggin @iouribelikov @njacazio @lbariogl @f3sch From caf7dc3c2d297c3520b60c0f3536ce2644d85531 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 15 May 2026 14:32:30 +0200 Subject: [PATCH 177/449] [DPG] tpcSkimsTableCreator: add RCT check, minor refactory (#16196) --- DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 96 +++++++++++++++-------- DPG/Tasks/TPC/tpcSkimsTableCreator.h | 4 +- DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h | 10 +-- 3 files changed, 73 insertions(+), 37 deletions(-) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 85607d41636..7bc4d190d6e 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -25,6 +25,7 @@ #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -102,6 +103,11 @@ struct TreeWriterTpcV0 { Configurable maxPt4dwnsmplTsalisProtons{"maxPt4dwnsmplTsalisProtons", 100., "Maximum Pt for applying downsampling factor of protons"}; Configurable maxPt4dwnsmplTsalisElectrons{"maxPt4dwnsmplTsalisElectrons", 100., "Maximum Pt for applying downsampling factor of electrons"}; Configurable maxPt4dwnsmplTsalisKaons{"maxPt4dwnsmplTsalisKaons", 100., "Maximum Pt for applying downsampling factor of kaons"}; + // Configurables for run condtion table + Configurable rctLabel{"rctLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable checkZdc{"checkZdc", false, "set ZDC flag for PbPb"}; + Configurable treatLimitedAcceptanceAsBad{"treatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + Configurable requireGoodRct{"requireGoodRct", false, "require good detector flag in run condtion table"}; // an arbitrary value of N sigma TOF assigned by TOF task to tracks which are not matched to TOF hits constexpr static float NSigmaTofUnmatched{o2::aod::v0data::kNoTOFValue}; @@ -146,9 +152,11 @@ struct TreeWriterTpcV0 { int negDaughterId{UndefValueInt}; }; - Service ccdb; + Service ccdb{}; - ctpRateFetcher mRateFetcher; + ctpRateFetcher mRateFetcher{}; + + o2::aod::rctsel::RCTFlagsChecker rctChecker{}; TRandom3* fRndm = new TRandom3(0); @@ -172,6 +180,8 @@ struct TreeWriterTpcV0 { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setFatalWhenNull(false); + + rctChecker.init(rctLabel, checkZdc, treatLimitedAcceptanceAsBad); } template @@ -250,7 +260,7 @@ struct TreeWriterTpcV0 { } template - void fillSkimmedV0Table(V0Casc const& v0casc, T const& track, aod::TracksQA const& trackQA, const bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, const int runnumber, const double dwnSmplFactor, const float hadronicRate, const int bcGlobalIndex, const int bcTimeFrameId, const int bcBcInTimeFrame, const OccupancyValues& occValues) + void fillSkimmedV0Table(V0Casc const& v0casc, T const& track, aod::TracksQA const& trackQA, const bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, const int runnumber, const double dwnSmplFactor, const float hadronicRate, const int bcGlobalIndex, const int bcTimeFrameId, const int bcBcInTimeFrame, const OccupancyValues& occValues, const bool isGoodRctEvent) { const double ncl = track.tpcNClsFound(); const double nclPID = track.tpcNClsFindableMinusPID(); @@ -277,7 +287,8 @@ struct TreeWriterTpcV0 { tpcdEdxNorm = existTrkQA ? trackQA.tpcdEdxNorm() : UndefValueFloat; } if constexpr (ModeId == ModeStandard || ModeId == ModeWithdEdxTrkQA) { - rowTPCTree(usedDedx, + rowTPCTree(isGoodRctEvent, + usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -307,7 +318,8 @@ struct TreeWriterTpcV0 { v0radius, gammapsipair); } else { - rowTPCTreeWithTrkQA(usedDedx, + rowTPCTreeWithTrkQA(isGoodRctEvent, + usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -406,17 +418,22 @@ struct TreeWriterTpcV0 { } } - const auto& tracksWithITSPid = soa::Attach(myTracks); + const auto tracksWithITSPid = soa::Attach(myTracks); for (const auto& collision : collisions) { if (!isEventSelected(collision, applyEvSel)) { continue; } - const auto& v0s = myV0s.sliceBy(perCollisionV0s, static_cast(collision.globalIndex())); - const auto& cascs = myCascs.sliceBy(perCollisionCascs, static_cast(collision.globalIndex())); - const auto& bc = collision.bc_as(); + const bool isGoodRctEvent = rctChecker.checkTable(collision); + if (requireGoodRct && !isGoodRctEvent) { + continue; + } + + const auto v0s = myV0s.sliceBy(perCollisionV0s, static_cast(collision.globalIndex())); + const auto cascs = myCascs.sliceBy(perCollisionCascs, static_cast(collision.globalIndex())); + const auto bc = collision.bc_as(); const int runnumber = bc.runNumber(); const auto hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * OneToKilo; const int bcGlobalIndex = bc.globalIndex(); @@ -448,11 +465,11 @@ struct TreeWriterTpcV0 { auto fillDaughterTrack = [&](const auto& mother, const TrksType::iterator& dauTrack, const auto& v0, const bool isPositive) { const auto [trackQAInstance, existTrkQA] = getTrackQA(dauTrack); const auto trackId = dauTrack.globalIndex(); - const auto& dauTrackWithITSPid = tracksWithITSPid.rawIteratorAt(trackId); + const auto dauTrackWithITSPid = tracksWithITSPid.rawIteratorAt(trackId); const auto v0Id = getAddId(v0); const V0Mother v0Mother = createV0Mother(v0Id); - const auto daighterId = isPositive ? v0Mother.posDaughterId : v0Mother.negDaughterId; - const V0Daughter daughter = createV0Daughter(v0, dauTrackWithITSPid, v0Id, daighterId, isPositive); + const auto daughterId = isPositive ? v0Mother.posDaughterId : v0Mother.negDaughterId; + const V0Daughter daughter = createV0Daughter(v0, dauTrackWithITSPid, v0Id, daughterId, isPositive); const bool passTrackSelection = isTrackSelected(dauTrack, trackSelection); const bool passDownsamplig = downsampleTsalisCharged(fRndm, dauTrack.pt(), daughter.downsamplingTsalis, daughter.mass, sqrtSNN, daughter.maxPt4dwnsmplTsalis); @@ -463,7 +480,7 @@ struct TreeWriterTpcV0 { if constexpr (ModeId == ModeWithTrkQA) { evaluateOccupancyVariables(dauTrack, occValues); } - fillSkimmedV0Table(mother, dauTrack, trackQAInstance, existTrkQA, collision, daughter.tpcNSigma, daughter.tofNSigma, daughter.itsNSigma, daughter.tpcExpSignal, daughter.id, runnumber, daughter.dwnSmplFactor, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame, occValues); + fillSkimmedV0Table(mother, dauTrack, trackQAInstance, existTrkQA, collision, daughter.tpcNSigma, daughter.tofNSigma, daughter.itsNSigma, daughter.tpcExpSignal, daughter.id, runnumber, daughter.dwnSmplFactor, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame, occValues, isGoodRctEvent); } }; @@ -473,8 +490,8 @@ struct TreeWriterTpcV0 { if (v0Id == MotherUndef) { continue; } - const auto& posTrack = v0.posTrack_as(); - const auto& negTrack = v0.negTrack_as(); + const auto posTrack = v0.posTrack_as(); + const auto negTrack = v0.negTrack_as(); fillDaughterTrack(v0, posTrack, v0, true); fillDaughterTrack(v0, negTrack, v0, false); @@ -486,7 +503,7 @@ struct TreeWriterTpcV0 { if (cascId == MotherUndef) { continue; } - const auto& bachTrack = casc.bachelor_as(); + const auto bachTrack = casc.bachelor_as(); // Omega and antiomega const auto isDaughterPositive = cascId == MotherAntiOmega ? true : false; fillDaughterTrack(casc, bachTrack, casc, isDaughterPositive); @@ -615,6 +632,11 @@ struct TreeWriterTpcTof { Configurable downsamplingTsalisProtons{"downsamplingTsalisProtons", -1., "Downsampling factor to reduce the number of protons"}; Configurable downsamplingTsalisKaons{"downsamplingTsalisKaons", -1., "Downsampling factor to reduce the number of kaons"}; Configurable downsamplingTsalisPions{"downsamplingTsalisPions", -1., "Downsampling factor to reduce the number of pions"}; + // Configurables for run condtion table + Configurable rctLabel{"rctLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable checkZdc{"checkZdc", false, "set ZDC flag for PbPb"}; + Configurable treatLimitedAcceptanceAsBad{"treatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + Configurable requireGoodRct{"requireGoodRct", false, "require good detector flag in run condtion table"}; struct TofTrack { bool isApplyHardCutOnly; @@ -633,9 +655,11 @@ struct TreeWriterTpcTof { double nSigmaTpcTpctof; }; - Service ccdb; + Service ccdb{}; - ctpRateFetcher mRateFetcher; + ctpRateFetcher mRateFetcher{}; + + o2::aod::rctsel::RCTFlagsChecker rctChecker{}; TRandom3* fRndm = new TRandom3(0); @@ -666,10 +690,12 @@ struct TreeWriterTpcTof { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setFatalWhenNull(false); + + rctChecker.init(rctLabel, checkZdc, treatLimitedAcceptanceAsBad); } template - void fillSkimmedTpcTofTable(T const& track, aod::TracksQA const& trackQA, const bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, const int runnumber, const double dwnSmplFactor, const double hadronicRate, const int bcGlobalIndex, const int bcTimeFrameId, const int bcBcInTimeFrame, const OccupancyValues& occValues) + void fillSkimmedTpcTofTable(T const& track, aod::TracksQA const& trackQA, const bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, const int runnumber, const double dwnSmplFactor, const double hadronicRate, const int bcGlobalIndex, const int bcTimeFrameId, const int bcBcInTimeFrame, const OccupancyValues& occValues, const bool isGoodRctEvent) { const double ncl = track.tpcNClsFound(); const double nclPID = track.tpcNClsFindableMinusPID(); @@ -689,7 +715,8 @@ struct TreeWriterTpcTof { tpcdEdxNorm = existTrkQA ? trackQA.tpcdEdxNorm() : UndefValueFloat; } if (ModeId == ModeStandard || ModeId == ModeWithdEdxTrkQA) { - rowTPCTOFTree(usedEdx, + rowTPCTOFTree(isGoodRctEvent, + usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -713,7 +740,8 @@ struct TreeWriterTpcTof { hadronicRate, tpcdEdxNorm); } else { - rowTPCTOFTreeWithTrkQA(usedEdx, + rowTPCTOFTreeWithTrkQA(isGoodRctEvent, + usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -776,10 +804,15 @@ struct TreeWriterTpcTof { } } for (const auto& collision : collisions) { - const auto& tracks = myTracks.sliceBy(perCollisionTracksType, collision.globalIndex()); + const auto tracks = myTracks.sliceBy(perCollisionTracksType, collision.globalIndex()); if (!isEventSelected(collision, applyEvSel)) { continue; } + const bool isGoodRctEvent = rctChecker.checkTable(collision); + if (requireGoodRct && !isGoodRctEvent) { + continue; + } + auto tracksWithITSPid = soa::Attach(tracks); @@ -788,7 +821,7 @@ struct TreeWriterTpcTof { tracksWithITSPid.bindExternalIndices(&trackMeanOccs); } - const auto& bc = collision.bc_as(); + const auto bc = collision.bc_as(); const int runnumber = bc.runNumber(); const auto hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * OneToKilo; const int bcGlobalIndex = bc.globalIndex(); @@ -826,17 +859,18 @@ struct TreeWriterTpcTof { TofTrack tofPion(false, UndefValueDouble, maxMomTPCOnlyPi, trk.tpcNSigmaPi(), nSigmaTPCOnlyPi, downsamplingTsalisPions, MassPiPlus, trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(tpcSignalGeneric(trk)), PidPion, dwnSmplFactorPi, nSigmaTofTpctofPi, nSigmaTpcTpctofPi); - OccupancyValues occValues; + OccupancyValues occValues{}; if constexpr (ModeId == ModeWithTrkQA) { evaluateOccupancyVariables(trk, occValues); } for (const auto& tofTrack : {&tofTriton, &tofDeuteron, &tofProton, &tofKaon, &tofPion}) { - if ((!tofTrack->isApplyHardCutOnly || trk.tpcInnerParam() < tofTrack->maxMomHardCutOnly) && - ((trk.tpcInnerParam() <= tofTrack->maxMomTPCOnly && std::fabs(tofTrack->tpcNSigma) < tofTrack->nSigmaTPCOnly) || - (trk.tpcInnerParam() > tofTrack->maxMomTPCOnly && std::fabs(tofTrack->tofNSigma) < tofTrack->nSigmaTofTpctof && std::fabs(tofTrack->tpcNSigma) < tofTrack->nSigmaTpcTpctof)) && - downsampleTsalisCharged(fRndm, trk.pt(), tofTrack->downsamplingTsalis, tofTrack->mass, sqrtSNN)) { - fillSkimmedTpcTofTable(trk, trackQA, existTrkQA, collision, tofTrack->tpcNSigma, tofTrack->tofNSigma, tofTrack->itsNSigma, tofTrack->tpcExpSignal, tofTrack->pid, runnumber, tofTrack->dwnSmplFactor, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame, occValues); + const bool passMomHardCut = !tofTrack->isApplyHardCutOnly || trk.tpcInnerParam() < tofTrack->maxMomHardCutOnly; + const bool passMomTpcOnly = trk.tpcInnerParam() <= tofTrack->maxMomTPCOnly && std::fabs(tofTrack->tpcNSigma) < tofTrack->nSigmaTPCOnly; + const bool passMomTpcTof = trk.tpcInnerParam() > tofTrack->maxMomTPCOnly && std::fabs(tofTrack->tofNSigma) < tofTrack->nSigmaTofTpctof && std::fabs(tofTrack->tpcNSigma) < tofTrack->nSigmaTpcTpctof; + const bool passDownsamplig = downsampleTsalisCharged(fRndm, trk.pt(), tofTrack->downsamplingTsalis, tofTrack->mass, sqrtSNN); + if (passMomHardCut && (passMomTpcOnly || passMomTpcTof) && passDownsamplig) { + fillSkimmedTpcTofTable(trk, trackQA, existTrkQA, collision, tofTrack->tpcNSigma, tofTrack->tofNSigma, tofTrack->itsNSigma, tofTrack->tpcExpSignal, tofTrack->pid, runnumber, tofTrack->dwnSmplFactor, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame, occValues, isGoodRctEvent); } } } /// Loop tracks diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.h b/DPG/Tasks/TPC/tpcSkimsTableCreator.h index 61017c27d1c..9172d8d2447 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.h +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.h @@ -31,6 +31,7 @@ namespace o2::aod { namespace tpcskims { +DECLARE_SOA_COLUMN(IsGoodRct, isGoodRct, bool); DECLARE_SOA_COLUMN(InvDeDxExpTPC, invDeDxExpTPC, float); DECLARE_SOA_COLUMN(Mass, mass, float); DECLARE_SOA_COLUMN(BetaGamma, betaGamma, float); @@ -58,7 +59,8 @@ DECLARE_SOA_COLUMN(BcBcInTimeFrame, bcBcInTimeFrame, int); } // namespace tpcskims #define TPCSKIMS_COLUMNS_BASE \ - o2::aod::track::TPCSignal, \ + tpcskims::IsGoodRct, \ + o2::aod::track::TPCSignal, \ tpcskims::InvDeDxExpTPC, \ o2::aod::track::TPCInnerParam, \ o2::aod::track::Tgl, \ diff --git a/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h b/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h index 32c27233067..b8550e094d7 100644 --- a/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h +++ b/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h @@ -49,7 +49,7 @@ enum { /// Event selection template -inline bool isEventSelected(const CollisionType& collision, const int applyEvSel) +bool isEventSelected(const CollisionType& collision, const int applyEvSel) { if ((applyEvSel == EventSelectionRun2 && !collision.sel7()) || (applyEvSel == EventSelectionRun3 && !collision.sel8())) { return false; @@ -88,7 +88,7 @@ inline bool downsampleTsalisCharged(TRandom3* fRndm, const double pt, const doub // Track selection template -inline bool isTrackSelected(const TrackType& track, const int trackSelection) +bool isTrackSelected(const TrackType& track, const int trackSelection) { bool isSelected{false}; isSelected |= trackSelection == TrackSelectionNoCut; @@ -103,7 +103,7 @@ inline bool isTrackSelected(const TrackType& track, const int trackSelection) /// Evaluate tpcSignal with or without dEdx correction template -inline double tpcSignalGeneric(const TrkType& track) +double tpcSignalGeneric(const TrkType& track) { if constexpr (IsCorrectedDeDx) { return track.tpcSignalCorrected(); @@ -129,12 +129,12 @@ using TrackMeanOccs = soa::Join -inline void evaluateOccupancyVariables(const TrkType& track, OccupancyValues& occValues) +void evaluateOccupancyVariables(const TrkType& track, OccupancyValues& occValues) { if (track.tmoId() == -1) { return; } - const auto& tmoFromTrack = track.template tmo_as(); + const auto tmoFromTrack = track.template tmo_as(); occValues.tmoPrimUnfm80 = tmoFromTrack.tmoPrimUnfm80(); occValues.tmoFV0AUnfm80 = tmoFromTrack.tmoFV0AUnfm80(); occValues.tmoFT0AUnfm80 = tmoFromTrack.tmoFT0AUnfm80(); From d85e5835f95be7838ca5770abba2d844c5a9a08f Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Fri, 15 May 2026 15:11:41 +0200 Subject: [PATCH 178/449] [PWGLF,PWGMM] mftReassociationValidation.cxx : change histogram names to be able to run 2D and 3D at the same time (#16251) --- .../Mult/Tasks/mftReassociationValidation.cxx | 845 ++++++++++-------- 1 file changed, 468 insertions(+), 377 deletions(-) diff --git a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx index b65d22bde62..060dce38310 100644 --- a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx +++ b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx @@ -233,9 +233,16 @@ enum McStatus { NotCollisionAmongTheCompatibleIds }; +enum ReassociationMethod { + TwoDimensional = 0, + ThreeDimensional, + NReassociationMethods +}; + static constexpr std::string_view WhatDataType[] = {"Data/", "MC/"}; static constexpr std::string_view WhatMultiplicityEstimator[] = {"multNTracksPV", "multNumContrib", "multFT0C", "multFT0M"}; static constexpr std::string_view WhatMcStatus[] = {"McMatched/", "NotMcMatched/", "CollisionAmongTheCompatibleIds/", "NotCollisionAmongTheCompatibleIds/"}; +static constexpr std::string_view WhatReassociationMethod[] = {"2D/", "3D/"}; std::unordered_map recoVtxX; std::unordered_map recoVtxY; std::unordered_map recoVtxZ; @@ -323,20 +330,26 @@ struct MftReassociationValidation { o2::parameters::GRPMagField* grpmag = nullptr; RCTFlagsChecker rctChecker; RCTFlagsChecker correlationAnalysisRctChecker{kFT0Bad, kITSBad, kTPCBadTracking, kTPCBadPID, kMFTBad}; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffAmbiguousTracks; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNonAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffAmbiguousTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNonAmbiguousTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNotMatchedTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaAmbiguousTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNonAmbiguousTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNotMatchedTracks2D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffAmbiguousTracks3D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNonAmbiguousTracks3D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNotMatchedTracks3D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaAmbiguousTracks3D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNonAmbiguousTracks3D; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNotMatchedTracks3D; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff2dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot2dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff3dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot3dReassociatedTracks; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNotMatchedTracks; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaAmbiguousTracks; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNonAmbiguousTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDca2dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNot2dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDca3dReassociatedTracks; std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNot3dReassociatedTracks; - std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNotMatchedTracks; // ========================= // using declarations : DATA @@ -394,22 +407,22 @@ struct MftReassociationValidation { HistogramRegistry registry{"registry"}; - template + template void addMftHistograms() { - registry.add(Form("%shAmbiguityOfMftTracks", WhatDataType[DataType].data()), "hAmbiguityOfMftTracks", {HistType::kTH1D, {{MftTrackAmbiguityStep::NMftAmbiguitySteps, -0.5, +MftTrackAmbiguityStep::NMftAmbiguitySteps - 0.5}}}); + registry.add(Form("%s%shAmbiguityOfMftTracks", WhatDataType[DataType].data(), WhatReassociationMethod[ReassociationMethod].data()), "hAmbiguityOfMftTracks", {HistType::kTH1D, {{MftTrackAmbiguityStep::NMftAmbiguitySteps, -0.5, +MftTrackAmbiguityStep::NMftAmbiguitySteps - 0.5}}}); std::string labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NMftAmbiguitySteps]; labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AllMftTracks] = "all MFT tracks"; labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AfterTrackSelection] = "MFT tracks after selection"; labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfAmbiguousTracks] = "how much tracks are ambigous"; labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks] = "how much tracks are non-ambiguous"; - registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->SetMinimum(0); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hAmbiguityOfMftTracks"))->SetMinimum(0); for (int iBin = 0; iBin < MftTrackAmbiguityStep::NMftAmbiguitySteps; iBin++) { - registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsAmbiguityOfMftTracks[iBin].data()); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hAmbiguityOfMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsAmbiguityOfMftTracks[iBin].data()); } - registry.add(Form("%shMftTracksSelection", WhatDataType[DataType].data()), "hMftTracksSelection", {HistType::kTH1D, {{MftTrackSelectionStep::NMftTrackSelectionSteps, -0.5, +MftTrackSelectionStep::NMftTrackSelectionSteps - 0.5}}}); + registry.add(Form("%s%shMftTracksSelection", WhatDataType[DataType].data(), WhatReassociationMethod[ReassociationMethod].data()), "hMftTracksSelection", {HistType::kTH1D, {{MftTrackSelectionStep::NMftTrackSelectionSteps, -0.5, +MftTrackSelectionStep::NMftTrackSelectionSteps - 0.5}}}); std::string labelsMftTracksSelection[MftTrackSelectionStep::NMftTrackSelectionSteps]; labelsMftTracksSelection[MftTrackSelectionStep::NoSelection] = "all MFT tracks"; labelsMftTracksSelection[MftTrackSelectionStep::Eta] = "MFT tracks after eta selection"; @@ -417,203 +430,271 @@ struct MftReassociationValidation { labelsMftTracksSelection[MftTrackSelectionStep::Pt] = "MFT tracks after pT selection"; labelsMftTracksSelection[MftTrackSelectionStep::IsCA] = "MFT tracks reconstructed with CA"; labelsMftTracksSelection[MftTrackSelectionStep::IsLTF] = "MFT tracks reconstructed with LTF"; - registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->SetMinimum(0); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hMftTracksSelection"))->SetMinimum(0); for (int iBin = 0; iBin < MftTrackSelectionStep::NMftTrackSelectionSteps; iBin++) { - registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftTracksSelection[iBin].data()); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hMftTracksSelection"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftTracksSelection[iBin].data()); } - registry.add(Form("%shReassociation2dMftTracks", WhatDataType[DataType].data()), "hReassociation2dMftTracks", {HistType::kTH1D, {{Reassociation2dMftTracks::NReassociation2dMftTracksSteps, -0.5, +Reassociation2dMftTracks::NReassociation2dMftTracksSteps - 0.5}}}); + registry.add(Form("%s%shReassociation2dMftTracks", WhatDataType[DataType].data(), WhatReassociationMethod[ReassociationMethod].data()), "hReassociation2dMftTracks", {HistType::kTH1D, {{Reassociation2dMftTracks::NReassociation2dMftTracksSteps, -0.5, +Reassociation2dMftTracks::NReassociation2dMftTracksSteps - 0.5}}}); std::string labelsReassociation2dMftTracks[Reassociation2dMftTracks::NReassociation2dMftTracksSteps]; labelsReassociation2dMftTracks[Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d] = "Ambiguous MFT tracks after track selection"; labelsReassociation2dMftTracks[Reassociation2dMftTracks::NotReassociated2dMftTracks] = "Not reassociated MFT tracks by DCAxy method"; labelsReassociation2dMftTracks[Reassociation2dMftTracks::Reassociated2dMftTracks] = "Reassociated MFT tracks by DCAxy method"; - registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->SetMinimum(0); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hReassociation2dMftTracks"))->SetMinimum(0); for (int iBin = 0; iBin < Reassociation2dMftTracks::NReassociation2dMftTracksSteps; iBin++) { - registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation2dMftTracks[iBin].data()); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hReassociation2dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation2dMftTracks[iBin].data()); } - registry.add(Form("%shReassociation3dMftTracks", WhatDataType[DataType].data()), "hReassociation3dMftTracks", {HistType::kTH1D, {{Reassociation3dMftTracks::NReassociation3dMftTracksSteps, -0.5, +Reassociation3dMftTracks::NReassociation3dMftTracksSteps - 0.5}}}); + registry.add(Form("%s%shReassociation3dMftTracks", WhatDataType[DataType].data(), WhatReassociationMethod[ReassociationMethod].data()), "hReassociation3dMftTracks", {HistType::kTH1D, {{Reassociation3dMftTracks::NReassociation3dMftTracksSteps, -0.5, +Reassociation3dMftTracks::NReassociation3dMftTracksSteps - 0.5}}}); std::string labelsReassociation3dMftTracks[Reassociation3dMftTracks::NReassociation3dMftTracksSteps]; labelsReassociation3dMftTracks[Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d] = "Ambiguous MFT tracks after track selection"; labelsReassociation3dMftTracks[Reassociation3dMftTracks::NotReassociated3dMftTracks] = "Not reassociated MFT tracks by DCAxyz method"; labelsReassociation3dMftTracks[Reassociation3dMftTracks::Reassociated3dMftTracks] = "Reassociated MFT tracks by DCAxyz method"; - registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->SetMinimum(0); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hReassociation3dMftTracks"))->SetMinimum(0); for (int iBin = 0; iBin < Reassociation3dMftTracks::NReassociation3dMftTracksSteps; iBin++) { - registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation3dMftTracks[iBin].data()); + registry.get(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hReassociation3dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation3dMftTracks[iBin].data()); } } - void addMftMonteCarloHistograms() + void addMftMonteCarloHistograms2D() { // AmbiguousTracks ZVtxDiff dist. (contains matched to true and not matched to true collision) - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hZVtxDiffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); // AmbiguousTracks NOT matched to true collisions ZVtxDiff dist. - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); // AmbiguousTracks matched to true collisions ZVtxDiff dist. - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTrackMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - - hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hZVtxDiffNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffNonAmbiguousTrackMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hZVtxDiff2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiff2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiff2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hZVtxDiffNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hZVtxDiffNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/hZVtxDiffNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hZVtxDiffNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hZVtxDiffNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/2D/hZVtxDiffNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/2D/hZVtxDiffNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/2D/hZVtxDiffNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hDcaAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hDcaAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hDcaAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNonAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hDcaNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hDcaNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hDcaNonAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDca2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDca2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDca2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDca2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hDca2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hDca2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hDca2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/2D/hDcaNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/2D/hDcaNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/2D/hDcaNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); - hDca3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDca3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDca3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDca3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/2D/hDcaNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/2D/hDcaNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/2D/hDcaNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/hDcaNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hDcaNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hDcaNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); - - registry.add("MC/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps]; labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous] = "number of MFT ambiguous tracks"; labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision] = "number of MFT ambiguous tracks matched to true collision"; labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision] = "number of MFT ambiguous tracks NOT matched to true collision"; - registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIsNonAmbiguousTrackMatchedToTrueCollision", "hIsNonAmbiguousTrackMatchedToTrue", {HistType::kTH1D, {{MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision", "hIsNonAmbiguousTrackMatchedToTrue", {HistType::kTH1D, {{MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps]; labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous] = "number of MFT Non ambiguous tracks"; labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision] = "number of MFT Non ambiguous tracks matched to true collision"; labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision] = "number of MFT Non ambiguous tracks NOT matched to true collision"; - registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIs2dReassociatedAndMatchedToTrueCollision", "Is2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision", "Is2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps]; labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated] = "number of MFT 2d reassociated tracks"; labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision] = "number of MFT 2d reassociated tracks matched to true collision"; labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 2d reassociated tracks NOT matched to true collision"; - registry.get(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIsNot2dReassociatedAndMatchedToTrueCollision", "IsNot2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision", "IsNot2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps]; labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated] = "number of MFT NOT 2d reassociated tracks"; labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks matched to true collision"; labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks NOT matched to true collision"; - registry.get(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/2D/hIsTrueCollisionAmongCompatibleCollisions", "IsTrueCollisionAmongCompatibleCollisions", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + std::string labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps]; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = "number of wrongly associated tracks"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks with True Coll. among Compatible"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks WITHOUT True Coll. among Compatible"; + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->SetMinimum(0); + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps; iBin++) { + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + } + } + + void addMftMonteCarloHistograms3D() + { + // AmbiguousTracks ZVtxDiff dist. (contains matched to true and not matched to true collision) + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hZVtxDiffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks NOT matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen> (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hZVtxDiffNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffNonAmbiguousTrackMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hZVtxDiff3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiff3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiff3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hZVtxDiffNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hZVtxDiffNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/3D/hZVtxDiffNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/3D/hZVtxDiffNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/3D/hZVtxDiffNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hDcaAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hDcaAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hDcaAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hDcaNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hDcaNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hDcaNonAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hDca3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hDca3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hDca3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/3D/hDcaNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/3D/hDcaNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/3D/hDcaNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/3D/hDcaNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/3D/hDcaNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/3D/hDcaNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + registry.add("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous] = "number of MFT ambiguous tracks"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision] = "number of MFT ambiguous tracks matched to true collision"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision] = "number of MFT ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision", "hIsNonAmbiguousTrackMatchedToTrue", {HistType::kTH1D, {{MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous] = "number of MFT Non ambiguous tracks"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision] = "number of MFT Non ambiguous tracks matched to true collision"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision] = "number of MFT Non ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIs3dReassociatedAndMatchedToTrueCollision", "Is3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision", "Is3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps]; labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated] = "number of MFT 3d reassociated tracks"; labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision] = "number of MFT 3d reassociated tracks matched to true collision"; labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 3d reassociated tracks NOT matched to true collision"; - registry.get(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIsNot3dReassociatedAndMatchedToTrueCollision", "IsNot3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + registry.add("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision", "IsNot3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps]; labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated] = "number of MFT NOT 3d reassociated tracks"; labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks matched to true collision"; labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks NOT matched to true collision"; - registry.get(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + registry.get(HIST("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); for (int iBin = 0; iBin < MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { - registry.get(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + registry.get(HIST("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); } - registry.add("MC/hIsTrueCollisionAmongCompatibleCollisions", "IsTrueCollisionAmongCompatibleCollisions", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); - registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); - registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/3D/hIsTrueCollisionAmongCompatibleCollisions", "IsTrueCollisionAmongCompatibleCollisions", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); std::string labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps]; labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = "number of wrongly associated tracks"; labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks with True Coll. among Compatible"; labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks WITHOUT True Coll. among Compatible"; - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->SetMinimum(0); - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->SetMinimum(0); - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->SetMinimum(0); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"))->SetMinimum(0); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->SetMinimum(0); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->SetMinimum(0); for (int iBin = 0; iBin < MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps; iBin++) { - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); - registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); } } - template + template void addParametersHistograms() { - registry.add(Form("MC/%shMftEta", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisEta}}); - registry.add(Form("MC/%shMftPhi", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPhi}}); - registry.add(Form("MC/%shMftPt", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPt}}); - registry.add(Form("MC/%shMftDcaXY", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisDcaX}}); - registry.add(Form("MC/%shMftDcaZ", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisDcaZ}}); - registry.add(Form("MC/%shMftAlgorithmUsed", WhatMcStatus[McStatus].data()), "hAlgorithmUsed", {HistType::kTH1D, {{TrackingAlgorithmStep::NTrackingAlgorithmSteps, -0.5, +TrackingAlgorithmStep::NTrackingAlgorithmSteps - 0.5}}}); + registry.add(Form("MC/%s%shMftEta", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisEta}}); + registry.add(Form("MC/%s%shMftPhi", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPhi}}); + registry.add(Form("MC/%s%shMftPt", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPt}}); + registry.add(Form("MC/%s%shMftDcaXY", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisDcaX}}); + registry.add(Form("MC/%s%shMftDcaZ", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisDcaZ}}); + registry.add(Form("MC/%s%shMftAlgorithmUsed", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "hMftAlgorithmUsed", {HistType::kTH1D, {{TrackingAlgorithmStep::NTrackingAlgorithmSteps, -0.5, +TrackingAlgorithmStep::NTrackingAlgorithmSteps - 0.5}}}); std::string labelsTrackingAlgorithm[TrackingAlgorithmStep::NTrackingAlgorithmSteps]; labelsTrackingAlgorithm[TrackingAlgorithmStep::IsLTFAlgorithm] = "IsLTF algorithm"; labelsTrackingAlgorithm[TrackingAlgorithmStep::IsCAAlgorithm] = "IsCA algorithm"; - registry.get(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"))->SetMinimum(0); - + registry.get(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"))->SetMinimum(0); for (int iBin = 0; iBin < TrackingAlgorithmStep::NTrackingAlgorithmSteps; iBin++) { - registry.get(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackingAlgorithm[iBin].data()); + registry.get(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackingAlgorithm[iBin].data()); } - registry.add(Form("MC/%shCollPosX", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPosX}}); - registry.add(Form("MC/%shCollPosY", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPosX}}); - registry.add(Form("MC/%shCollPosZ", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisVertex}}); - registry.add(Form("MC/%shCollMultiplicity", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); - registry.add(Form("MC/%shCollNumContrib", WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); + registry.add(Form("MC/%s%shCollPosX", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPosX}}); + registry.add(Form("MC/%s%shCollPosY", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisPosX}}); + registry.add(Form("MC/%s%shCollPosZ", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisVertex}}); + registry.add(Form("MC/%s%shCollMultiplicity", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); + registry.add(Form("MC/%s%shCollNumContrib", WhatReassociationMethod[ReassociationMethod].data(), WhatMcStatus[McStatus].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); } // ========================= @@ -637,7 +718,8 @@ struct MftReassociationValidation { // registry.add("Data/hNTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); registry.add(Form("Data/hMultiplicity_%s", WhatMultiplicityEstimator[configCollision.multiplicityEstimator].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); - registry.add("hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + registry.add("MC/2D/hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + registry.add("MC/3D/hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); std::string labels[SpecificEventSelectionStep::NSpecificEventSelectionSteps]; labels[SpecificEventSelectionStep::AllEventsPrecise] = "all"; labels[SpecificEventSelectionStep::HasMcCollision] = "has MC coll?"; @@ -653,13 +735,16 @@ struct MftReassociationValidation { labels[SpecificEventSelectionStep::IsNoHighMultCollInPrevRof] = "IsNoHighMultCollInPrevRof"; labels[SpecificEventSelectionStep::IsRctFlagChecked] = "IsRctFlagChecked"; labels[SpecificEventSelectionStep::IsWithinZvtxWindow] = "IsWithinZvtxWindow"; - registry.get(HIST("hPreciseEventCounter"))->SetMinimum(0); + registry.get(HIST("MC/2D/hPreciseEventCounter"))->SetMinimum(0); + registry.get(HIST("MC/3D/hPreciseEventCounter"))->SetMinimum(0); for (int iBin = 0; iBin < SpecificEventSelectionStep::NSpecificEventSelectionSteps; iBin++) { - registry.get(HIST("hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + registry.get(HIST("MC/2D/hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + registry.get(HIST("MC/3D/hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } - registry.add("MC/hPreciseTrackSelectionCounter", "hPreciseTrackSelectionCounter", {HistType::kTH1D, {{SpecificTrackSelectionStep::NSpecificTrackSelectionSteps, -0.5, +SpecificTrackSelectionStep::NSpecificTrackSelectionSteps - 0.5}}}); + registry.add("MC/2D/hPreciseTrackSelectionCounter", "hPreciseTrackSelectionCounter", {HistType::kTH1D, {{SpecificTrackSelectionStep::NSpecificTrackSelectionSteps, -0.5, +SpecificTrackSelectionStep::NSpecificTrackSelectionSteps - 0.5}}}); + registry.add("MC/3D/hPreciseTrackSelectionCounter", "hPreciseTrackSelectionCounter", {HistType::kTH1D, {{SpecificTrackSelectionStep::NSpecificTrackSelectionSteps, -0.5, +SpecificTrackSelectionStep::NSpecificTrackSelectionSteps - 0.5}}}); std::string labelsTrackSelection[SpecificTrackSelectionStep::NSpecificTrackSelectionSteps]; labelsTrackSelection[SpecificTrackSelectionStep::AllTracksPrecise] = "all tracks"; labelsTrackSelection[SpecificTrackSelectionStep::IsTrueTrack] = "true tracks"; @@ -672,44 +757,55 @@ struct MftReassociationValidation { labelsTrackSelection[SpecificTrackSelectionStep::IsCATrack] = "is CA track"; labelsTrackSelection[SpecificTrackSelectionStep::IsLTFTrack] = "is LTF track"; labelsTrackSelection[SpecificTrackSelectionStep::HasMcParticle] = "has MC particle"; - registry.get(HIST("MC/hPreciseTrackSelectionCounter"))->SetMinimum(0); + registry.get(HIST("MC/2D/hPreciseTrackSelectionCounter"))->SetMinimum(0); + registry.get(HIST("MC/3D/hPreciseTrackSelectionCounter"))->SetMinimum(0); for (int iBin = 0; iBin < SpecificTrackSelectionStep::NSpecificTrackSelectionSteps; iBin++) { - registry.get(HIST("MC/hPreciseTrackSelectionCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackSelection[iBin].data()); + registry.get(HIST("MC/2D/hPreciseTrackSelectionCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackSelection[iBin].data()); + registry.get(HIST("MC/3D/hPreciseTrackSelectionCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackSelection[iBin].data()); } - registry.add("MC/hTrackAmbiguityCheck", "hTrackAmbiguityCheck", {HistType::kTH1D, {{TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps, -0.5, +TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps - 0.5}}}); + registry.add("MC/2D/hTrackAmbiguityCheck", "hTrackAmbiguityCheck", {HistType::kTH1D, {{TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps, -0.5, +TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps - 0.5}}}); + registry.add("MC/3D/hTrackAmbiguityCheck", "hTrackAmbiguityCheck", {HistType::kTH1D, {{TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps, -0.5, +TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps - 0.5}}}); std::string labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps]; labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::AllTracksCheck] = "all tracks"; labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize] = "ambDegree == compatibleCollIds.size"; - registry.get(HIST("MC/hTrackAmbiguityCheck"))->SetMinimum(0); + registry.get(HIST("MC/2D/hTrackAmbiguityCheck"))->SetMinimum(0); + registry.get(HIST("MC/3D/hTrackAmbiguityCheck"))->SetMinimum(0); for (int iBin = 0; iBin < TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps; iBin++) { - registry.get(HIST("MC/hTrackAmbiguityCheck"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackAmbiguityCheck[iBin].data()); + registry.get(HIST("MC/2D/hTrackAmbiguityCheck"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackAmbiguityCheck[iBin].data()); + registry.get(HIST("MC/3D/hTrackAmbiguityCheck"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackAmbiguityCheck[iBin].data()); } - registry.add("MC/hMonteCarloEventCounter", "hMonteCarloEventCounter", {HistType::kTH1D, {{MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps, -0.5, +MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps - 0.5}}}); + registry.add("MC/2D/hMonteCarloEventCounter", "hMonteCarloEventCounter", {HistType::kTH1D, {{MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps, -0.5, +MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps - 0.5}}}); + registry.add("MC/3D/hMonteCarloEventCounter", "hMonteCarloEventCounter", {HistType::kTH1D, {{MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps, -0.5, +MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps - 0.5}}}); std::string labelsMonteCarloEvents[MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps]; labelsMonteCarloEvents[MonteCarloEventSelectionStep::AllMonteCarloEvents] = "all collisions"; labelsMonteCarloEvents[MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection] = "collisions after event selection"; labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasMonteCarloCollision] = "has MC collision"; labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasNotMonteCarloCollision] = "has not MC collision"; - registry.get(HIST("MC/hMonteCarloEventCounter"))->SetMinimum(0); + registry.get(HIST("MC/2D/hMonteCarloEventCounter"))->SetMinimum(0); + registry.get(HIST("MC/3D/hMonteCarloEventCounter"))->SetMinimum(0); for (int iBin = 0; iBin < MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps; iBin++) { - registry.get(HIST("MC/hMonteCarloEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloEvents[iBin].data()); + registry.get(HIST("MC/2D/hMonteCarloEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloEvents[iBin].data()); + registry.get(HIST("MC/3D/hMonteCarloEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloEvents[iBin].data()); } - registry.add("MC/hMonteCarloTrackCounter", "hMonteCarloTrackCounter", {HistType::kTH1D, {{MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps, -0.5, +MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps - 0.5}}}); + registry.add("MC/2D/hMonteCarloTrackCounter", "hMonteCarloTrackCounter", {HistType::kTH1D, {{MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps, -0.5, +MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps - 0.5}}}); + registry.add("MC/3D/hMonteCarloTrackCounter", "hMonteCarloTrackCounter", {HistType::kTH1D, {{MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps, -0.5, +MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps - 0.5}}}); std::string labelsMonteCarloTracks[MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps]; labelsMonteCarloTracks[MonteCarloTrackSelectionStep::AllMonteCarloTracks] = "all tracks"; labelsMonteCarloTracks[MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection] = "tracks after track selection"; labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasMonteCarloParticle] = "has MC particle"; labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasNotMonteCarloParticle] = "has not MC particle"; - registry.get(HIST("MC/hMonteCarloTrackCounter"))->SetMinimum(0); + registry.get(HIST("MC/2D/hMonteCarloTrackCounter"))->SetMinimum(0); + registry.get(HIST("MC/3D/hMonteCarloTrackCounter"))->SetMinimum(0); for (int iBin = 0; iBin < MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps; iBin++) { - registry.get(HIST("MC/hMonteCarloTrackCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloTracks[iBin].data()); + registry.get(HIST("MC/2D/hMonteCarloTrackCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloTracks[iBin].data()); + registry.get(HIST("MC/3D/hMonteCarloTrackCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloTracks[iBin].data()); } // ========================= @@ -717,25 +813,25 @@ struct MftReassociationValidation { // ========================= if (doprocessData) { - addMftHistograms(); + addMftHistograms(); } if (doprocessMcReassociated2d) { - addMftHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addMftMonteCarloHistograms(); + addMftHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addMftMonteCarloHistograms2D(); } if (doprocessMcReassociated3d) { - addMftHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addParametersHistograms(); - addMftMonteCarloHistograms(); + addMftHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addParametersHistograms(); + addMftMonteCarloHistograms3D(); } } // End of init() function @@ -831,33 +927,33 @@ struct MftReassociationValidation { } } - template + template void fillTrackParametersHistograms(TMftTrack const& mftTrack, float dcaXY, float dcaZ) { float phi = mftTrack.phi(); o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftEta"), mftTrack.eta()); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftPhi"), phi); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftPt"), mftTrack.pt()); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftDcaXY"), dcaXY); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftDcaZ"), dcaZ); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftEta"), mftTrack.eta()); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftPhi"), phi); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftPt"), mftTrack.pt()); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftDcaXY"), dcaXY); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftDcaZ"), dcaZ); if (mftTrack.isCA()) { - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"), TrackingAlgorithmStep::IsCAAlgorithm); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"), TrackingAlgorithmStep::IsCAAlgorithm); } else { - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"), TrackingAlgorithmStep::IsLTFAlgorithm); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hMftAlgorithmUsed"), TrackingAlgorithmStep::IsLTFAlgorithm); } } - template + template void fillCollisionParametersHistograms(TPosX const& posX, TPosY const& posY, TPosZ const& posZ, TMultiplicity const& multiplicity, TNumContrib const& numContrib) { - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosX"), posX); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosY"), posY); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosZ"), posZ); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hCollMultiplicity"), multiplicity); - registry.fill(HIST("MC/") + HIST(WhatMcStatus[McStatus]) + HIST("hCollNumContrib"), numContrib); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosX"), posX); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosY"), posY); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hCollPosZ"), posZ); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hCollMultiplicity"), multiplicity); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST(WhatMcStatus[McStatus]) + HIST("hCollNumContrib"), numContrib); } // ========================= @@ -865,63 +961,64 @@ struct MftReassociationValidation { // ========================= // FIXME: Some collisions are rejected here, what causes (part of) differences with the D0 task - template + template bool isAcceptedCollision(TCollision const& collision, bool fillHistograms = false) { if (!collision.sel8()) { return false; } + if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); } if (configCollision.isApplySameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); } if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); } if (configCollision.isApplyGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); } if (configCollision.isApplyNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); } if (configCollision.isApplyNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); } if (configCollision.isApplyNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); } if (configCollision.isApplyNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); } if (configCollision.isApplyNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); } if (configCollision.requireRCTFlagChecker && !rctChecker(collision)) { return false; @@ -930,13 +1027,13 @@ struct MftReassociationValidation { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); } if (collision.posZ() > configCollision.zVertexMax || collision.posZ() < (-configCollision.zVertexMax)) { return false; } if (fillHistograms) { - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsWithinZvtxWindow); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsWithinZvtxWindow); } registry.fill(HIST("Data/hVtxZ"), collision.posZ()); @@ -947,7 +1044,7 @@ struct MftReassociationValidation { // TODO: Check how to put this into a Filter // I tried to put it as a filter, but filters for normal TPC tracks also apply to MFT tracks I think // and it seems that they are not compatible - template + template bool isAcceptedMftTrack(TTrack const& mftTrack, bool fillHistograms, bool isData, float dcaXY, float dcaZ) { // cut on the eta of MFT tracks @@ -957,12 +1054,11 @@ struct MftReassociationValidation { if (fillHistograms) { if (isData) { - registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Eta); + registry.fill(HIST("Data/2D/hMftTracksSelection"), MftTrackSelectionStep::Eta); } else { - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterEtaCut); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterEtaCut); } } - // cut on the number of clusters of the reconstructed MFT track if (mftTrack.nClusters() < configMft.nClustersMftTrack) { return false; @@ -970,9 +1066,9 @@ struct MftReassociationValidation { if (fillHistograms) { if (isData) { - registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Cluster); + registry.fill(HIST("Data/2D/hMftTracksSelection"), MftTrackSelectionStep::Cluster); } else { - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterClusterCut); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterClusterCut); } } @@ -983,28 +1079,27 @@ struct MftReassociationValidation { if (fillHistograms) { if (isData) { - registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Pt); + registry.fill(HIST("Data/2D/hMftTracksSelection"), MftTrackSelectionStep::Pt); } else { - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterPtCut); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterPtCut); } } if (configMft.cutOnDcaXY && std::abs(dcaXY) > configMft.dcaXYMax) { return false; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaXYCut); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaXYCut); if (configMft.cutOnDcaZ && std::abs(dcaZ) > configMft.dcaZMax) { return false; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaZCut); - + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaZCut); // cut on the track algorithm of MFT tracks if (mftTrack.isCA()) { if (fillHistograms) { if (isData) { - registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::IsCA); + registry.fill(HIST("Data/2D/hMftTracksSelection"), MftTrackSelectionStep::IsCA); } else { - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsCATrack); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsCATrack); } } @@ -1015,9 +1110,9 @@ struct MftReassociationValidation { } else { if (fillHistograms) { if (isData) { - registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::IsLTF); + registry.fill(HIST("Data/2D/hMftTracksSelection"), MftTrackSelectionStep::IsLTF); } else { - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsLTFTrack); + registry.fill(HIST("MC/") + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsLTFTrack); } } @@ -1030,29 +1125,29 @@ struct MftReassociationValidation { } // Cut on ambiguous MFT tracks - template + template bool isAmbiguousMftTrack(TTrack const& mftTrack, bool fillHistograms) { if (mftTrack.ambDegree() > 1) { if (fillHistograms) { - registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); } return true; if (mftTrack.ambDegree() > 1) { if (fillHistograms) { - registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); } return true; } if (fillHistograms) { - registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); } return false; } if (fillHistograms) { - registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST(WhatDataType[DataType]) + HIST(WhatReassociationMethod[ReassociationMethod]) + HIST("hPreciseTrackSelectionCounter"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); } return false; } @@ -1071,7 +1166,7 @@ struct MftReassociationValidation { auto bc = collision.template bc_as(); loadZVertexShiftCorrection(bc); - if (!(isAcceptedCollision(collision, true))) { + if (!(isAcceptedCollision(collision, true))) { return; } @@ -1088,13 +1183,13 @@ struct MftReassociationValidation { auto dcaXYoriginal = 999.f; dcaXYoriginal = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); - if (!isAcceptedMftTrack(templatedMftTrack, false, true, dcaXYoriginal, dcaInfOrig[2])) { + if (!isAcceptedMftTrack(templatedMftTrack, false, true, dcaXYoriginal, dcaInfOrig[2])) { continue; } registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); - if (isAmbiguousMftTrack(reassociated2dMftTrack, true)) { + if (isAmbiguousMftTrack(reassociated2dMftTrack, true)) { registry.fill(HIST("Data/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); } @@ -1147,16 +1242,16 @@ struct MftReassociationValidation { auto bc = collision.template bc_as(); loadZVertexShiftCorrection(bc); - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + registry.fill(HIST("MC/2D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("MC/2D/hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); if (!collision.has_mcCollision()) { - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + registry.fill(HIST("MC/2D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); return; } - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + registry.fill(HIST("MC/2D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("MC/2D/hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); const int mcCollisionId = collision.mcCollisionId(); auto iteratorMcCollisionBestCollIndex = recoMcCollBestCollisionIndex.find(mcCollisionId); @@ -1169,13 +1264,13 @@ struct MftReassociationValidation { return; } - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); + registry.fill(HIST("MC/2D/hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); - if (!isAcceptedCollision(collision, true)) { + if (!isAcceptedCollision(collision, true)) { return; } - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + registry.fill(HIST("MC/2D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); for (auto const& reassociated2dMftTrack : reassociated2dMftTracks) { @@ -1188,10 +1283,10 @@ struct MftReassociationValidation { } } - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); - registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); + registry.fill(HIST("MC/2D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/2D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + registry.fill(HIST("MC/2D/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); + registry.fill(HIST("MC/2D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); auto templatedTrack = reassociated2dMftTrack.template mfttrack_as(); @@ -1204,26 +1299,24 @@ struct MftReassociationValidation { if (configMft.cutFakeTracks && templatedTrack.mcMask() != 0) { continue; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); + registry.fill(HIST("MC/2D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); if (configMft.cutOrphanTracksExplicitly && reassociated2dMftTrack.ambDegree() == 0) { continue; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); - - if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { + registry.fill(HIST("MC/2D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); + if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { continue; } if (reassociated2dMftTrack.ambDegree() == static_cast(reassociated2dMftTrack.compatibleCollIds().size())) { - registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); + registry.fill(HIST("MC/2D/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); } - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); - + registry.fill(HIST("MC/2D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/2D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); if (templatedTrack.has_mcParticle()) { - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); + registry.fill(HIST("MC/2D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + registry.fill(HIST("MC/2D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); auto particle = templatedTrack.template mcParticle_as(); float deltaX = -999.f; @@ -1303,130 +1396,130 @@ struct MftReassociationValidation { auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); if (reassociated2dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); - registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/2D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/2D/hReassociation2dMftTracks"), Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); } else { - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/2D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); } if (templatedTrack.collisionId() == reassociated2dMftTrack.bestCollisionId()) { // IS NOT 2D REASSOCIATED - registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); - registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated); + registry.fill(HIST("MC/2D/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); + registry.fill(HIST("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated); hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); if (mcCollisionIdReco == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision); + registry.fill(HIST("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision); hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision); + registry.fill(HIST("MC/2D/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision); hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } } } else { // IS 2D REASSOCIATED - registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::Reassociated2dMftTracks); - registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated); + registry.fill(HIST("MC/2D/hReassociation2dMftTracks"), Reassociation2dMftTracks::Reassociated2dMftTracks); + registry.fill(HIST("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated); hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); // is collision.mcCollisionId() the reassociated collision vertex ? or the initial collision if (mcCollisionIdReco == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision); + registry.fill(HIST("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision); hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision); + registry.fill(HIST("MC/2D/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision); hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/2D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks2D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } } } } else { // NON AMBI TRACKS - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/2D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); + registry.fill(HIST("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); } else { - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); - fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); + registry.fill(HIST("MC/2D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks2D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated2dMftTrack.bestDCAXY(), 0.f); + fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); } } // end of if non ambi } else { - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + registry.fill(HIST("MC/2D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); } } // end of loop over reassociated2dMftTracks } @@ -1442,16 +1535,16 @@ struct MftReassociationValidation { auto bc = collision.template bc_as(); loadZVertexShiftCorrection(bc); - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + registry.fill(HIST("MC/3D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("MC/3D/hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); if (!collision.has_mcCollision()) { - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + registry.fill(HIST("MC/3D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); return; } - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + registry.fill(HIST("MC/3D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("MC/3D/hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); const int mcCollisionId = collision.mcCollisionId(); auto iteratorMcCollisionBestCollIndex = recoMcCollBestCollisionIndex.find(mcCollisionId); @@ -1464,13 +1557,13 @@ struct MftReassociationValidation { return; } - registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); + registry.fill(HIST("MC/3D/hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); - if (!isAcceptedCollision(collision, true)) { + if (!isAcceptedCollision(collision, true)) { return; } - registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + registry.fill(HIST("MC/3D/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); for (auto const& reassociated3dMftTrack : reassociated3dMftTracks) { @@ -1483,10 +1576,10 @@ struct MftReassociationValidation { } } - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); - registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); + registry.fill(HIST("MC/3D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/3D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + registry.fill(HIST("MC/3D/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); + registry.fill(HIST("MC/3D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); auto templatedTrack = reassociated3dMftTrack.template mfttrack_as(); @@ -1499,26 +1592,24 @@ struct MftReassociationValidation { if (configMft.cutFakeTracks && templatedTrack.mcMask() != 0) { continue; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); + registry.fill(HIST("MC/3D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); if (configMft.cutOrphanTracksExplicitly && reassociated3dMftTrack.ambDegree() == 0) { continue; } - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); - - if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { + registry.fill(HIST("MC/3D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); + if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { continue; } if (reassociated3dMftTrack.ambDegree() == static_cast(reassociated3dMftTrack.compatibleCollIds().size())) { - registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); + registry.fill(HIST("MC/3D/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); } - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); - + registry.fill(HIST("MC/3D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/3D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); if (templatedTrack.has_mcParticle()) { - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); - registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); + registry.fill(HIST("MC/3D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + registry.fill(HIST("MC/3D/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); auto particle = templatedTrack.template mcParticle_as(); float deltaX = -999.f; @@ -1598,129 +1689,129 @@ struct MftReassociationValidation { auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); if (reassociated3dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); - registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/3D/hReassociation3dMftTracks"), Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d); + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); } else { - registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); - hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); } if (templatedTrack.collisionId() == reassociated3dMftTrack.bestCollisionId()) { // IS NOT 3D REASSOCIATED - registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::NotReassociated3dMftTracks); - registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated); + registry.fill(HIST("MC/3D/hReassociation3dMftTracks"), Reassociation3dMftTracks::NotReassociated3dMftTracks); + registry.fill(HIST("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated); hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); if (mcCollisionIdReco == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision); + registry.fill(HIST("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision); hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision); + registry.fill(HIST("MC/3D/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision); hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } } } else { // IS 3D REASSOCIATED - registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::Reassociated3dMftTracks); - registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated); + registry.fill(HIST("MC/3D/hReassociation3dMftTracks"), Reassociation3dMftTracks::Reassociated3dMftTracks); + registry.fill(HIST("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated); hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); if (mcCollisionIdReco == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision); + registry.fill(HIST("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision); hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision); + registry.fill(HIST("MC/3D/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision); hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } else { - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); - hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); - hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/3D/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks3D[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(xPosBestColl, yPosBestColl, zPosBestColl, bestCollMult, bestCollNumContrib); } } } } else { // NON AMBI TRACKS - registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + registry.fill(HIST("MC/3D/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); if (collision.mcCollisionId() == particle.mcCollisionId()) { - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); + registry.fill(HIST("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); } else { - registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); - hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); - hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); - fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); - fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); + registry.fill(HIST("MC/3D/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks3D[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + fillTrackParametersHistograms(templatedTrack, reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ()); + fillCollisionParametersHistograms(collision.posX(), collision.posY(), collision.posZ(), getMultiplicityEstimator(collision), collision.numContrib()); } } // end of if non ambi } else { - registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + registry.fill(HIST("MC/3D/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); } } // end of loop over reassociated3dMftTracks } From e126219f50759a5cd510afbed616a496f8fe5c90 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 15 May 2026 16:25:38 +0200 Subject: [PATCH 179/449] [ALICE3] Refactor otf decayer and fix indices for cascade decays (#16262) --- ALICE3/Core/TrackUtilities.h | 101 +++- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 473 +++---------------- 2 files changed, 152 insertions(+), 422 deletions(-) diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index 1b042452899..6e4905672bd 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -22,20 +22,25 @@ #include +#include #include +#include #include namespace o2::upgrade { -/// Struct to store mc info for the otf decayer -struct OTFParticle { +class OTFParticle +{ + public: OTFParticle() = default; template explicit OTFParticle(const TParticle& particle) { mPdgCode = particle.pdgCode(); + mGlobalIndex = particle.globalIndex(); + mCollisionId = particle.mcCollisionId(); mPx = particle.px(); mPy = particle.py(); mPz = particle.pz(); @@ -43,18 +48,26 @@ struct OTFParticle { mVx = particle.vx(); mVy = particle.vy(); mVz = particle.vz(); + mIsFromMcParticles = true; + if (particle.has_mothers()) { + mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; + } } // Setters - void setIsAlive(bool isAlive) { mIsAlive = isAlive; } - void setPDG(int pdg) { mPdgCode = pdg; } - void setVxVyVz(float vx, float vy, float vz) + void setIsAlive(const bool isAlive) { mIsAlive = isAlive; } + void setIsPrimary(const bool isPrimary) { mIsPrimary = isPrimary; } + void setCollisionId(const int collisionId) { mCollisionId = collisionId; } + void setPDG(const int pdg) { mPdgCode = pdg; } + void setIndicesMother(const int start, const int stop) { mIndicesMother = {start, stop}; } + void setIndicesDaughter(const int start, const int stop) { mIndicesDaughter = {start, stop}; } + void setVxVyVz(const float vx, const float vy, const float vz) { mVx = vx; mVy = vy; mVz = vz; } - void setPxPyPzE(float px, float py, float pz, float e) + void setPxPyPzE(const float px, const float py, const float pz, const float e) { mPx = px; mPy = py; @@ -64,7 +77,31 @@ struct OTFParticle { // Getters int pdgCode() const { return mPdgCode; } + int globalIndex() const { return mGlobalIndex; } + int collisionId() const { return mCollisionId; } bool isAlive() const { return mIsAlive; } + bool isPrimary() const { return mIsPrimary; } + bool isFromMcParticles() const { return mIsFromMcParticles; } + float weight() const + { + static constexpr float Weight = 1.f; + return Weight; + } + uint8_t flags() const + { + static constexpr uint8_t Flags = 1; + return Flags; + } + float vt() const + { + static constexpr float Vt = 1.f; + return Vt; + } + int statusCode() const + { + static constexpr int StatusCode = 1; + return StatusCode; + } float vx() const { return mVx; } float vy() const { return mVy; } float vz() const { return mVz; } @@ -73,15 +110,63 @@ struct OTFParticle { float pz() const { return mPz; } float e() const { return mE; } float radius() const { return std::hypot(mVx, mVy); } + float r() const { return radius(); } float pt() const { return std::hypot(mPx, mPy); } float p() const { return std::hypot(mPx, mPy, mPz); } + float phi() const { return o2::constants::math::PI + std::atan2(-1.0f * py(), -1.0f * px()); } + float eta() const + { + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 + static constexpr float Tolerance = 1e-7f; + if ((p() - mPz) < Tolerance) { + return (mPz < 0.0f) ? -100.0f : 100.0f; + } else { + return 0.5f * std::log((p() + mPz) / (p() - mPz)); + } + } + + float y() const + { + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 + static constexpr float Tolerance = 1e-7f; + if ((e() - mPz) < Tolerance) { + return (mPz < 0.0f) ? -100.0f : 100.0f; + } else { + return 0.5f * std::log((mE + mPz) / (mE - mPz)); + } + } + + bool hasDaughters() const { return (mIndicesDaughter[0] > 0); } + bool hasMothers() const { return (mIndicesMother[0] > 0); } + int getMotherIndexStart() const { return mIndicesMother[0]; } + int getMotherIndexStop() const { return mIndicesMother[1]; } + int getDaughterIndexStart() const { return mIndicesDaughter[0]; } + int getDaughterIndexStop() const { return mIndicesDaughter[1]; } + std::array getMothers() const { return mIndicesMother; } + std::array getDaughters() const { return mIndicesDaughter; } + std::span getMotherSpan() const { return hasMothers() ? std::span(mIndicesMother.data(), 2) : std::span(); } + + bool hasNaN() const + { + return std::isnan(mPx) || std::isnan(mPy) || std::isnan(mPz) || std::isnan(mE) || + std::isnan(mVx) || std::isnan(mVy) || std::isnan(mVz); + } + + bool hasIndex() const + { + return (mGlobalIndex != -1); + } private: - int mPdgCode{}; + int mPdgCode{}, mGlobalIndex{-1}; + int mCollisionId{}; float mE{}; float mVx{}, mVy{}, mVz{}; float mPx{}, mPy{}, mPz{}; - bool mIsAlive{}; + bool mIsAlive{}, mIsFromMcParticles{false}; + bool mIsPrimary{}; + + std::array mIndicesMother{-1, -1}, mIndicesDaughter{-1, -1}; }; /// Function to convert a TLorentzVector into a perfect Track diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 9c308ebe6ab..c7713d9c45d 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -38,9 +38,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -53,7 +53,6 @@ using namespace o2::framework; static constexpr int NumDecays = 7; static constexpr int NumParameters = 1; static constexpr int DefaultParameters[NumDecays][NumParameters]{{1}, {1}, {1}, {1}, {1}, {1}, {1}}; -static constexpr float Tolerance = 1e-7f; static const std::vector ParameterNames{"enable"}; static const std::vector ParticleNames{"K0s", "Lambda", @@ -71,23 +70,6 @@ static const std::vector pdgCodes{PDG_t::kK0Short, PDG_t::kOmegaMinus, PDG_t::kOmegaPlusBar}; -enum class V0 { kNeg, - kPos, - kSize }; -enum class AntiV0 { kPos, - kNeg, - kSize }; -enum class Cascade { kBach, - kV0, - kNeg, - kPos, - kSize }; -enum class AntiCascade { kBach, - kV0, - kPos, - kNeg, - kSize }; - struct OnTheFlyDecayer { Produces tableMcParticlesWithDau; @@ -97,155 +79,23 @@ struct OnTheFlyDecayer { Configurable seed{"seed", 0, "Set seed for particle decayer"}; Configurable magneticField{"magneticField", 20., "Magnetic field (kG)"}; - Configurable maxEta{"maxEta", 2.5, "Only decay particles that appear within selected eta range"}; Configurable> enabledDecays{"enabledDecays", {DefaultParameters[0], NumDecays, NumParameters, ParticleNames, ParameterNames}, "Enable option for particle to be decayed: 0 - no, 1 - yes"}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - ConfigurableAxis axisRadius{"axisRadius", {200, 0, 100}, "Radial axis"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; - - ConfigurableAxis axisLogRadius{"axisLogRadius", {VARIABLE_WIDTH, 0.0f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f, 10.4713f, 10.9648f, 11.4815f, 12.0226f, 12.5893f, 13.1826f, 13.8038f, 14.4544f, 15.1356f, 15.8489f, 16.5959f, 17.378f, 18.197f, 19.0546f, 19.9526f, 20.893f, 21.8776f, 22.9087f, 23.9883f, 25.1189f, 26.3027f, 27.5423f, 28.8403f, 30.1995f, 31.6228f, 33.1131f, 34.6737f, 36.3078f, 38.0189f, 39.8107f, 41.6869f, 43.6516f, 45.7088f, 47.863f, 50.1187f, 52.4807f, 54.9541f, 57.544f, 60.256f, 63.0957f, 66.0693f, 69.1831f, 72.4436f, 75.8578f, 79.4328f, 83.1764f, 87.0964f, 91.2011f, 95.4993f, 100.0f}, "Radial axis"}; - - ConfigurableAxis axisLogPt{"axisLogPt", {VARIABLE_WIDTH, 0.0f, 0.001f, 0.00104713f, 0.00109648f, 0.00114815f, 0.00120226f, 0.00125893f, 0.00131826f, 0.00138038f, 0.00144544f, 0.00151356f, 0.00158489f, 0.00165959f, 0.0017378f, 0.0018197f, 0.00190546f, 0.00199526f, 0.0020893f, 0.00218776f, 0.00229087f, 0.00239883f, 0.00251189f, 0.00263027f, 0.00275423f, 0.00288403f, 0.00301995f, 0.00316228f, 0.00331131f, 0.00346737f, 0.00363078f, 0.00380189f, 0.00398107f, 0.00416869f, 0.00436516f, 0.00457088f, 0.0047863f, 0.00501187f, 0.00524807f, 0.00549541f, 0.0057544f, 0.0060256f, 0.00630957f, 0.00660693f, 0.00691831f, 0.00724436f, 0.00758578f, 0.00794328f, 0.00831764f, 0.00870964f, 0.00912011f, 0.00954993f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f}, "pt axis for QA histograms"}; - - struct McParticleAlice3 { - McParticleAlice3() = default; - ~McParticleAlice3() = default; - McParticleAlice3(const McParticleAlice3& src) = default; - McParticleAlice3(int collisionId, - int pdgCode, - int statusCode, - int flags, - int mother0, - int mother1, - int daughter0, - int daughter1, - float weight, - float px, float py, float pz, float e, - float vx, float vy, float vz, float vt, - float phi, float eta, float pt, float p, float y, - bool isAlive, bool isPrimary) : collisionId(collisionId), - pdgCode(pdgCode), - statusCode(statusCode), - flags(flags), - mothersIds{mother0, mother1}, - daughtersIdSlice{daughter0, daughter1}, - weight(weight), - px(px), - py(py), - pz(pz), - e(e), - vx(vx), - vy(vy), - vz(vz), - vt(vt), - phi(phi), - eta(eta), - pt(pt), - p(p), - y(y), - isAlive(isAlive), - isPrimary(isPrimary) {} - - bool hasNaN() const - { - return std::isnan(px) || std::isnan(py) || std::isnan(pz) || std::isnan(e) || - std::isnan(vx) || std::isnan(vy) || std::isnan(vz) || std::isnan(vt) || - std::isnan(phi) || std::isnan(eta) || std::isnan(pt) || std::isnan(p) || - std::isnan(y) || std::isnan(weight); - } - - int collisionId; - int pdgCode; - int statusCode; - int flags; - int mothersIds[2]; - int daughtersIdSlice[2]; - float weight; - float px, py, pz, e; - float vx, vy, vz, vt; - float phi, eta, pt, p, y; - bool isAlive; - bool isPrimary; - }; - - template - int idx(TEnumerate enumerate) - { - return static_cast(enumerate); - } - - bool checkDecayChannel(const int pdgMother, const std::vector& daus) - { - switch (pdgMother) { - case PDG_t::kK0Short: - if (daus.size() != static_cast(V0::kSize)) { - return false; - } - return (daus[idx(V0::kNeg)].pdgCode() == PDG_t::kPiMinus && - daus[idx(V0::kPos)].pdgCode() == PDG_t::kPiPlus); - case PDG_t::kLambda0: - if (daus.size() != static_cast(V0::kSize)) { - return false; - } - return (daus[idx(V0::kNeg)].pdgCode() == PDG_t::kPiMinus && - daus[idx(V0::kPos)].pdgCode() == PDG_t::kProton); - case PDG_t::kLambda0Bar: - if (daus.size() != static_cast(AntiV0::kSize)) { - return false; - } - return (daus[idx(AntiV0::kNeg)].pdgCode() == PDG_t::kProtonBar && - daus[idx(AntiV0::kPos)].pdgCode() == PDG_t::kPiPlus); - case PDG_t::kXiMinus: - if (daus.size() != static_cast(Cascade::kSize)) { - return false; - } - return (daus[idx(Cascade::kBach)].pdgCode() == PDG_t::kPiMinus && - daus[idx(Cascade::kV0)].pdgCode() == PDG_t::kLambda0 && - daus[idx(Cascade::kNeg)].pdgCode() == PDG_t::kPiMinus && - daus[idx(Cascade::kPos)].pdgCode() == PDG_t::kProton); - case PDG_t::kXiPlusBar: - if (daus.size() != static_cast(AntiCascade::kSize)) { - return false; - } - return (daus[idx(AntiCascade::kBach)].pdgCode() == PDG_t::kPiPlus && - daus[idx(AntiCascade::kV0)].pdgCode() == PDG_t::kLambda0Bar && - daus[idx(AntiCascade::kPos)].pdgCode() == PDG_t::kPiPlus && - daus[idx(AntiCascade::kNeg)].pdgCode() == PDG_t::kProtonBar); - case PDG_t::kOmegaMinus: - if (daus.size() != static_cast(Cascade::kSize)) { - return false; - } - return (daus[idx(Cascade::kBach)].pdgCode() == PDG_t::kKMinus && - daus[idx(Cascade::kV0)].pdgCode() == PDG_t::kLambda0 && - daus[idx(Cascade::kNeg)].pdgCode() == PDG_t::kPiMinus && - daus[idx(Cascade::kPos)].pdgCode() == PDG_t::kProton); - case PDG_t::kOmegaPlusBar: - if (daus.size() != static_cast(AntiCascade::kSize)) { - return false; - } - return (daus[idx(AntiCascade::kBach)].pdgCode() == PDG_t::kKPlus && - daus[idx(AntiCascade::kV0)].pdgCode() == PDG_t::kLambda0Bar && - daus[idx(AntiCascade::kPos)].pdgCode() == PDG_t::kPiPlus && - daus[idx(AntiCascade::kNeg)].pdgCode() == PDG_t::kProtonBar); - default: - return false; - } - } std::vector mEnabledDecays; void init(o2::framework::InitContext&) { - LOG(info) << "Initializing on-the-fly-decayer."; - LOG(info) << "Using seed: " << seed; - LOG(info) << "Using magnetic field: " << magneticField; + LOG(info) << " --- Initializing on-the-fly-decayer."; + LOG(info) << " --- Using seed: " << seed; + LOG(info) << " --- Using magnetic field: " << magneticField; decayer.setSeed(seed); decayer.setBField(magneticField); for (int i = 0; i < NumDecays; ++i) { if (enabledDecays->get(ParticleNames[i].c_str(), "enable")) { - LOG(info) << "Decay enabled: " << ParticleNames[i].c_str(); + LOG(info) << " --- Decay enabled: " << pdgCodes[i]; mEnabledDecays.push_back(pdgCodes[i]); } } @@ -253,287 +103,82 @@ struct OnTheFlyDecayer { auto hNaNBookkeeping = histos.add("hNaNBookkeeping", "hNaNBookkeeping", kTH1D, {{2, -0.5, 1.5}}); hNaNBookkeeping->GetXaxis()->SetBinLabel(1, "OK"); hNaNBookkeeping->GetXaxis()->SetBinLabel(2, "NaN"); - - histos.add("K0S/hGenK0S", "hGenK0S;pT (GeV)", kTH1D, {axisPt}); - histos.add("K0S/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("K0S/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("Lambda/hGenLambda", "hGenLambda;pT (GeV)", kTH1D, {axisPt}); - histos.add("Lambda/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Lambda/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("AntiLambda/hGenAntiLambda", "hGenAntiLambda;pT (GeV)", kTH1D, {axisPt}); - histos.add("AntiLambda/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiLambda/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("Xi/hGenXi", "hGenXi;pT (GeV)", kTH1D, {axisPt}); - histos.add("Xi/hV0DauDecayRadius", "hV0DauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Xi/hBachDauDecayRadius", "hBachDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Xi/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Xi/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("AntiXi/hGenAntiXi", "hGenAntiXi;pT (GeV)", kTH1D, {axisPt}); - histos.add("AntiXi/hV0DauDecayRadius", "hV0DauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiXi/hBachDauDecayRadius", "hBachDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiXi/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiXi/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("Omega/hGenOmega", "hGenOmega;pT (GeV)", kTH1D, {axisPt}); - histos.add("Omega/hV0DauDecayRadius", "hV0DauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Omega/hBachDauDecayRadius", "hBachDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Omega/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("Omega/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("AntiOmega/hGenAntiOmega", "hGenAntiOmega;pT (GeV)", kTH1D, {axisPt}); - histos.add("AntiOmega/hV0DauDecayRadius", "hV0DauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiOmega/hBachDauDecayRadius", "hBachDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiOmega/hPosDauDecayRadius", "hPosDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - histos.add("AntiOmega/hNegDauDecayRadius", "hNegDauDecayRadius;Radius decay vtx 2D (cm); Daughter pT (GeV)", kTH2D, {axisLogRadius, axisLogPt}); - - histos.add("Secondaries/hGenEl", "hGenEl;pT (GeV)", kTH1D, {axisPt}); - histos.add("Secondaries/hGenMu", "hGenMu;pT (GeV)", kTH1D, {axisPt}); - histos.add("Secondaries/hGenPi", "hGenPi;pT (GeV)", kTH1D, {axisPt}); - histos.add("Secondaries/hGenKa", "hGenKa;pT (GeV)", kTH1D, {axisPt}); - histos.add("Secondaries/hGenPr", "hGenPr;pT (GeV)", kTH1D, {axisPt}); } - bool canDecay(const int pdgCode) + bool canDecay(const o2::upgrade::OTFParticle& particle) { - return std::find(mEnabledDecays.begin(), mEnabledDecays.end(), pdgCode) != mEnabledDecays.end(); + if (particle.hasDaughters()) { + return false; + } + + return std::find(mEnabledDecays.begin(), mEnabledDecays.end(), particle.pdgCode()) != mEnabledDecays.end(); } - std::vector mcParticlesAlice3; - void process(aod::McCollision const&, aod::McParticles const& mcParticles) + std::vector allParticles; + void decayParticles(const int start, const int stop) { - mDecayDaughters.clear(); - mcParticlesAlice3.clear(); - u_int64_t nStoredDaughters = 0; - for (int index{0}; index < static_cast(mcParticles.size()); ++index) { - const auto& particle = mcParticles.rawIteratorAt(index); - std::vector decayDaughters, decayStack; - if (canDecay(particle.pdgCode()) && std::abs(particle.eta()) < maxEta) { - o2::upgrade::OTFParticle mother(particle); - decayStack = decayer.decayParticle(pdgDB, mother); - while (!decayStack.empty()) { - o2::upgrade::OTFParticle otfParticle = decayStack.back(); - decayStack.pop_back(); - - const bool stable = !canDecay(otfParticle.pdgCode()); - otfParticle.setIsAlive(stable); - decayDaughters.push_back(otfParticle); - - if (stable) { - continue; - } - - std::vector daughters = decayer.decayParticle(pdgDB, otfParticle); - for (const o2::upgrade::OTFParticle& dau : daughters) { - decayStack.push_back(dau); - } - } - - if (decayDaughters.empty()) { - LOG(error) << "Attempted to decay " << particle.pdgCode() << " but resulting vector of daugthers were empty"; - continue; - } - - switch (particle.pdgCode()) { // Do QA on specific channels - case PDG_t::kK0Short: - if (!checkDecayChannel(PDG_t::kK0Short, decayDaughters)) { - break; - } - histos.fill(HIST("K0S/hGenK0S"), particle.pt()); - histos.fill(HIST("K0S/hPosDauDecayRadius"), decayDaughters[idx(V0::kPos)].radius(), decayDaughters[idx(V0::kPos)].pt()); - histos.fill(HIST("K0S/hNegDauDecayRadius"), decayDaughters[idx(V0::kNeg)].radius(), decayDaughters[idx(V0::kNeg)].pt()); - break; - - case PDG_t::kLambda0: - if (!checkDecayChannel(PDG_t::kLambda0, decayDaughters)) { - break; - } - histos.fill(HIST("Lambda/hGenLambda"), particle.pt()); - histos.fill(HIST("Lambda/hPosDauDecayRadius"), decayDaughters[idx(V0::kPos)].radius(), decayDaughters[idx(V0::kPos)].pt()); - histos.fill(HIST("Lambda/hNegDauDecayRadius"), decayDaughters[idx(V0::kNeg)].radius(), decayDaughters[idx(V0::kNeg)].pt()); - break; - - case PDG_t::kLambda0Bar: - if (!checkDecayChannel(PDG_t::kLambda0Bar, decayDaughters)) { - break; - } - histos.fill(HIST("AntiLambda/hGenAntiLambda"), particle.pt()); - histos.fill(HIST("AntiLambda/hPosDauDecayRadius"), decayDaughters[idx(AntiV0::kPos)].radius(), decayDaughters[idx(AntiV0::kPos)].pt()); - histos.fill(HIST("AntiLambda/hNegDauDecayRadius"), decayDaughters[idx(AntiV0::kNeg)].radius(), decayDaughters[idx(AntiV0::kNeg)].pt()); - break; - - case PDG_t::kXiMinus: - if (!checkDecayChannel(PDG_t::kXiMinus, decayDaughters)) { - break; - } - histos.fill(HIST("Xi/hGenXi"), particle.pt()); - histos.fill(HIST("Xi/hBachDauDecayRadius"), decayDaughters[idx(Cascade::kBach)].radius(), decayDaughters[idx(Cascade::kBach)].pt()); - histos.fill(HIST("Xi/hV0DauDecayRadius"), decayDaughters[idx(Cascade::kV0)].radius(), decayDaughters[idx(Cascade::kV0)].pt()); - histos.fill(HIST("Xi/hPosDauDecayRadius"), decayDaughters[idx(Cascade::kPos)].radius(), decayDaughters[idx(Cascade::kPos)].pt()); - histos.fill(HIST("Xi/hNegDauDecayRadius"), decayDaughters[idx(Cascade::kNeg)].radius(), decayDaughters[idx(Cascade::kNeg)].pt()); - break; - - case PDG_t::kXiPlusBar: - if (!checkDecayChannel(PDG_t::kXiPlusBar, decayDaughters)) { - break; - } - histos.fill(HIST("AntiXi/hGenAntiXi"), particle.pt()); - histos.fill(HIST("AntiXi/hBachDauDecayRadius"), decayDaughters[idx(AntiCascade::kBach)].radius(), decayDaughters[idx(AntiCascade::kBach)].pt()); - histos.fill(HIST("AntiXi/hV0DauDecayRadius"), decayDaughters[idx(AntiCascade::kV0)].radius(), decayDaughters[idx(AntiCascade::kV0)].pt()); - histos.fill(HIST("AntiXi/hPosDauDecayRadius"), decayDaughters[idx(AntiCascade::kPos)].radius(), decayDaughters[idx(AntiCascade::kPos)].pt()); - histos.fill(HIST("AntiXi/hNegDauDecayRadius"), decayDaughters[idx(AntiCascade::kNeg)].radius(), decayDaughters[idx(AntiCascade::kNeg)].pt()); - break; - - case PDG_t::kOmegaMinus: - if (!checkDecayChannel(PDG_t::kOmegaMinus, decayDaughters)) { - break; - } - histos.fill(HIST("Omega/hGenOmega"), particle.pt()); - histos.fill(HIST("Omega/hBachDauDecayRadius"), decayDaughters[idx(Cascade::kBach)].radius(), decayDaughters[idx(Cascade::kBach)].pt()); - histos.fill(HIST("Omega/hV0DauDecayRadius"), decayDaughters[idx(Cascade::kV0)].radius(), decayDaughters[idx(Cascade::kV0)].pt()); - histos.fill(HIST("Omega/hPosDauDecayRadius"), decayDaughters[idx(Cascade::kPos)].radius(), decayDaughters[idx(Cascade::kPos)].pt()); - histos.fill(HIST("Omega/hNegDauDecayRadius"), decayDaughters[idx(Cascade::kNeg)].radius(), decayDaughters[idx(Cascade::kNeg)].pt()); - break; - - case PDG_t::kOmegaPlusBar: - if (!checkDecayChannel(PDG_t::kOmegaPlusBar, decayDaughters)) { - break; - } - histos.fill(HIST("AntiOmega/hGenAntiOmega"), particle.pt()); - histos.fill(HIST("AntiOmega/hBachDauDecayRadius"), decayDaughters[idx(AntiCascade::kBach)].radius(), decayDaughters[idx(AntiCascade::kBach)].pt()); - histos.fill(HIST("AntiOmega/hV0DauDecayRadius"), decayDaughters[idx(AntiCascade::kV0)].radius(), decayDaughters[idx(AntiCascade::kV0)].pt()); - histos.fill(HIST("AntiOmega/hPosDauDecayRadius"), decayDaughters[idx(AntiCascade::kPos)].radius(), decayDaughters[idx(AntiCascade::kPos)].pt()); - histos.fill(HIST("AntiOmega/hNegDauDecayRadius"), decayDaughters[idx(AntiCascade::kNeg)].radius(), decayDaughters[idx(AntiCascade::kNeg)].pt()); - break; - - default: - break; - } - } - - int daughtersIdSlice[2]; - if (canDecay(particle.pdgCode())) { - daughtersIdSlice[0] = idx(mcParticles.size() + nStoredDaughters); - daughtersIdSlice[1] = idx(mcParticles.size() + nStoredDaughters + decayDaughters.size()); - } else { - daughtersIdSlice[0] = idx(particle.daughtersIds()[0]); - daughtersIdSlice[1] = idx(particle.daughtersIds()[1]); + int ndau = 0; + for (int i = start; i < stop; i++) { + o2::upgrade::OTFParticle& particle = allParticles[i]; + if (particle.isFromMcParticles()) { + particle.setIsPrimary(true); + particle.setIsAlive(true); } - mDecayDaughters.emplace(index, decayDaughters); - nStoredDaughters += decayDaughters.size(); - - const float phi = o2::constants::math::PI + std::atan2(-1.0f * particle.py(), -1.0f * particle.px()); - float eta; // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 - const float pt = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py()); - const float p = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py() + particle.pz() * particle.pz()); - float y; // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 - - if ((p - particle.pz()) < Tolerance) { - eta = (particle.pz() < 0.0f) ? -100.0f : 100.0f; - } else { - eta = 0.5f * std::log((p + particle.pz()) / (p - particle.pz())); + if (!canDecay(particle)) { + continue; } - if ((particle.e() - particle.pz()) < Tolerance) { - y = (particle.pz() < 0.0f) ? -100.0f : 100.0f; - } else { - y = 0.5f * std::log((particle.e() + particle.pz()) / (particle.e() - particle.pz())); + particle.setIsAlive(false); + std::vector decayStack = decayer.decayParticle(pdgDB, particle); + particle.setIndicesDaughter(allParticles.size(), allParticles.size() + (decayStack.size() - 1)); + for (o2::upgrade::OTFParticle daughter : decayStack) { + daughter.setIndicesMother(i, i); + daughter.setCollisionId(particle.collisionId()); + daughter.setIsAlive(true); + daughter.setIsPrimary(false); + allParticles.push_back(daughter); + ndau++; } - - // TODO: Particle status code - // TODO: Expression columns - auto mothers = particle.mothersIds(); - int mother0 = mothers.size() > 0 ? mothers[0] : -1; - int mother1 = mothers.size() > 1 ? mothers[1] : mother0; - mcParticlesAlice3.push_back(McParticleAlice3{particle.mcCollisionId(), particle.pdgCode(), particle.statusCode(), - particle.flags(), mother0, mother1, - daughtersIdSlice[0], daughtersIdSlice[1], particle.weight(), - particle.px(), particle.py(), particle.pz(), particle.e(), - particle.vx(), particle.vy(), particle.vz(), particle.vt(), - phi, eta, pt, p, y, !canDecay(particle.pdgCode()), true}); } - int daughtersIdSlice[2] = {-1, -1}; - for (const auto& [index, decayDaughters] : mDecayDaughters) { - for (const auto& dau : decayDaughters) { - if (index >= mcParticles.size()) { - LOG(error) << "--- Index " << index << " out of bounds for mcParticles table of size " << mcParticles.size() << std::endl; - continue; - } - - const float phi = o2::constants::math::PI + std::atan2(-1.0f * dau.py(), -1.0f * dau.px()); - float eta; // Conditional as https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 - const float pt = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py()); - const float p = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py() + dau.pz() * dau.pz()); - float y; // Conditional as https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 - - if ((p - dau.pz()) < Tolerance) { - eta = (dau.pz() < 0.0f) ? -100.0f : 100.0f; - } else { - eta = 0.5f * std::log((p + dau.pz()) / (p - dau.pz())); - } - - if ((dau.e() - dau.pz()) < Tolerance) { - y = (dau.pz() < 0.0f) ? -100.0f : 100.0f; - } else { - y = 0.5f * std::log((dau.e() + dau.pz()) / (dau.e() - dau.pz())); - } - - switch (dau.pdgCode()) { - case PDG_t::kElectron: - histos.fill(HIST("Secondaries/hGenEl"), pt); - break; - - case PDG_t::kMuonMinus: - histos.fill(HIST("Secondaries/hGenMu"), pt); - break; + if (start >= stop) { + return; + } - case PDG_t::kPiPlus: - histos.fill(HIST("Secondaries/hGenPi"), pt); - break; + decayParticles(stop, stop + ndau); + } - case PDG_t::kKPlus: - histos.fill(HIST("Secondaries/hGenKa"), pt); - break; + void process(aod::McCollision const&, aod::McParticles const& mcParticles) + { + allParticles.clear(); - case PDG_t::kProton: - histos.fill(HIST("Secondaries/hGenPr"), pt); - break; + // First we copy the particles from the table into a vector that is extendable + for (int index{0}; index < static_cast(mcParticles.size()); ++index) { + const auto& mcParticle = mcParticles.rawIteratorAt(index); + allParticles.push_back(o2::upgrade::OTFParticle{mcParticle}); + } - default: - break; - } + // Do all decays + decayParticles(0, allParticles.size()); - // TODO: Particle status code - // TODO: Expression columns - // TODO: vt - auto mother = mcParticles.rawIteratorAt(index); - mcParticlesAlice3.push_back(McParticleAlice3{mother.mcCollisionId(), dau.pdgCode(), 1, - -1, index, index, daughtersIdSlice[0], daughtersIdSlice[1], mother.weight(), - dau.px(), dau.py(), dau.pz(), dau.e(), - dau.vx(), dau.vy(), dau.vz(), mother.vt(), - phi, eta, pt, p, y, dau.isAlive(), false}); - } - } + // Fill output table + for (int index{0}; index < static_cast(allParticles.size()); ++index) { + const auto& otfParticle = allParticles[index]; - for (const auto& particle : mcParticlesAlice3) { - if (particle.hasNaN()) { + if (otfParticle.hasNaN()) { histos.fill(HIST("hNaNBookkeeping"), 1); - continue; + } else { + histos.fill(HIST("hNaNBookkeeping"), 0); } - histos.fill(HIST("hNaNBookkeeping"), 0); - std::span motherSpan(particle.mothersIds, 2); - tableMcParticlesWithDau(particle.collisionId, particle.pdgCode, particle.statusCode, - particle.flags, motherSpan, particle.daughtersIdSlice, particle.weight, - particle.px, particle.py, particle.pz, particle.e, - particle.vx, particle.vy, particle.vz, particle.vt, - particle.phi, particle.eta, particle.pt, particle.p, particle.y, - particle.isAlive, particle.isPrimary); + // todo: status codes and vt + tableMcParticlesWithDau(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), + otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), + otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), + otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt(), + otfParticle.phi(), otfParticle.eta(), otfParticle.pt(), otfParticle.p(), otfParticle.y(), + otfParticle.isAlive(), otfParticle.isPrimary()); } } }; From a2f08241a7cfa0e8d61be115dbb2ee163ce8f1b0 Mon Sep 17 00:00:00 2001 From: creetz16 <79141119+creetz16@users.noreply.github.com> Date: Fri, 15 May 2026 18:59:01 +0200 Subject: [PATCH 180/449] [PWGLF] Update MC background flagging in decay3bodybuilder (#16263) --- .../Nuspex/decay3bodybuilder.cxx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index 3b7205ca27c..80dd5703951 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -806,7 +806,7 @@ struct decay3bodyBuilder { if (!doStoreMcBkg) { continue; // if not storing MC background, skip candidates where at least one daughter is not matched to MC particle } else { - this3BodyMCInfo.motherLabel = -5; // at least one non-matched daughter + this3BodyMCInfo.motherLabel = -5; // at least one of the daughters not matched to MC particle // fill analysis table (only McVtx3BodyDatas is filled here) fillAnalysisTables(); } @@ -1200,10 +1200,11 @@ struct decay3bodyBuilder { // global mother ID: proton, pion, and deuteron have common mother and it's a hypertriton // first, check identity of MC daughters - if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron || (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus)) { - return -4; + if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus)) { + return -4; // at least one of the daughters has wrong identity (in this case it's either proton or pion wrong identity) } - // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi + // --> now the proton is a proton and the pion is either a pi+ or a muon + // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi, if not, fill as background auto mcParticlePiTmp = mcParticlePi; if (std::abs(mcParticlePiTmp.pdgCode()) == PDG_t::kMuonMinus) { bool isMuonReco = false; @@ -1216,9 +1217,10 @@ struct decay3bodyBuilder { } // If the track is a muon but none of its mothers is a pi+, treat as wrong identity if (!isMuonReco) { - return -4; + return -4; // at least one of the daughters has wrong identity (in this case it's pion wrong identity) } } + // --> now proton and pion have correct identity // now first check if the proton and pion have the same mother and it is a Lambda for (const auto& motherPr : mcParticlePr.template mothers_as()) { @@ -1228,6 +1230,13 @@ struct decay3bodyBuilder { } } } + // --> now proton and pion have correct identity and are not from a common mother Lambda + + // now check if deuteron has correct identity + if (std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron) { + return -4; // at least one daughter has wrong identity (in this case it's the deuteron) + } + // --> now the deuteron has correct identity // now check if all three daughters have the same mother int momID = -1; From 3d0443adace2893e844ac4b2016cca2ae3e23822 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 15 May 2026 20:06:44 +0200 Subject: [PATCH 181/449] [ALICE3] add more qa to otf decayer (#16265) --- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 6 +- ALICE3/Tasks/alice3DecayerQa.cxx | 180 ++++++++++++++----- 2 files changed, 140 insertions(+), 46 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index c7713d9c45d..1d1a301cd3f 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -85,6 +85,7 @@ struct OnTheFlyDecayer { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + int mCollisionId{-1}; std::vector mEnabledDecays; void init(o2::framework::InitContext&) { @@ -134,7 +135,7 @@ struct OnTheFlyDecayer { particle.setIndicesDaughter(allParticles.size(), allParticles.size() + (decayStack.size() - 1)); for (o2::upgrade::OTFParticle daughter : decayStack) { daughter.setIndicesMother(i, i); - daughter.setCollisionId(particle.collisionId()); + daughter.setCollisionId(mCollisionId); daughter.setIsAlive(true); daughter.setIsPrimary(false); allParticles.push_back(daughter); @@ -149,8 +150,9 @@ struct OnTheFlyDecayer { decayParticles(stop, stop + ndau); } - void process(aod::McCollision const&, aod::McParticles const& mcParticles) + void process(aod::McCollision const& collision, aod::McParticles const& mcParticles) { + mCollisionId = collision.globalIndex(); allParticles.clear(); // First we copy the particles from the table into a vector that is extendable diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index cf1c369d17f..da97cac6989 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -38,6 +38,7 @@ using namespace o2::framework; struct Alice3DecayerQA { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + SliceCache cache; struct : ConfigurableGroup { ConfigurableAxis axisCollisionId{"axisCollisionId", {1000, 0, 999}, "CollisionId axis for QA histograms"}; @@ -54,34 +55,33 @@ struct Alice3DecayerQA { ConfigurableAxis axisIsAlive{"axisIsAlive", {2, 0, 1}, "IsAlive axis for QA histograms"}; ConfigurableAxis axisIsPrimary{"axisIsPrimary", {2, 0, 1}, "IsPrimary axis for QA histograms"}; ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + ConfigurableAxis axisRadiusLog{"axisRadiusLog", {VARIABLE_WIDTH, 0.0f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f, 10.4713f, 10.9648f, 11.4815f, 12.0226f, 12.5893f, 13.1826f, 13.8038f, 14.4544f, 15.1356f, 15.8489f, 16.5959f, 17.378f, 18.197f, 19.0546f, 19.9526f, 20.893f, 21.8776f, 22.9087f, 23.9883f, 25.1189f, 26.3027f, 27.5423f, 28.8403f, 30.1995f, 31.6228f, 33.1131f, 34.6737f, 36.3078f, 38.0189f, 39.8107f, 41.6869f, 43.6516f, 45.7088f, 47.863f, 50.1187f, 52.4807f, 54.9541f, 57.544f, 60.256f, 63.0957f, 66.0693f, 69.1831f, 72.4436f, 75.8578f, 79.4328f, 83.1764f, 87.0964f, 91.2011f, 95.4993f, 100.0f}, "Radial axis"}; + ConfigurableAxis axisPtLog{"axisPtLog", {VARIABLE_WIDTH, 0.0f, 0.001f, 0.00104713f, 0.00109648f, 0.00114815f, 0.00120226f, 0.00125893f, 0.00131826f, 0.00138038f, 0.00144544f, 0.00151356f, 0.00158489f, 0.00165959f, 0.0017378f, 0.0018197f, 0.00190546f, 0.00199526f, 0.0020893f, 0.00218776f, 0.00229087f, 0.00239883f, 0.00251189f, 0.00263027f, 0.00275423f, 0.00288403f, 0.00301995f, 0.00316228f, 0.00331131f, 0.00346737f, 0.00363078f, 0.00380189f, 0.00398107f, 0.00416869f, 0.00436516f, 0.00457088f, 0.0047863f, 0.00501187f, 0.00524807f, 0.00549541f, 0.0057544f, 0.0060256f, 0.00630957f, 0.00660693f, 0.00691831f, 0.00724436f, 0.00758578f, 0.00794328f, 0.00831764f, 0.00870964f, 0.00912011f, 0.00954993f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f}, "pt axis for QA histograms"}; } axes; - Partition trueEl = aod::mcparticle::pdgCode == static_cast(kElectron); - Partition trueMu = aod::mcparticle::pdgCode == static_cast(kMuonMinus); - Partition truePi = aod::mcparticle::pdgCode == static_cast(kPiPlus); - Partition trueKa = aod::mcparticle::pdgCode == static_cast(kKMinus); - Partition truePr = aod::mcparticle::pdgCode == static_cast(kProton); + Partition trueElectrons = aod::mcparticle::pdgCode == static_cast(PDG_t::kElectron); + Partition trueMuons = aod::mcparticle::pdgCode == static_cast(PDG_t::kMuonMinus); + Partition truePions = aod::mcparticle::pdgCode == static_cast(PDG_t::kPiPlus); + Partition trueKaons = aod::mcparticle::pdgCode == static_cast(PDG_t::kKMinus); + Partition trueProtons = aod::mcparticle::pdgCode == static_cast(PDG_t::kProton); + Partition trueK0Short = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); + Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); + Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); - Partition trueElWithDau = aod::mcparticle::pdgCode == static_cast(kElectron); - Partition trueMuWithDau = aod::mcparticle::pdgCode == static_cast(kMuonMinus); - Partition truePiWithDau = aod::mcparticle::pdgCode == static_cast(kPiPlus); - Partition trueKaWithDau = aod::mcparticle::pdgCode == static_cast(kKMinus); - Partition truePrWithDau = aod::mcparticle::pdgCode == static_cast(kProton); + template + float radius(const TParticle& particle) const + { + return std::hypot(particle.vx(), particle.vy()); + } void init(o2::framework::InitContext&) { - histos.add("DefaultMC/hElPt", "hElPt", kTH1D, {axes.axisPt}); - histos.add("DefaultMC/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); - histos.add("DefaultMC/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); - histos.add("DefaultMC/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); - histos.add("DefaultMC/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); - + // QA with Table entries histos.add("MCWithDau/hElPt", "hElPt", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); histos.add("MCWithDau/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); histos.add("MCWithDau/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); @@ -104,44 +104,137 @@ struct Alice3DecayerQA { histos.add("MCWithDau/hPt", "hPt", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hP", "hP", kTH1D, {axes.axisPt}); histos.add("MCWithDau/hE", "hE", kTH1D, {axes.axisPt}); - } - void processMC(const aod::McParticles&) - { - for (const auto& particle : trueEl) { - histos.fill(HIST("DefaultMC/hElPt"), particle.pt()); - } - for (const auto& particle : trueMu) { - histos.fill(HIST("DefaultMC/hMuPt"), particle.pt()); - } - for (const auto& particle : truePi) { - histos.fill(HIST("DefaultMC/hPiPt"), particle.pt()); - } - for (const auto& particle : trueKa) { - histos.fill(HIST("DefaultMC/hKaPt"), particle.pt()); - } - for (const auto& particle : truePr) { - histos.fill(HIST("DefaultMC/hPrPt"), particle.pt()); - } + // QA with daughters from Decayer + histos.add("K0S/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); + histos.add("K0S/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + histos.add("K0S/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("K0S/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("Lambda/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); + histos.add("Lambda/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + histos.add("Lambda/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("Lambda/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); + histos.add("XiMinus/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + histos.add("XiMinus/hBachDauDecayRadius", "hBachDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hV0DauDecayRadius", "hV0DauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); } - void processMCWithDau(const aod::McCollision&, const aod::McPartWithDaus& particles) + void process(const aod::McCollision& collision, const aod::McPartWithDaus& particles) { - for (const auto& particle : trueElWithDau) { + // Group with collision + auto trueElectronsGrouped = trueElectrons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueMuonsGrouped = trueMuons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto truePionsGrouped = truePions->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueKaonsGrouped = trueKaons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueProtonsGrouped = trueProtons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueK0ShortGrouped = trueK0Short->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueLambdasGrouped = trueLambdas->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto trueXiMinusGrouped = trueXiMinus->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + + for (const auto& particle : trueElectronsGrouped) { histos.fill(HIST("MCWithDau/hElPt"), particle.pt()); } - for (const auto& particle : trueMuWithDau) { + for (const auto& particle : trueMuonsGrouped) { histos.fill(HIST("MCWithDau/hMuPt"), particle.pt()); } - for (const auto& particle : truePiWithDau) { + for (const auto& particle : truePionsGrouped) { histos.fill(HIST("MCWithDau/hPiPt"), particle.pt()); } - for (const auto& particle : trueKaWithDau) { + for (const auto& particle : trueKaonsGrouped) { histos.fill(HIST("MCWithDau/hKaPt"), particle.pt()); } - for (const auto& particle : truePrWithDau) { + for (const auto& particle : trueProtonsGrouped) { histos.fill(HIST("MCWithDau/hPrPt"), particle.pt()); } + for (const auto& particle : trueK0ShortGrouped) { + histos.fill(HIST("K0S/hGeneratedPt"), particle.pt()); + if (particle.has_daughters()) { + histos.fill(HIST("K0S/hHasDecayed"), 0); + auto daughters = particle.daughtersIds(); + if (daughters.size() == 2) { + auto dau0 = particles.rawIteratorAt(daughters.front()); + auto dau1 = particles.rawIteratorAt(daughters.back()); + + // K0S -> pi+ pi- + const bool k0sDecay = (dau0.pdgCode() == PDG_t::kPiPlus && dau1.pdgCode() == PDG_t::kPiMinus) || + (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kPiPlus); + if (k0sDecay) { + auto& positive = dau0.pdgCode() == PDG_t::kPiPlus ? dau0 : dau1; + auto& negative = dau0.pdgCode() == PDG_t::kPiPlus ? dau1 : dau0; + histos.fill(HIST("K0S/hPosDauDecayRadius"), radius(positive), positive.pt()); + histos.fill(HIST("K0S/hNegDauDecayRadius"), radius(negative), negative.pt()); + } + } + } else { + histos.fill(HIST("K0S/hHasDecayed"), 1); + } + } + for (const auto& particle : trueLambdasGrouped) { + histos.fill(HIST("Lambda/hGeneratedPt"), particle.pt()); + if (particle.has_daughters()) { + histos.fill(HIST("Lambda/hHasDecayed"), 0); + auto daughters = particle.daughtersIds(); + if (daughters.size() == 2) { + auto dau0 = particles.rawIteratorAt(daughters[0]); + auto dau1 = particles.rawIteratorAt(daughters[1]); + + // Lambda -> p pi- + const bool lambdaDecay = (dau0.pdgCode() == PDG_t::kProton && dau1.pdgCode() == PDG_t::kPiMinus) || + (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kProton); + if (lambdaDecay) { + auto& positive = dau0.pdgCode() == PDG_t::kProton ? dau0 : dau1; + auto& negative = dau0.pdgCode() == PDG_t::kProton ? dau1 : dau0; + histos.fill(HIST("Lambda/hPosDauDecayRadius"), radius(positive), positive.pt()); + histos.fill(HIST("Lambda/hNegDauDecayRadius"), radius(negative), negative.pt()); + } + } + } else { + histos.fill(HIST("Lambda/hHasDecayed"), 1); + } + } + for (const auto& particle : trueXiMinusGrouped) { + histos.fill(HIST("XiMinus/hGeneratedPt"), particle.pt()); + if (particle.has_daughters()) { + histos.fill(HIST("XiMinus/hHasDecayed"), 0); + auto daughters = particle.daughtersIds(); + if (daughters.size() == 2) { + auto dau0 = particles.rawIteratorAt(daughters.front()); + auto dau1 = particles.rawIteratorAt(daughters.back()); + + // Xi- -> Lambda pi- + const bool xiDecay = (dau0.pdgCode() == PDG_t::kLambda0 && dau1.pdgCode() == PDG_t::kPiMinus) || + (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kLambda0); + if (xiDecay) { + auto& v0 = dau0.pdgCode() == PDG_t::kLambda0 ? dau0 : dau1; + auto& bachelor = dau0.pdgCode() == PDG_t::kLambda0 ? dau1 : dau0; + histos.fill(HIST("XiMinus/hBachDauDecayRadius"), radius(bachelor), bachelor.pt()); + histos.fill(HIST("XiMinus/hV0DauDecayRadius"), radius(v0), v0.pt()); + + // Lambda -> p pi- + if (v0.has_daughters()) { + auto v0daughters = v0.daughtersIds(); + if (v0daughters.size() == 2) { + auto v0dau0 = particles.rawIteratorAt(v0daughters.front()); + auto v0dau1 = particles.rawIteratorAt(v0daughters.back()); + const bool lambdaDecay = (v0dau0.pdgCode() == PDG_t::kProton && v0dau1.pdgCode() == PDG_t::kPiMinus) || + (v0dau0.pdgCode() == PDG_t::kPiMinus && v0dau1.pdgCode() == PDG_t::kProton); + if (lambdaDecay) { + auto& positive = v0dau0.pdgCode() == PDG_t::kProton ? v0dau0 : v0dau1; + auto& negative = v0dau0.pdgCode() == PDG_t::kProton ? v0dau1 : v0dau0; + histos.fill(HIST("XiMinus/hPosDauDecayRadius"), radius(positive), positive.pt()); + histos.fill(HIST("XiMinus/hNegDauDecayRadius"), radius(negative), negative.pt()); + } + } + } + } + } + } else { + histos.fill(HIST("XiMinus/hHasDecayed"), 1); + } + } for (const auto& particle : particles) { histos.fill(HIST("MCWithDau/hCollisionId"), particle.mcCollisionId()); @@ -167,14 +260,13 @@ struct Alice3DecayerQA { for (const auto& motherParticleId : particle.mothersIds()) { histos.fill(HIST("MCWithDau/hMothersIds"), motherParticleId); } - for (const auto& dauParticleId : particle.mothersIds()) { + for (const auto& dauParticleId : particle.daughtersIds()) { histos.fill(HIST("MCWithDau/hDaughtersIds"), dauParticleId); } } } - PROCESS_SWITCH(Alice3DecayerQA, processMC, "fill MC-only histograms", false); - PROCESS_SWITCH(Alice3DecayerQA, processMCWithDau, "fill MC-with-dau histograms", true); + PROCESS_SWITCH(Alice3DecayerQA, process, "fill MC-with-dau histograms", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& ctx) From a59af4654d870eecded86903c9460b0bbdeefaed Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Fri, 15 May 2026 21:58:01 +0200 Subject: [PATCH 182/449] [Common] Add EsE q-vectors to q-vector calibration task (#16244) Co-authored-by: ALICE Action Bot --- Common/DataModel/Qvectors.h | 2 +- Common/Tasks/qVectorsCorrection.cxx | 520 +++++++++++++--------------- 2 files changed, 236 insertions(+), 286 deletions(-) diff --git a/Common/DataModel/Qvectors.h b/Common/DataModel/Qvectors.h index f62e8851a2b..e71cb7ed0cb 100644 --- a/Common/DataModel/Qvectors.h +++ b/Common/DataModel/Qvectors.h @@ -201,7 +201,7 @@ DECLARE_SOA_COLUMN(EseRedQFV0A, eseRedQFV0A, float); } // namespace ese_qvec DECLARE_SOA_TABLE(EseQvectors, "AOD", "ESEQVECTORDEVS", //! Table with all Qvectors. - qvec::Cent, ese_qvec::IsCalibrated, ese_qvec::EseQvecRe, ese_qvec::EseQvecIm, ese_qvec::EseQvecAmp); + qvec::Cent, ese_qvec::IsCalibrated, ese_qvec::EseQvecRe, ese_qvec::EseQvecIm, qvec::QvecAmp); using Qvector = Qvectors::iterator; DECLARE_SOA_TABLE(EseQvecFT0Cs, "AOD", "ESEQVECFT0C", ese_qvec::IsCalibrated, ese_qvec::EseQvecFT0CRe, ese_qvec::EseQvecFT0CIm, qvec::SumAmplFT0C); diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx index f54bcfd29f4..b879cdaeb4c 100644 --- a/Common/Tasks/qVectorsCorrection.cxx +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -45,7 +45,8 @@ using namespace o2; using namespace o2::framework; -using MyCollisions = soa::Join; +using MySpCollisions = soa::Join; +using MyEseCollisions = soa::Join; using MyTracks = soa::Join; struct qVectorsCorrection { @@ -101,6 +102,26 @@ struct qVectorsCorrection { int RefAId; int RefBId; + template + float getQVecRe(TColl const& collision, int detId) + { + if constexpr (std::derived_from) { + return collision.eseQvecRe()[detId]; + } else { + return collision.qvecRe()[detId]; + } + } + + template + float getQVecIm(TColl const& collision, int detId) + { + if constexpr (std::derived_from) { + return collision.eseQvecIm()[detId]; + } else { + return collision.qvecIm()[detId]; + } + } + template int GetDetId(const T& name) { @@ -178,9 +199,9 @@ struct qVectorsCorrection { AxisSpec axisBasis = {20, 0, 20, "basis"}; AxisSpec axisVertex = {220, -11, 11, "vertex"}; - histosQA.add("histCentFull", "Centrality distribution for valid events", HistType::kTH1F, {axisCent}); - histosQA.add("histCentSelected", "Centrality distribution for valid events", HistType::kTH1F, {axisCent}); - histosQA.add("histVtxSelected", "Centrality distribution for valid events", HistType::kTH1F, {axisVertex}); + histosQA.add("histCentFull", "Centrality distribution for all events", HistType::kTH1F, {axisCent}); + histosQA.add("histCentSelected", "Centrality distribution for selected events", HistType::kTH1F, {axisCent}); + histosQA.add("histVtxSelected", "Z vtx coordinate distribution for valid events", HistType::kTH1F, {axisVertex}); for (uint i = 0; i < cfgnMods->size(); i++) { histosQA.add(Form("histQvecUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); @@ -270,97 +291,42 @@ struct qVectorsCorrection { return; } + auto aTan2DetInd = TMath::ATan2(getQVecIm(vec, DetInd), getQVecRe(vec, DetInd)); + auto aTan2RefAInd = TMath::ATan2(getQVecIm(vec, RefAInd), getQVecRe(vec, RefAInd)); + auto aTan2RefBInd = TMath::ATan2(getQVecIm(vec, RefBInd), getQVecRe(vec, RefBInd)); + if (nmode == 2) { for (int ishift = 1; ishift <= 10; ishift++) { - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2DetInd)); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2DetInd)); - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefAInd)); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefAInd)); - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefBInd)); + histosQA.fill(HIST("histShiftV2"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefBInd)); } } else if (nmode == 3) { for (int ishift = 1; ishift <= 10; ishift++) { - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2DetInd)); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2DetInd)); - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefAInd)); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefAInd)); - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefBInd)); + histosQA.fill(HIST("histShiftV3"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefBInd)); } } else if (nmode == 4) { for (int ishift = 1; ishift <= 10; ishift++) { - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[DetInd], vec.qvecRe()[DetInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * DetId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2DetInd)); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * DetId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2DetInd)); - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefAInd], vec.qvecRe()[RefAInd]) / static_cast(nmode))); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefAId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefAInd)); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefAId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefAInd)); - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); - histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * static_cast(nmode) * TMath::ATan2(vec.qvecIm()[RefBInd], vec.qvecRe()[RefBInd]) / static_cast(nmode))); - } - } - } - - template - void fillHistosFlowWithSC(const CollType& coll, const TrackType& track, int nmode) - { - int DetInd = DetId + cfgnTotalSystem * (nmode - 2); - int RefAInd = RefAId + cfgnTotalSystem * (nmode - 2); - int RefBInd = RefBId + cfgnTotalSystem * (nmode - 2); - - if (coll.qvecAmp()[DetId] < 1e-8 || coll.qvecAmp()[RefAId] < 1e-8 || coll.qvecAmp()[RefBId] < 1e-8) { - return; - } - - for (auto& trk : track) { - if (!SelTrack(trk)) { - continue; - } - - if (std::abs(trk.eta()) > 0.8) { - continue; - } - if (nmode == 2) { - histosQA.fill(HIST("hist_EP_cos_Det_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefA_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefB_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - } else if (nmode == 3) { - histosQA.fill(HIST("hist_EP_cos_Det_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefA_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefB_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - } else if (nmode == 4) { - histosQA.fill(HIST("hist_EP_cos_Det_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[DetInd], coll.qvecShiftedIm()[DetInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefA_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefAInd], coll.qvecShiftedIm()[RefAInd], nmode)))); - - histosQA.fill(HIST("hist_EP_cos_RefB_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecShiftedRe()[RefBInd], coll.qvecShiftedIm()[RefBInd], nmode)))); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefBId + 0.5, ishift - 0.5, TMath::Sin(ishift * aTan2RefBInd)); + histosQA.fill(HIST("histShiftV4"), vec.cent(), 2.0 * RefBId + 1.5, ishift - 0.5, TMath::Cos(ishift * aTan2RefBInd)); } } } @@ -384,99 +350,53 @@ struct qVectorsCorrection { continue; } + auto trkPhi = trk.phi(); + auto trkPt = trk.pt(); + auto cent = coll.cent(); + auto epDetInd = helperEP.GetEventPlane(getQVecRe(coll, DetInd + 3), getQVecIm(coll, DetInd + 3), nmode); + auto epRefAInd = helperEP.GetEventPlane(getQVecRe(coll, RefAInd + 3), getQVecIm(coll, RefAInd + 3), nmode); + auto epRefBInd = helperEP.GetEventPlane(getQVecRe(coll, RefBInd + 3), getQVecIm(coll, RefBInd + 3), nmode); + if (nmode == 2) { - histosQA.fill(HIST("hist_EP_cos_Det_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_Det_v2"), cent, trkPt, std::cos(2.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_sin_Det_v2"), cent, trkPt, std::sin(2.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v2"), cent, trkPt, TVector2::Phi_0_2pi(2.0 * (trkPhi - epDetInd))); - histosQA.fill(HIST("hist_EP_cos_RefA_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefA_v2"), cent, trkPt, std::cos(2.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_sin_RefA_v2"), cent, trkPt, std::sin(2.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v2"), cent, trkPt, TVector2::Phi_0_2pi(2.0 * (trkPhi - epRefAInd))); - histosQA.fill(HIST("hist_EP_cos_RefB_v2"), coll.cent(), trk.pt(), std::cos(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v2"), coll.cent(), trk.pt(), std::sin(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v2"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(2.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefB_v2"), cent, trkPt, std::cos(2.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_sin_RefB_v2"), cent, trkPt, std::sin(2.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v2"), cent, trkPt, TVector2::Phi_0_2pi(2.0 * (trkPhi - epRefBInd))); } else if (nmode == 3) { - histosQA.fill(HIST("hist_EP_cos_Det_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_Det_v3"), cent, trkPt, std::cos(3.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_sin_Det_v3"), cent, trkPt, std::sin(3.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v3"), cent, trkPt, TVector2::Phi_0_2pi(3.0 * (trkPhi - epDetInd))); - histosQA.fill(HIST("hist_EP_cos_RefA_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefA_v3"), cent, trkPt, std::cos(3.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_sin_RefA_v3"), cent, trkPt, std::sin(3.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v3"), cent, trkPt, TVector2::Phi_0_2pi(3.0 * (trkPhi - epRefAInd))); - histosQA.fill(HIST("hist_EP_cos_RefB_v3"), coll.cent(), trk.pt(), std::cos(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v3"), coll.cent(), trk.pt(), std::sin(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v3"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(3.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefB_v3"), cent, trkPt, std::cos(3.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_sin_RefB_v3"), cent, trkPt, std::sin(3.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v3"), cent, trkPt, TVector2::Phi_0_2pi(3.0 * (trkPhi - epRefBInd))); } else if (nmode == 4) { - histosQA.fill(HIST("hist_EP_cos_Det_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_Det_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_Det_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[DetInd + 3], coll.qvecIm()[DetInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_Det_v4"), cent, trkPt, std::cos(4.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_sin_Det_v4"), cent, trkPt, std::sin(4.0 * (trkPhi - epDetInd))); + histosQA.fill(HIST("hist_EP_azimuth_Det_v4"), cent, trkPt, TVector2::Phi_0_2pi(4.0 * (trkPhi - epDetInd))); - histosQA.fill(HIST("hist_EP_cos_RefA_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefA_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefA_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefAInd + 3], coll.qvecIm()[RefAInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefA_v4"), cent, trkPt, std::cos(4.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_sin_RefA_v4"), cent, trkPt, std::sin(4.0 * (trkPhi - epRefAInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefA_v4"), cent, trkPt, TVector2::Phi_0_2pi(4.0 * (trkPhi - epRefAInd))); - histosQA.fill(HIST("hist_EP_cos_RefB_v4"), coll.cent(), trk.pt(), std::cos(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_sin_RefB_v4"), coll.cent(), trk.pt(), std::sin(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); - histosQA.fill(HIST("hist_EP_azimuth_RefB_v4"), coll.cent(), trk.pt(), TVector2::Phi_0_2pi(4.0 * (trk.phi() - helperEP.GetEventPlane(coll.qvecRe()[RefBInd + 3], coll.qvecIm()[RefBInd + 3], nmode)))); + histosQA.fill(HIST("hist_EP_cos_RefB_v4"), cent, trkPt, std::cos(4.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_sin_RefB_v4"), cent, trkPt, std::sin(4.0 * (trkPhi - epRefBInd))); + histosQA.fill(HIST("hist_EP_azimuth_RefB_v4"), cent, trkPt, TVector2::Phi_0_2pi(4.0 * (trkPhi - epRefBInd))); } } } - template - void fillHistosQvecWithSC(const T& vec, int nmode) - { - int DetInd = DetId + cfgnTotalSystem * (nmode - 2); - int RefAInd = RefAId + cfgnTotalSystem * (nmode - 2); - int RefBInd = RefBId + cfgnTotalSystem * (nmode - 2); - - if (vec.qvecAmp()[DetId] < 1e-8 || vec.qvecAmp()[RefAId] < 1e-8 || vec.qvecAmp()[RefBId] < 1e-8) { - return; - } - - if (nmode == 2) { - histosQA.fill(HIST("histQvecFinalV2"), vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefAFinalV2"), vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV2"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefBFinalV2"), vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV2"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), vec.cent()); - - histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - } else if (nmode == 3) { - histosQA.fill(HIST("histQvecFinalV3"), vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefAFinalV3"), vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV3"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefBFinalV3"), vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV3"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), vec.cent()); - - histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - } else if (nmode == 4) { - histosQA.fill(HIST("histQvecFinalV4"), vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV4"), helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefAFinalV4"), vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV4"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), vec.cent()); - - histosQA.fill(HIST("histQvecRefBFinalV4"), vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV4"), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), vec.cent()); - - histosQA.fill(HIST("histEvtPlRes_SigRefAV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[DetInd], vec.qvecShiftedIm()[DetInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecShiftedRe()[RefAInd], vec.qvecShiftedIm()[RefAInd], nmode), helperEP.GetEventPlane(vec.qvecShiftedRe()[RefBInd], vec.qvecShiftedIm()[RefBInd], nmode), nmode), vec.cent()); - } - } - // Definition of all the needed template functions. template void fillHistosQvec(const T& vec, int nmode) @@ -484,275 +404,305 @@ struct qVectorsCorrection { int DetInd = DetId * 4 + cfgnTotalSystem * 4 * (nmode - 2); int RefAInd = RefAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); int RefBInd = RefBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + auto epDetInd = helperEP.GetEventPlane(getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), nmode); + auto epDetIndRectr = helperEP.GetEventPlane(getQVecRe(vec, DetInd + 1), getQVecIm(vec, DetInd + 1), nmode); + auto epDetIndTwist = helperEP.GetEventPlane(getQVecRe(vec, DetInd + 2), getQVecIm(vec, DetInd + 2), nmode); + auto epDetIndFinal = helperEP.GetEventPlane(getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), nmode); + auto epRefAInd = helperEP.GetEventPlane(getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), nmode); + auto epRefARectrInd = helperEP.GetEventPlane(getQVecRe(vec, RefAInd + 1), getQVecIm(vec, RefAInd + 1), nmode); + auto epRefATwistInd = helperEP.GetEventPlane(getQVecRe(vec, RefAInd + 2), getQVecIm(vec, RefAInd + 2), nmode); + auto epRefAFinalInd = helperEP.GetEventPlane(getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), nmode); + auto epRefBInd = helperEP.GetEventPlane(getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), nmode); + auto epRefBRectrInd = helperEP.GetEventPlane(getQVecRe(vec, RefBInd + 1), getQVecIm(vec, RefBInd + 1), nmode); + auto epRefBTwistInd = helperEP.GetEventPlane(getQVecRe(vec, RefBInd + 2), getQVecIm(vec, RefBInd + 2), nmode); + auto epRefBFinalInd = helperEP.GetEventPlane(getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), nmode); + + auto occ = vec.trackOccupancyInTimeRange(); + auto cent = vec.cent(); + if (nmode == 2) { if (vec.qvecAmp()[DetId] > 1e-8) { - histosQA.fill(HIST("histQvecUncorV2"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecUncorV2"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent); + histosQA.fill(HIST("histEvtPlUncorV2"), epDetInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccUncorV2"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccUncorV2"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecFinalV2"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecFinalV2"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent); + histosQA.fill(HIST("histEvtPlFinalV2"), epDetIndFinal, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccFinalV2"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccFinalV2"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRectrV2"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecTwistV2"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRectrV2"), getQVecRe(vec, DetInd + 1), getQVecIm(vec, DetInd + 1), cent); + histosQA.fill(HIST("histQvecTwistV2"), getQVecRe(vec, DetInd + 2), getQVecIm(vec, DetInd + 2), cent); - histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRectrV2"), epDetIndRectr, cent); + histosQA.fill(HIST("histEvtPlTwistV2"), epDetIndTwist, cent); } } } if (vec.qvecAmp()[RefAId] > 1e-8) { - histosQA.fill(HIST("histQvecRefAUncorV2"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAUncorV2"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent); + histosQA.fill(HIST("histEvtPlRefAUncorV2"), epRefAInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccUncorV2"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccUncorV2"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefAFinalV2"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAFinalV2"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefAFinalV2"), epRefAFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccFinalV2"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccFinalV2"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefARectrV2"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefATwistV2"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefARectrV2"), getQVecRe(vec, RefAInd + 1), getQVecIm(vec, RefAInd + 1), cent); + histosQA.fill(HIST("histQvecRefATwistV2"), getQVecRe(vec, RefAInd + 2), getQVecIm(vec, RefAInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefARectrV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefATwistV2"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefARectrV2"), epRefARectrInd, cent); + histosQA.fill(HIST("histEvtPlRefATwistV2"), epRefATwistInd, cent); } } } if (vec.qvecAmp()[RefBId] > 1e-8) { - histosQA.fill(HIST("histQvecRefBUncorV2"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBUncorV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBUncorV2"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent); + histosQA.fill(HIST("histEvtPlRefBUncorV2"), epRefBInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccUncorV2"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccUncorV2"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefBFinalV2"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBFinalV2"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefBFinalV2"), epRefBFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccFinalV2"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccFinalV2"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefBRectrV2"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefBTwistV2"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefBRectrV2"), getQVecRe(vec, RefBInd + 1), getQVecIm(vec, RefBInd + 1), cent); + histosQA.fill(HIST("histQvecRefBTwistV2"), getQVecRe(vec, RefBInd + 2), getQVecIm(vec, RefBInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefBRectrV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBTwistV2"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBRectrV2"), epRefBRectrInd, cent); + histosQA.fill(HIST("histEvtPlRefBTwistV2"), epRefBTwistInd, cent); } } } if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { - histosQA.fill(HIST("histQvecRes_SigRefAV2"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_SigRefBV2"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_RefARefBV2"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefAV2"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefAInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histQvecRes_SigRefBV2"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histQvecRes_RefARefBV2"), getQVecRe(vec, RefAInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, RefAInd + 3) * getQVecIm(vec, RefBInd + 3), cent); - histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(epDetIndFinal, epRefAFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(epDetIndFinal, epRefBFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(epRefAFinalInd, epRefBFinalInd, nmode), cent); } } else if (nmode == 3) { if (vec.qvecAmp()[DetId] > 1e-8) { - histosQA.fill(HIST("histQvecUncorV3"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecUncorV3"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent); + histosQA.fill(HIST("histEvtPlUncorV3"), epDetInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccUncorV3"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccUncorV3"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent, occ); } if (cfgQAFinal) { if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccFinalV3"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccFinalV3"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent, occ); } - histosQA.fill(HIST("histQvecFinalV3"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecFinalV3"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent); + histosQA.fill(HIST("histEvtPlFinalV3"), epDetIndFinal, cent); if (cfgQAAll) { - histosQA.fill(HIST("histQvecRectrV3"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecTwistV3"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRectrV3"), getQVecRe(vec, DetInd + 1), getQVecIm(vec, DetInd + 1), cent); + histosQA.fill(HIST("histQvecTwistV3"), getQVecRe(vec, DetInd + 2), getQVecIm(vec, DetInd + 2), cent); - histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRectrV3"), epDetIndRectr, cent); + histosQA.fill(HIST("histEvtPlTwistV3"), epDetIndTwist, cent); } } } if (vec.qvecAmp()[RefAId] > 1e-8) { - histosQA.fill(HIST("histQvecRefAUncorV3"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAUncorV3"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent); + histosQA.fill(HIST("histEvtPlRefAUncorV3"), epRefAInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccUncorV3"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccUncorV3"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefAFinalV3"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAFinalV3"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefAFinalV3"), epRefAFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccFinalV3"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccFinalV3"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefARectrV3"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefATwistV3"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefARectrV3"), getQVecRe(vec, RefAInd + 1), getQVecIm(vec, RefAInd + 1), cent); + histosQA.fill(HIST("histQvecRefATwistV3"), getQVecRe(vec, RefAInd + 2), getQVecIm(vec, RefAInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefARectrV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefATwistV3"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefARectrV3"), epRefARectrInd, cent); + histosQA.fill(HIST("histEvtPlRefATwistV3"), epRefATwistInd, cent); } } } if (vec.qvecAmp()[RefBId] > 1e-8) { - histosQA.fill(HIST("histQvecRefBUncorV3"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBUncorV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBUncorV3"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent); + histosQA.fill(HIST("histEvtPlRefBUncorV3"), epRefBInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccUncorV3"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccUncorV3"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefBFinalV3"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBFinalV3"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefBFinalV3"), epRefBFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccFinalV3"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccFinalV3"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefBRectrV3"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefBTwistV3"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefBRectrV3"), getQVecRe(vec, RefBInd + 1), getQVecIm(vec, RefBInd + 1), cent); + histosQA.fill(HIST("histQvecRefBTwistV3"), getQVecRe(vec, RefBInd + 2), getQVecIm(vec, RefBInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefBRectrV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBTwistV3"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBRectrV3"), epRefBRectrInd, cent); + histosQA.fill(HIST("histEvtPlRefBTwistV3"), epRefBTwistInd, cent); } } } if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { - histosQA.fill(HIST("histQvecRes_SigRefAV3"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_SigRefBV3"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_RefARefBV3"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefAV3"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefAInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histQvecRes_SigRefBV3"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histQvecRes_RefARefBV3"), getQVecRe(vec, RefAInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, RefAInd + 3) * getQVecIm(vec, RefBInd + 3), cent); - histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(epDetIndFinal, epRefAFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(epDetIndFinal, epRefBFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(epRefAFinalInd, epRefBFinalInd, nmode), cent); } } else if (nmode == 4) { if (vec.qvecAmp()[DetId] > 1e-8) { - histosQA.fill(HIST("histQvecUncorV4"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent()); - histosQA.fill(HIST("histEvtPlUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecUncorV4"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent); + histosQA.fill(HIST("histEvtPlUncorV4"), epDetInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccUncorV4"), vec.qvecRe()[DetInd], vec.qvecIm()[DetInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccUncorV4"), getQVecRe(vec, DetInd), getQVecIm(vec, DetInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecFinalV4"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecFinalV4"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent); + histosQA.fill(HIST("histEvtPlFinalV4"), epDetIndFinal, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecOccFinalV4"), vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecOccFinalV4"), getQVecRe(vec, DetInd + 3), getQVecIm(vec, DetInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRectrV4"), vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecTwistV4"), vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRectrV4"), getQVecRe(vec, DetInd + 1), getQVecIm(vec, DetInd + 1), cent); + histosQA.fill(HIST("histQvecTwistV4"), getQVecRe(vec, DetInd + 2), getQVecIm(vec, DetInd + 2), cent); - histosQA.fill(HIST("histEvtPlRectrV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 1], vec.qvecIm()[DetInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlTwistV4"), helperEP.GetEventPlane(vec.qvecRe()[DetInd + 2], vec.qvecIm()[DetInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRectrV4"), epDetIndRectr, cent); + histosQA.fill(HIST("histEvtPlTwistV4"), epDetIndTwist, cent); } } } if (vec.qvecAmp()[RefAId] > 1e-8) { - histosQA.fill(HIST("histQvecRefAUncorV4"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAUncorV4"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent); + histosQA.fill(HIST("histEvtPlRefAUncorV4"), epRefAInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccUncorV4"), vec.qvecRe()[RefAInd], vec.qvecIm()[RefAInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccUncorV4"), getQVecRe(vec, RefAInd), getQVecIm(vec, RefAInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefAFinalV4"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefAFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefAFinalV4"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefAFinalV4"), epRefAFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefAOccFinalV4"), vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefAOccFinalV4"), getQVecRe(vec, RefAInd + 3), getQVecIm(vec, RefAInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefARectrV4"), vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefATwistV4"), vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefARectrV4"), getQVecRe(vec, RefAInd + 1), getQVecIm(vec, RefAInd + 1), cent); + histosQA.fill(HIST("histQvecRefATwistV4"), getQVecRe(vec, RefAInd + 2), getQVecIm(vec, RefAInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefARectrV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 1], vec.qvecIm()[RefAInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefATwistV4"), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 2], vec.qvecIm()[RefAInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefARectrV4"), epRefARectrInd, cent); + histosQA.fill(HIST("histEvtPlRefATwistV4"), epRefATwistInd, cent); } } } if (vec.qvecAmp()[RefBId] > 1e-8) { - histosQA.fill(HIST("histQvecRefBUncorV4"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBUncorV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBUncorV4"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent); + histosQA.fill(HIST("histEvtPlRefBUncorV4"), epRefBInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccUncorV4"), vec.qvecRe()[RefBInd], vec.qvecIm()[RefBInd], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccUncorV4"), getQVecRe(vec, RefBInd), getQVecIm(vec, RefBInd), cent, occ); } if (cfgQAFinal) { - histosQA.fill(HIST("histQvecRefBFinalV4"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histEvtPlRefBFinalV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), vec.cent()); + histosQA.fill(HIST("histQvecRefBFinalV4"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histEvtPlRefBFinalV4"), epRefBFinalInd, cent); if (cfgQAOccupancyStudy) { - histosQA.fill(HIST("histQvecRefBOccFinalV4"), vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], vec.cent(), vec.trackOccupancyInTimeRange()); + histosQA.fill(HIST("histQvecRefBOccFinalV4"), getQVecRe(vec, RefBInd + 3), getQVecIm(vec, RefBInd + 3), cent, occ); } if (cfgQAAll) { - histosQA.fill(HIST("histQvecRefBRectrV4"), vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], vec.cent()); - histosQA.fill(HIST("histQvecRefBTwistV4"), vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], vec.cent()); + histosQA.fill(HIST("histQvecRefBRectrV4"), getQVecRe(vec, RefBInd + 1), getQVecIm(vec, RefBInd + 1), cent); + histosQA.fill(HIST("histQvecRefBTwistV4"), getQVecRe(vec, RefBInd + 2), getQVecIm(vec, RefBInd + 2), cent); - histosQA.fill(HIST("histEvtPlRefBRectrV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 1], vec.qvecIm()[RefBInd + 1], nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRefBTwistV4"), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 2], vec.qvecIm()[RefBInd + 2], nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRefBRectrV4"), epRefBRectrInd, cent); + histosQA.fill(HIST("histEvtPlRefBTwistV4"), epRefBTwistInd, cent); } } } if (vec.qvecAmp()[DetId] > 1e-8 && vec.qvecAmp()[RefAId] > 1e-8 && vec.qvecAmp()[RefBId] > 1e-8 && cfgQAFinal) { - histosQA.fill(HIST("histQvecRes_SigRefAV4"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefAInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefAInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_SigRefBV4"), vec.qvecRe()[DetInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[DetInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); - histosQA.fill(HIST("histQvecRes_RefARefBV4"), vec.qvecRe()[RefAInd + 3] * vec.qvecRe()[RefBInd + 3] + vec.qvecIm()[RefAInd + 3] * vec.qvecIm()[RefBInd + 3], vec.cent()); + histosQA.fill(HIST("histQvecRes_SigRefAV4"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefAInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefAInd + 3), cent); + histosQA.fill(HIST("histQvecRes_SigRefBV4"), getQVecRe(vec, DetInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, DetInd + 3) * getQVecIm(vec, RefBInd + 3), cent); + histosQA.fill(HIST("histQvecRes_RefARefBV4"), getQVecRe(vec, RefAInd + 3) * getQVecRe(vec, RefBInd + 3) + getQVecIm(vec, RefAInd + 3) * getQVecIm(vec, RefBInd + 3), cent); - histosQA.fill(HIST("histEvtPlRes_SigRefAV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[DetInd + 3], vec.qvecIm()[DetInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV4"), helperEP.GetResolution(helperEP.GetEventPlane(vec.qvecRe()[RefAInd + 3], vec.qvecIm()[RefAInd + 3], nmode), helperEP.GetEventPlane(vec.qvecRe()[RefBInd + 3], vec.qvecIm()[RefBInd + 3], nmode), nmode), vec.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefAV4"), helperEP.GetResolution(epDetIndFinal, epRefAFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_SigRefBV4"), helperEP.GetResolution(epDetIndFinal, epRefBFinalInd, nmode), cent); + histosQA.fill(HIST("histEvtPlRes_RefARefBV4"), helperEP.GetResolution(epRefAFinalInd, epRefBFinalInd, nmode), cent); } } } - void processDefault(MyCollisions::iterator const& qVec, MyTracks const& tracks) + + template + void processColls(TCollision const& flowQVec, MyTracks const& tracks) { - histosQA.fill(HIST("histCentFull"), qVec.cent()); + histosQA.fill(HIST("histCentFull"), flowQVec.cent()); if (cfgAddEvtSel) { - if (std::abs(qVec.posZ()) > 10.) + if (std::abs(flowQVec.posZ()) > 10.) return; switch (cfgEvtSel) { case 0: // Sel8 - if (!qVec.sel8()) + if (!flowQVec.sel8()) return; break; case 1: // PbPb standard - if (!qVec.sel8() || !qVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) + if (!flowQVec.sel8() || !flowQVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !flowQVec.selection_bit(aod::evsel::kNoSameBunchPileup)) return; break; case 2: // PbPb with pileup - if (!qVec.sel8() || !qVec.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !qVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) + if (!flowQVec.sel8() || !flowQVec.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || + !flowQVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !flowQVec.selection_bit(aod::evsel::kNoSameBunchPileup)) return; break; case 3: // Small systems (OO, NeNe, pp) - if (!qVec.sel8() || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) + if (!flowQVec.sel8() || !flowQVec.selection_bit(aod::evsel::kNoSameBunchPileup)) return; break; default: LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); } // Check occupancy - if (qVec.trackOccupancyInTimeRange() > cfgMaxOccupancy || qVec.trackOccupancyInTimeRange() < cfgMinOccupancy) + if (flowQVec.trackOccupancyInTimeRange() > cfgMaxOccupancy || flowQVec.trackOccupancyInTimeRange() < cfgMinOccupancy) return; } - histosQA.fill(HIST("histCentSelected"), qVec.cent()); - histosQA.fill(HIST("histVtxSelected"), qVec.posZ()); + histosQA.fill(HIST("histCentSelected"), flowQVec.cent()); + histosQA.fill(HIST("histVtxSelected"), flowQVec.posZ()); if (cfgShiftCorPrep) { for (uint i = 0; i < cfgnMods->size(); i++) { - fillHistosShiftCor(qVec, cfgnMods->at(i)); + fillHistosShiftCor(flowQVec, cfgnMods->at(i)); } } - for (uint i = 0; i < cfgnMods->size(); i++) { - fillHistosQvec(qVec, cfgnMods->at(i)); + fillHistosQvec(flowQVec, cfgnMods->at(i)); if (cfgQAFinal && cfgQAFlowStudy) { - fillHistosFlow(qVec, tracks, cfgnMods->at(i)); + fillHistosFlow(flowQVec, tracks, cfgnMods->at(i)); } } } - PROCESS_SWITCH(qVectorsCorrection, processDefault, "default process", true); + + void processSp(MySpCollisions::iterator const& spQVec, MyTracks const& tracks) + { + processColls(spQVec, tracks); + } + PROCESS_SWITCH(qVectorsCorrection, processSp, "process SP", true); + + void processEse(MyEseCollisions::iterator const& eseQVec, MyTracks const& tracks) + { + processColls(eseQVec, tracks); + } + + PROCESS_SWITCH(qVectorsCorrection, processEse, "process Ese", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 543f37145435fb442dcae3f9360782cac82bc7e9 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Fri, 15 May 2026 22:23:48 +0200 Subject: [PATCH 183/449] [Common] fix linter warnings, add further QA (#16264) Co-authored-by: ALICE Builder --- Common/Tasks/centralityStudypp.cxx | 129 +++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 24 deletions(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index 839c34accfb..cb37808c8d4 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -14,11 +14,9 @@ // multCentTable output #include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" #include -#include #include #include #include @@ -34,7 +32,6 @@ #include #include -#include #include #include #include @@ -53,19 +50,28 @@ struct centralityStudypp { std::map histPointers; std::string histPath; Service ccdb; - int mRunNumber; - uint64_t startOfRunTimestamp; + int mRunNumber = -1; // vertex Z equalization - TList* hCalibObjects; - TProfile* hVtxZFV0A; - TProfile* hVtxZFT0A; - TProfile* hVtxZFT0C; - TProfile* hVtxZNTracks; - TProfile* hVtxZNGlobals; - TProfile* hVtxZMFT; - TProfile* hVtxZFDDA; - TProfile* hVtxZFDDC; + TList* hCalibObjects = nullptr; + TProfile* hVtxZFV0A = nullptr; + TProfile* hVtxZFT0A = nullptr; + TProfile* hVtxZFT0C = nullptr; + TProfile* hVtxZNTracks = nullptr; + TProfile* hVtxZNGlobals = nullptr; + TProfile* hVtxZMFT = nullptr; + TProfile* hVtxZFDDA = nullptr; + TProfile* hVtxZFDDC = nullptr; + + // calibration histograms + TH1* hCentralityFV0A = nullptr; + TH1* hCentralityFT0A = nullptr; + TH1* hCentralityFT0C = nullptr; + TH1* hCentralityFT0M = nullptr; + TH1* hCentralityFDDM = nullptr; + TH1* hCentralityNTPV = nullptr; + TH1* hCentralityNGlo = nullptr; + TH1* hCentralityMFT = nullptr; // Configurables Configurable do2DPlots{"do2DPlots", true, "0 - no, 1 - yes"}; @@ -73,6 +79,7 @@ struct centralityStudypp { // event selection criteria Configurable applyVertexZEqualization{"applyVertexZEqualization", false, "0 - no, 1 - yes"}; Configurable saveUnequalized{"saveUnequalized", false, "save unequalized raw: 0 - no, 1 - yes"}; + Configurable doCentralityQA{"doCentralityQA", false, "do centrality QA: 0 - no, 1 - yes"}; Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; Configurable requireINELgtZERO{"requireINELgtZERO", true, "0 no, 1 - yes"}; @@ -84,6 +91,8 @@ struct centralityStudypp { Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD"}; Configurable rejectSameBunchPileup{"rejectSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable vertexZcut{"vertexZcut", 10.0f, "vertex Z cut (cm)"}; + // For one-dimensional plots, where binning is no issue ConfigurableAxis axisMultUltraFineFV0A{"axisMultUltraFineFV0A", {60000, 0, 60000}, "FV0A amplitude"}; ConfigurableAxis axisMultUltraFineFT0A{"axisMultUltraFineFT0A", {60000, 0, 60000}, "FT0A amplitude"}; @@ -97,11 +106,14 @@ struct centralityStudypp { // For profile Z ConfigurableAxis axisPVz{"axisPVz", {400, -20.0f, +20.0f}, "PVz (cm)"}; ConfigurableAxis axisZN{"axisZN", {1100, -50.0f, +500.0f}, "ZN"}; + // For centrality QA + ConfigurableAxis axisCentrality{"axisCentrality", {10000, 0, 100}, "centrality percentile"}; // ccdb matters Configurable ccdbURL{"ccdbURL", "http://alice-ccdb.cern.ch", "ccdb url"}; Configurable pathGRPECSObject{"pathGRPECSObject", "GLO/Config/GRPECS", "Path to GRPECS object"}; Configurable pathVertexZ{"pathVertexZ", "Users/d/ddobrigk/Centrality/Calibration", "Path to vertexZ profiles"}; + Configurable pathCentrality{"pathCentrality", "Users/d/ddobrigk/Centrality/Estimators", "Path to centrality calibration"}; void init(InitContext&) { @@ -115,6 +127,15 @@ struct centralityStudypp { hVtxZFDDA = nullptr; hVtxZFDDC = nullptr; + hCentralityFV0A = nullptr; + hCentralityFT0A = nullptr; + hCentralityFT0C = nullptr; + hCentralityFT0M = nullptr; + hCentralityFDDM = nullptr; + hCentralityNTPV = nullptr; + hCentralityNGlo = nullptr; + hCentralityMFT = nullptr; + const AxisSpec axisCollisions{100, -0.5f, 99.5f, "Number of collisions"}; histos.add("hCollisionSelection", "hCollisionSelection", kTH1D, {{20, -0.5f, +19.5f}}); histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); @@ -171,14 +192,14 @@ struct centralityStudypp { LOGF(info, "Acquiring vertex-Z profiles for run %i", mRunNumber); hCalibObjects = ccdb->getForRun(pathVertexZ, mRunNumber); - hVtxZFV0A = static_cast(hCalibObjects->FindObject("hVtxZFV0A")); - hVtxZFT0A = static_cast(hCalibObjects->FindObject("hVtxZFT0A")); - hVtxZFT0C = static_cast(hCalibObjects->FindObject("hVtxZFT0C")); - hVtxZFDDA = static_cast(hCalibObjects->FindObject("hVtxZFDDA")); - hVtxZFDDC = static_cast(hCalibObjects->FindObject("hVtxZFDDC")); - hVtxZNTracks = static_cast(hCalibObjects->FindObject("hVtxZNTracksPV")); - hVtxZNGlobals = static_cast(hCalibObjects->FindObject("hVtxZNGlobals")); - hVtxZMFT = static_cast(hCalibObjects->FindObject("hVtxZMFT")); + hVtxZFV0A = dynamic_cast(hCalibObjects->FindObject("hVtxZFV0A")); + hVtxZFT0A = dynamic_cast(hCalibObjects->FindObject("hVtxZFT0A")); + hVtxZFT0C = dynamic_cast(hCalibObjects->FindObject("hVtxZFT0C")); + hVtxZFDDA = dynamic_cast(hCalibObjects->FindObject("hVtxZFDDA")); + hVtxZFDDC = dynamic_cast(hCalibObjects->FindObject("hVtxZFDDC")); + hVtxZNTracks = dynamic_cast(hCalibObjects->FindObject("hVtxZNTracksPV")); + hVtxZNGlobals = dynamic_cast(hCalibObjects->FindObject("hVtxZNGlobals")); + hVtxZMFT = dynamic_cast(hCalibObjects->FindObject("hVtxZMFT")); // Capture error if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZFDDA || !hVtxZFDDC || !hVtxZNTracks || !hVtxZNGlobals || !hVtxZMFT) { @@ -186,6 +207,24 @@ struct centralityStudypp { } } + if (doCentralityQA.value) { + // acquire vertex-Z equalization histograms if requested + LOGF(info, "Acquiring vertex-Z profiles for run %i", mRunNumber); + TList* hCentralityObjects = nullptr; + hCentralityObjects = ccdb->getForRun(pathCentrality, mRunNumber); + + hCentralityFV0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFV0")); + hCentralityFT0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0A")); + hCentralityFT0C = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0C")); + hCentralityFT0M = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0")); + hCentralityFDDM = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFDD")); + hCentralityNTPV = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNTracksPV")); + hCentralityNGlo = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNGlobal")); + hCentralityMFT = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqMFT")); + + // won't capture null pointers -> explicitly check for those when attempting to evaluate + } + histPath = std::format("Run_{}/", mRunNumber); histPointers.insert({histPath + "hCollisionSelection", histos.add((histPath + "hCollisionSelection").c_str(), "hCollisionSelection", {kTH1D, {{20, -0.5f, +19.5f}}})}); @@ -227,6 +266,17 @@ struct centralityStudypp { histPointers.insert({histPath + "hNPVContributors_Unequalized", histos.add((histPath + "hNPVContributors_Unequalized").c_str(), "hNPVContributors_Unequalized", {kTH1D, {{axisMultUltraFinePVContributors}}})}); } + if (doCentralityQA.value) { + histPointers.insert({histPath + "hCentralityDistributionFV0A", histos.add((histPath + "hCentralityDistributionFV0A").c_str(), "hCentralityDistributionFV0A", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionFT0A", histos.add((histPath + "hCentralityDistributionFT0A").c_str(), "hCentralityDistributionFT0A", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionFT0C", histos.add((histPath + "hCentralityDistributionFT0C").c_str(), "hCentralityDistributionFT0C", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionFT0M", histos.add((histPath + "hCentralityDistributionFT0M").c_str(), "hCentralityDistributionFT0M", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionFDDM", histos.add((histPath + "hCentralityDistributionFDDM").c_str(), "hCentralityDistributionFDDM", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionNPTV", histos.add((histPath + "hCentralityDistributionNPTV").c_str(), "hCentralityDistributionNPTV", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionNGlobal", histos.add((histPath + "hCentralityDistributionNGlobal").c_str(), "hCentralityDistributionNGlobal", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionMFT", histos.add((histPath + "hCentralityDistributionMFT").c_str(), "hCentralityDistributionMFT", {kTH1D, {{axisCentrality}}})}); + } + histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFT0CvsPVz_Collisions", histos.add((histPath + "hFT0CvsPVz_Collisions").c_str(), "hFT0CvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); histPointers.insert({histPath + "hFDDAvsPVz_Collisions", histos.add((histPath + "hFDDAvsPVz_Collisions").c_str(), "hFDDAvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); @@ -245,8 +295,9 @@ struct centralityStudypp { histos.fill(HIST("hCollisionSelection"), 0); // all collisions getHist(TH1, histPath + "hCollisionSelection")->Fill(0); - if (applySel8 && !collision.multSel8()) + if (applySel8 && !collision.multSel8()) { return; + } histos.fill(HIST("hCollisionSelection"), 1); getHist(TH1, histPath + "hCollisionSelection")->Fill(1); @@ -331,8 +382,9 @@ struct centralityStudypp { // _______________________________________________________ - if (applyVtxZ && TMath::Abs(collision.multPVz()) > 10) + if (applyVtxZ && TMath::Abs(collision.multPVz()) > vertexZcut.value) { return; + } histos.fill(HIST("hCollisionSelection"), 2); getHist(TH1, histPath + "hCollisionSelection")->Fill(2); @@ -418,6 +470,35 @@ struct centralityStudypp { getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); } + + if (doCentralityQA.value) { + // generate centralities on the spot in case the centrality histograms are in memory + if (hCentralityFV0A) { + getHist(TH1, histPath + "hCentralityDistributionFV0A")->Fill(hCentralityFV0A->GetBinContent(hCentralityFV0A->FindBin(multFV0A))); + } + if (hCentralityFT0A) { + getHist(TH1, histPath + "hCentralityDistributionFT0A")->Fill(hCentralityFT0A->GetBinContent(hCentralityFT0A->FindBin(multFT0A))); + } + if (hCentralityFT0C) { + getHist(TH1, histPath + "hCentralityDistributionFT0C")->Fill(hCentralityFT0C->GetBinContent(hCentralityFT0C->FindBin(multFT0C))); + } + if (hCentralityFT0M) { + getHist(TH1, histPath + "hCentralityDistributionFT0M")->Fill(hCentralityFT0M->GetBinContent(hCentralityFT0M->FindBin(multFT0A + multFT0C))); + } + if (hCentralityFDDM) { + getHist(TH1, histPath + "hCentralityDistributionFDDM")->Fill(hCentralityFDDM->GetBinContent(hCentralityFDDM->FindBin(multFDDA + multFDDC))); + } + if (hCentralityNTPV) { + // note: not vertex-Z-equalized to match what is done in central framework for this estimator + getHist(TH1, histPath + "hCentralityDistributionNTPV")->Fill(hCentralityNTPV->GetBinContent(hCentralityNTPV->FindBin(collision.multNTracksPV()))); + } + if (hCentralityNGlo) { + getHist(TH1, histPath + "hCentralityDistributionNGlobal")->Fill(hCentralityNGlo->GetBinContent(hCentralityNGlo->FindBin(multNTracksGlobal))); + } + if (hCentralityMFT) { + getHist(TH1, histPath + "hCentralityDistributionMFT")->Fill(hCentralityMFT->GetBinContent(hCentralityMFT->FindBin(mftNtracks))); + } + } } void process(soa::Join::iterator const& collision) From dcb15ab501a83ae5accc0b5c555503306eee5a2d Mon Sep 17 00:00:00 2001 From: blacwovie Date: Sat, 16 May 2026 16:05:51 +0800 Subject: [PATCH 184/449] [PWGCF] change pion selection (#16267) Co-authored-by: ALICE Action Bot --- .../TableProducer/HadNucleiFemto.cxx | 128 ++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index a8ef42e5973..88540514c26 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -185,8 +185,11 @@ struct HadNucleiFemto { Configurable settingCutNsigmaTOFTPCHad{"settingCutNsigmaTOFTPCHad", 3.0f, "Value of the hsdron TOF TPC combNsigma cut"}; Configurable settingCutNsigTPCPrMin{"settingCutNsigTPCPrMin", 3.0f, "Minimum TPC Pr Nsigma cut for rejection"}; Configurable settingCutNsigTPCPiMin{"settingCutNsigTPCPiMin", 3.0f, "Minimum TPC Pi Nsigma cut for rejection"}; + Configurable settingCutNsigTPCKaMin{"settingCutNsigTPCKaMin", 3.0f, "Minimum TPC Ka Nsigma cut for rejection"}; Configurable settingCutNsigTOFPrMin{"settingCutNsigTOFPrMin", 3.0f, "Minimum TOF Pr Nsigma cut for rejection"}; Configurable settingCutNsigTOFPiMin{"settingCutNsigTOFPiMin", 3.0f, "Minimum TOF Pi Nsigma cut for rejection"}; + Configurable settingCutNsigTOFKaMin{"settingCutNsigTOFKaMin", 3.0f, "Minimum TOF Ka Nsigma cut for rejection"}; + Configurable settingUsePionReferencePIDCuts{"settingUsePionReferencePIDCuts", false, "If true, use the reference pion track/PID cuts from the pi-p study"}; // Deuteron purity and PID cuts Configurable settingCutPinMinDe{"settingCutPinMinDe", 0.0f, "Minimum Pin for De"}; Configurable settingCutClSizeItsDe{"settingCutClSizeItsDe", 4.0f, "Minimum ITS cluster size for De"}; @@ -297,18 +300,23 @@ struct HadNucleiFemto { {"h2NsigmaHadTPC_preselection", "NsigmaNu TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"h2NsigmaHadTOF", "NsigmaHad TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, {"h2NsigmaHadTOF_preselection", "NsigmaHad TOF distribution; #iit{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"h2NsigmaHadComb_preselection", "NsigmaHad TPCTOF comb distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{comb}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 5.0f}}}}, {"h2NsigmaHadPrTPC", "NsigmaHad TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, {"h2NsigmaHadPiTPC", "NsigmaHad TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(pi)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, + {"h2NsigmaHadKaTPC", "NsigmaHad TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(K)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, {"h2NsigmaHadPrTOF", "NsigmaHad TOF distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, {"h2NsigmaHadPiTOF", "NsigmaHad TOF distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(pi)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, + {"h2NsigmaHadKaTOF", "NsigmaHad TOF distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(K)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, // Purity {"purity/h2NsigmaNuTPC_preselection", "NsigmaNu TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"purity/h2NsigmaNuTPC_preselecComp", "NsigmaNu TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"purity/h2NSigmaNuITS_preselection", "NsigmaNu ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} Nu", {HistType::kTH2F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}}}}, {"purity/h2NsigmaNuTOF_preselection", "NsigmaNu TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"purity/h2NsigmaNuComb_preselection", "NsigmaNu TPCTOF comb distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{comb}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 5.0f}}}}, {"purity/h2NsigmaHadTPC_preselection", "NsigmaNu TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(Nu)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"purity/h2NsigmaHadTOF_preselection", "NsigmaHad TOF distribution; #iit{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"purity/h2NsigmaHadComb_preselection", "NsigmaHad TPCTOF comb distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{comb}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 5.0f}}}}, // Hypertriton {"hHe3TPCnsigma", "NsigmaHe3 TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(He3)", {HistType::kTH2F, {{100, -2.0f, 2.0f}, {200, -5.0f, 5.0f}}}}, @@ -498,7 +506,7 @@ struct HadNucleiFemto { return false; } const int minTPCNClsFound = 90; - const int minTPCNClsCrossedRows = 100; + const int minTPCNClsCrossedRows = 70; const float crossedRowsToFindableRatio = 0.83f; if (candidate.itsNCls() < settingCutNCls || candidate.tpcNClsFound() < minTPCNClsFound || @@ -513,6 +521,59 @@ struct HadNucleiFemto { return true; } + bool useReferencePionCuts() const + { + return settingUsePionReferencePIDCuts.value && settingHadPDGCode.value == static_cast(PDG_t::kPiPlus); + } + + template + bool selectTrackPionReference(const Ttrack& candidate) + { + constexpr float pionRefPtMin = 0.14f; + constexpr float pionRefPtMax = 2.5f; + constexpr int pionRefITSInnerBarrelMin = 3; + constexpr int pionRefITSNClsMin = 7; + constexpr int pionRefTPCNClsFoundMin = 80; + constexpr int pionRefTPCCrossedRowsMin = 90; + + if (std::abs(candidate.eta()) > settingCutEta) { + return false; + } + + const float absPt = std::abs(candidate.pt()); + if (absPt < pionRefPtMin || absPt > pionRefPtMax) { + return false; + } + + if (candidate.itsNClsInnerBarrel() < pionRefITSInnerBarrelMin || + candidate.itsNCls() < pionRefITSNClsMin || + candidate.tpcNClsFound() < pionRefTPCNClsFoundMin || + candidate.tpcNClsCrossedRows() < pionRefTPCCrossedRowsMin) { + return false; + } + + if (absPt <= 0.f) { + return false; + } + + const float pionDCAxyMax = 0.004f + 0.013f / absPt; + const float pionDCAzMax = 0.004f + 0.013f / absPt; + if (std::abs(candidate.dcaXY()) > pionDCAxyMax || std::abs(candidate.dcaZ()) > pionDCAzMax) { + return false; + } + + return true; + } + + template + bool selectTrackHadron(const Ttrack& candidate) + { + if (useReferencePionCuts()) { + return selectTrackPionReference(candidate); + } + return selectTrack(candidate); + } + template bool selectTrackDe(const Ttrack& candidate) { @@ -595,6 +656,42 @@ struct HadNucleiFemto { template bool selectionPIDPion(const Ttrack& candidate) { + if (useReferencePionCuts()) { + constexpr float pionRefPCombMin = 0.5f; + constexpr float pionRefTPCNsigmaMax = 3.0f; + constexpr float pionRefCombNsigmaMax = 3.0f; + + const float tpcNSigmaPi = candidate.tpcNSigmaPi(); + const float absP = std::abs(candidate.p()); + mQaRegistry.fill(HIST("h2NsigmaHadTPC_preselection"), candidate.sign() * candidate.tpcInnerParam(), tpcNSigmaPi); + + if (absP <= pionRefPCombMin) { + if (std::abs(tpcNSigmaPi) > pionRefTPCNsigmaMax) { + return false; + } + mQaRegistry.fill(HIST("h2NsigmaHadTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPi); + mQaRegistry.fill(HIST("h2dEdxHadcandidates"), candidate.sign() * candidate.tpcInnerParam(), candidate.tpcSignal()); + return true; + } + + if (!candidate.hasTOF()) { + return false; + } + + const float tofNSigmaPi = candidate.tofNSigmaPi(); + const float combNsigma = std::sqrt(tofNSigmaPi * tofNSigmaPi + tpcNSigmaPi * tpcNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaHadTOF_preselection"), candidate.sign() * candidate.pt(), tofNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaHadComb_preselection"), candidate.sign() * candidate.pt(), combNsigma); + if (combNsigma > pionRefCombNsigmaMax) { + return false; + } + mQaRegistry.fill(HIST("h2NsigmaHadTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaHadTOF"), candidate.sign() * candidate.pt(), tofNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaHadComb"), candidate.sign() * candidate.pt(), combNsigma); + mQaRegistry.fill(HIST("h2dEdxHadcandidates"), candidate.sign() * candidate.tpcInnerParam(), candidate.tpcSignal()); + return true; + } + if (std::abs(candidate.dcaXY()) > settingCutHadDCAxyMin || std::abs(candidate.dcaZ()) > settingCutHadDCAzMin) return false; @@ -602,13 +699,21 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("h2NsigmaHadTPC_preselection"), candidate.sign() * candidate.tpcInnerParam(), tpcNSigmaPi); if (std::abs(candidate.pt()) < settingCutHadptMin || std::abs(candidate.pt()) > settingCutHadptMax) return false; - // reject protons + // reject protons and kaons if (std::abs(candidate.tpcNSigmaPr()) < settingCutNsigTPCPrMin) return false; + if (std::abs(candidate.tpcNSigmaKa()) < settingCutNsigTPCKaMin) + return false; mQaRegistry.fill(HIST("h2NsigmaHadPrTPC"), candidate.tpcNSigmaPr()); + mQaRegistry.fill(HIST("h2NsigmaHadKaTPC"), candidate.tpcNSigmaKa()); if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < settingCutNsigTOFPrMin) return false; + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < settingCutNsigTOFKaMin) + return false; mQaRegistry.fill(HIST("h2NsigmaHadPrTOF"), candidate.tofNSigmaPr()); + if (candidate.hasTOF()) { + mQaRegistry.fill(HIST("h2NsigmaHadKaTOF"), candidate.tofNSigmaKa()); + } if (candidate.hasTOF() && std::abs(candidate.pt()) > settingCutPinMinTOFHad) { auto tofNSigmaPi = candidate.tofNSigmaPi(); @@ -967,7 +1072,7 @@ struct HadNucleiFemto { } } - if (!selectTrack(track1) || !selectionPIDHadron(track1)) { + if (!selectTrackHadron(track1) || !selectionPIDHadron(track1)) { continue; } @@ -993,7 +1098,7 @@ struct HadNucleiFemto { mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); - if (!selectTrack(hadTrack)) { + if (!selectTrackHadron(hadTrack)) { continue; } mQaRegistry.fill(HIST("hTrackSel"), Selections::kTrackCuts); @@ -1022,7 +1127,7 @@ struct HadNucleiFemto { continue; } for (const auto& hadCand : hadCands) { - if (!selectTrack(hadCand) || !selectionPIDHadron(hadCand)) { + if (!selectTrackHadron(hadCand) || !selectionPIDHadron(hadCand)) { continue; } @@ -1045,7 +1150,7 @@ struct HadNucleiFemto { continue; } for (const auto& hadCand : hadCands) { - if (!selectTrack(hadCand) || !selectionPIDHadron(hadCand)) { + if (!selectTrackHadron(hadCand) || !selectionPIDHadron(hadCand)) { continue; } @@ -1396,7 +1501,8 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa trackTableThisCollision.bindExternalIndices(&tracks); for (const auto& track : trackTableThisCollision) { - const bool passTrackHad = selectTrack(track); + constexpr float pionRefPCombMin = 0.5f; + const bool passTrackHad = selectTrackHadron(track); const bool passTrackDe = selectTrackDe(track); mQaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); @@ -1412,16 +1518,20 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa if (passTrackHad && settingHadPDGCode == PDG_t::kPiPlus) { const float tpcNSigmaHad = track.tpcNSigmaPi(); mQaRegistry.fill(HIST("purity/h2NsigmaHadTPC_preselection"), track.sign() * track.pt(), tpcNSigmaHad); - if (track.hasTOF() && std::abs(track.pt()) > settingCutPinMinTOFHad) { + if (useReferencePionCuts() ? (track.hasTOF() && std::abs(track.p()) > pionRefPCombMin) : (track.hasTOF() && std::abs(track.pt()) > settingCutPinMinTOFHad)) { const float tofNSigmaHad = track.tofNSigmaPi(); + const float combNsigmaHad = std::sqrt(tofNSigmaHad * tofNSigmaHad + tpcNSigmaHad * tpcNSigmaHad); mQaRegistry.fill(HIST("purity/h2NsigmaHadTOF_preselection"), track.sign() * track.pt(), tofNSigmaHad); + mQaRegistry.fill(HIST("purity/h2NsigmaHadComb_preselection"), track.sign() * track.pt(), combNsigmaHad); } } else if (passTrackHad && settingHadPDGCode == PDG_t::kKPlus) { const float tpcNSigmaHad = track.tpcNSigmaKa(); mQaRegistry.fill(HIST("purity/h2NsigmaHadTPC_preselection"), track.sign() * track.pt(), tpcNSigmaHad); if (track.hasTOF() && track.tpcInnerParam() >= settingCutPinMinTOFHad) { const float tofNSigmaHad = track.tofNSigmaKa(); + const float combNsigmaHad = std::sqrt(tofNSigmaHad * tofNSigmaHad + tpcNSigmaHad * tpcNSigmaHad); mQaRegistry.fill(HIST("purity/h2NsigmaHadTOF_preselection"), track.sign() * track.pt(), tofNSigmaHad); + mQaRegistry.fill(HIST("purity/h2NsigmaHadComb_preselection"), track.sign() * track.pt(), combNsigmaHad); } } @@ -1431,7 +1541,9 @@ PROCESS_SWITCH(HadNucleiFemto, processMixedEventHyper, "Process Mixed event", fa mQaRegistry.fill(HIST("purity/h2NsigmaNuTPC_preselecComp"), track.sign() * track.pt(), track.tpcNSigmaDe()); if (track.hasTOF() && track.tpcInnerParam() > settingCutPinMinTOFITSDe) { const float tofNSigmaDe = track.tofNSigmaDe(); + const float combNsigmaDe = std::sqrt(tofNSigmaDe * tofNSigmaDe + tpcNSigmaDe * tpcNSigmaDe); mQaRegistry.fill(HIST("purity/h2NsigmaNuTOF_preselection"), track.sign() * track.pt(), tofNSigmaDe); + mQaRegistry.fill(HIST("purity/h2NsigmaNuComb_preselection"), track.sign() * track.pt(), combNsigmaDe); } else if (track.tpcInnerParam() <= settingCutPinMinTOFITSDe) { const float itsNSigmaDe = itsResponse.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta()); mQaRegistry.fill(HIST("purity/h2NSigmaNuITS_preselection"), track.sign() * track.pt(), itsNSigmaDe); From a3cd8a15cdbfed7a73bf668bf386756c2eb49a26 Mon Sep 17 00:00:00 2001 From: sashingo Date: Sat, 16 May 2026 17:30:28 +0900 Subject: [PATCH 185/449] [PWGHF] added THn for QA of electrons from Z (#16231) --- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 100 ++++++++++++++-------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index a172f752afc..52a8f9b905e 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -140,21 +140,23 @@ struct HfTaskElectronWeakBoson { Configurable> centralityBins{"centralityBins", {0, 20, 60, 100}, "centrality bins"}; // QA for Z->ee - Configurable enableZeeRecoQA{"enableZeeRecoQA", false, "Enable QA for Z->ee reconstruction"}; + Configurable enableZeeTrkRecoQA{"enableZeeTrkRecoQA", false, "Enable QA for track info Z->ee reconstruction"}; + Configurable enableZeeEmcRecoQA{"enableZeeEmcRecoQA", false, "Enable QA for Emc info Z->ee reconstruction"}; Configurable massZMinQA{"massZMinQA", 0.1, "minimum mass cut for Zee Reco QA"}; - // CCDB service object - Service ccdb{}; // UE Configurable nRandomCones{"nRandomCones", 100, "number of random cones"}; Configurable rcHardE{"rcHardE", 5.0, "hard cluster veto energy"}; Configurable rcVetoR{"rcVetoR", 0.4, "veto radius"}; Configurable useUEsub{"useUEsub", true, "apply UE subtraction in isolation"}; + // CCDB service object + Service ccdb{}; + struct HfElectronCandidate { - float pt, eta, phi, dcaxyTrk, dcazTrk, eop, energyIso, momIso; + float pt, eta, phi, dcaxyTrk, dcazTrk, eop, energyIso, momIso, dedxTrk, m02Emc; int ntrackIso, nclusterTPC, nclusterITS; - HfElectronCandidate(float ptr, float e, float ph, float dcaxy, float dcaz, float ep, float eiso, float piso, int ntrkiso, int nclstpc, int nclsits) - : pt(ptr), eta(e), phi(ph), dcaxyTrk(dcaxy), dcazTrk(dcaz), eop(ep), energyIso(eiso), momIso(piso), ntrackIso(ntrkiso), nclusterTPC(nclstpc), nclusterITS(nclsits) {} + HfElectronCandidate(float ptr, float e, float ph, float dcaxy, float dcaz, float ep, float eiso, float piso, float dedx, float m02, int ntrkiso, int nclstpc, int nclsits) + : pt(ptr), eta(e), phi(ph), dcaxyTrk(dcaxy), dcazTrk(dcaz), eop(ep), energyIso(eiso), momIso(piso), dedxTrk(dedx), m02Emc(m02), ntrackIso(ntrkiso), nclusterTPC(nclstpc), nclusterITS(nclsits) {} }; std::vector selectedElectronsIso; std::vector selectedPositronsIso; @@ -196,20 +198,13 @@ struct HfTaskElectronWeakBoson { ConfigurableAxis confaxisPtZneg{"confaxisPtZneg", {60, 20, 80}, "p_{T,neg} (GeV/c)"}; ConfigurableAxis confaxisPtZpos{"confaxisPtZpos", {60, 20, 80}, "p_{T,pos} (GeV/c)"}; ConfigurableAxis confaxisEop{"confaxisEop", {300, -0.01, 1.49}, "E/p"}; - ConfigurableAxis confaxisEopZneg{"confaxisEopZneg", {300, -0.01, 1.49}, "E/p_{neg}"}; - ConfigurableAxis confaxisEopZpos{"confaxisEopZpos", {300, -0.01, 1.49}, "E/p_{pos}"}; ConfigurableAxis confaxisIsoEnergy{"confaxisIsoEnergy", {255, 0, 2.0}, "E_{iso}"}; - ConfigurableAxis confaxisIsoEnergyZneg{"confaxisIsoEnergyZneg", {255, 0, 2.0}, "E_{iso,neg}"}; - ConfigurableAxis confaxisIsoEnergyZpos{"confaxisIsoEnergyZpos", {255, 0, 2.0}, "E_{iso,pos}"}; - ConfigurableAxis confaxisIsoMomentum{"confaxisIsoMomentum", {255, 0, 2.0}, "E_{iso}"}; - ConfigurableAxis confaxisIsoMomentumZneg{"confaxisIsoMomentumZneg", {255, 0, 1.5}, "E_{iso,neg}"}; - ConfigurableAxis confaxisIsoMomentumZpos{"confaxisIsoMomentumZpos", {255, 0, 1.5}, "E_{iso,pos}"}; + ConfigurableAxis confaxisIsoMomentum{"confaxisIsoMomentum", {255, 0, 2.0}, "p_{iso}"}; ConfigurableAxis confaxisIsoTrack{"confaxisIsoTrack", {25, -0.5, 24.5}, "Isolation Track"}; - ConfigurableAxis confaxisIsoTrackZneg{"confaxisIsoTrackZneg", {25, -0.5, 24.5}, "N_{isotrk,neg}"}; - ConfigurableAxis confaxisIsoTrackZpos{"confaxisIsoTrackZpos", {25, -0.5, 24.5}, "N_{isotrk,pos}"}; ConfigurableAxis confaxisInvMassZgamma{"confaxisInvMassZgamma", {150, 0, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisInvMassZ{"confaxisInvMassZ", {130, 20, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisZfrag{"confaxisZfrag", {200, 0, 2.0}, "p_{T,h}/p_{T,Z}"}; + ConfigurableAxis confaxisDEtaZh{"confaxisDEtaZh", {200, -4.0, 4.0}, "#Delta#eta"}; ConfigurableAxis confaxisMultPV{"confaxisMultPV", {200, 0, 200.0}, "multiplicity"}; ConfigurableAxis confaxisMultFT0{"confaxisMultFT0", {1000, 0, 1000.0}, "multiplicity"}; @@ -262,9 +257,13 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisSectorTPCneg{360, 0, 18, "TPCsector_{neg}"}; const AxisSpec axisSectorTPCpos{360, 0, 18, "TPCsector_{pos}"}; const AxisSpec axisNsigma{100, -5, 5, "N#sigma"}; + const AxisSpec axisNsigmaZneg{100, -5, 5, "N#sigma_{pos}"}; + const AxisSpec axisNsigmaZpos{100, -5, 5, "N#sigma_{neg}"}; const AxisSpec axisDedx{150, 0, 150, "dEdx"}; const AxisSpec axisE{nBinsE, 0, binEmax, "Energy"}; const AxisSpec axisM02{100, 0, 1, "M02"}; + const AxisSpec axisM02neg{100, 0, 1, "M02(neg)"}; + const AxisSpec axisM02pos{100, 0, 1, "M02(pos)"}; const AxisSpec axisdPhi{100, -0.5, 0.5, "dPhi"}; const AxisSpec axisdEta{100, -0.5, 0.5, "dEta"}; const AxisSpec axisdR{20, 0.0, 0.2, "dR"}; @@ -276,26 +275,27 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisEMCtime{100, -50.0, 50, "EMC time"}; const AxisSpec axisTrigger{3, -0.5, 2.5, "Trigger status of zorro"}; const AxisSpec axisDPhiZh{64, -o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf, "#Delta#phi(Z-h)"}; + const AxisSpec axisDEtaZh{confaxisDEtaZh, "#Delta#Eta(Z-h)"}; const AxisSpec axisPtHadron{nBinsPt, 0, binPtmax, "p_{T,hadron} (GeV/c)"}; const AxisSpec axisPtZ{nBinsPt, 0, binPtmax, "p_{T,Z} (GeV/c)"}; const AxisSpec axisSign{2, -2, 2, "charge sign"}; const AxisSpec axisCentrality{centralityBins, "centrality"}; const AxisSpec axisEop{confaxisEop, "E/p"}; - const AxisSpec axisEopZneg{confaxisEopZneg, "E/p_{neg}"}; - const AxisSpec axisEopZpos{confaxisEopZpos, "E/p_{[pos}"}; + const AxisSpec axisEopZneg{confaxisEop, "E/p_{neg}"}; + const AxisSpec axisEopZpos{confaxisEop, "E/p_{[pos}"}; const AxisSpec axisPt{confaxisPt, "p_{T}"}; const AxisSpec axisPtZee{confaxisPtZee, "p_{T}"}; const AxisSpec axisPtZneg{confaxisPtZneg, "p_{T,neg} (GeV/c)"}; const AxisSpec axisPtZpos{confaxisPtZpos, "p_{T,pos} (GeV/c)"}; const AxisSpec axisIsoEnergy{confaxisIsoEnergy, "E_{iso}"}; - const AxisSpec axisIsoEnergyZneg{confaxisIsoEnergyZneg, "E_{iso}"}; - const AxisSpec axisIsoEnergyZpos{confaxisIsoEnergyZpos, "E_{iso}"}; - const AxisSpec axisIsoMomentum{confaxisIsoMomentum, "Isolation momentum(GeV/C)"}; - const AxisSpec axisIsoMomentumZneg{confaxisIsoMomentumZneg, "Isolation momentum(GeV/C)"}; - const AxisSpec axisIsoMomentumZpos{confaxisIsoMomentumZpos, "Isolation momentum(GeV/C)"}; + const AxisSpec axisIsoEnergyZneg{confaxisIsoEnergy, "E_{iso, neg} (GeV)"}; + const AxisSpec axisIsoEnergyZpos{confaxisIsoEnergy, "E_{iso, pos} (GeV)"}; + const AxisSpec axisIsoMomentum{confaxisIsoMomentum, "p_{iso} (GeV/C)"}; + const AxisSpec axisIsoMomentumZneg{confaxisIsoMomentum, "p_{iso, neg}(GeV/C)"}; + const AxisSpec axisIsoMomentumZpos{confaxisIsoMomentum, "p_{iso, pos}(GeV/C)"}; const AxisSpec axisIsoTrack{confaxisIsoTrack, "Isolation Track"}; - const AxisSpec axisIsoTrackZneg{confaxisIsoTrackZneg, "N_{isotrk,neg}"}; - const AxisSpec axisIsoTrackZpos{confaxisIsoTrackZpos, "N_{isotrk,pos}"}; + const AxisSpec axisIsoTrackZneg{confaxisIsoTrack, "N_{isotrk,neg}"}; + const AxisSpec axisIsoTrackZpos{confaxisIsoTrack, "N_{isotrk,pos}"}; const AxisSpec axisInvMassZgamma{confaxisInvMassZgamma, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisInvMassZ{confaxisInvMassZ, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisZfrag{confaxisZfrag, "p_{T,h}/p_{T,Z}"}; @@ -333,13 +333,15 @@ struct HfTaskElectronWeakBoson { registry.add("hIsolationEnergy", "Isolation Energy", kTH2F, {{axisE}, {axisIsoEnergy}}); registry.add("hInvMassZee", "invariant mass for Z ULS pair", HistType::kTHnSparseF, {axisCentrality, axisSign, axisPt, axisInvMassZgamma}); registry.add("hKfInvMassZee", "invariant mass for Z ULS pair KFp", HistType::kTHnSparseF, {axisCentrality, axisSign, axisPt, axisInvMassZgamma}); - registry.add("hInvMassZeeQA", "QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisDCAxyneg, axisDCAxypos, axisDCAzpos, axisNclsTPCneg, axisNclsTPCpos, axisNclsITSneg, axisNclsITSpos, axisSectorTPCneg, axisSectorTPCneg, axisEopZneg, axisEopZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); - registry.add("hInvMassZeeQAbg", "QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisDCAxyneg, axisDCAxypos, axisDCAzpos, axisNclsTPCneg, axisNclsTPCpos, axisNclsITSneg, axisNclsITSpos, axisSectorTPCneg, axisSectorTPCneg, axisEopZneg, axisEopZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); + registry.add("hInvMassZeeTrkQA", "Track QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisDCAxyneg, axisDCAxypos, axisDCAzpos, axisNclsTPCneg, axisNclsTPCpos, axisNclsITSneg, axisNclsITSpos, axisSectorTPCneg, axisSectorTPCneg, axisEopZneg, axisEopZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); + registry.add("hInvMassZeeTrkQAbg", "Track QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisDCAxyneg, axisDCAxypos, axisDCAzpos, axisNclsTPCneg, axisNclsTPCpos, axisNclsITSneg, axisNclsITSpos, axisSectorTPCneg, axisSectorTPCneg, axisEopZneg, axisEopZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); + registry.add("hInvMassZeeEmcQA", "EMCal QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisEopZneg, axisEopZpos, axisM02neg, axisM02pos, axisNsigmaZneg, axisNsigmaZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); + registry.add("hInvMassZeeEmcQAbg", "EMCal QA for invariant mass for Z", HistType::kTHnSparseF, {axisInvMassZ, axisPtZneg, axisPtZpos, axisEopZneg, axisEopZpos, axisM02neg, axisM02pos, axisNsigmaZneg, axisNsigmaZpos, axisIsoEnergyZneg, axisIsoEnergyZpos, axisIsoMomentumZneg, axisIsoMomentumZpos, axisIsoTrackZneg, axisIsoTrackZpos}); registry.add("hTHnElectrons", "electron info", HistType::kTHnSparseF, {axisPt, axisNsigma, axisM02, axisEop, axisIsoEnergy, axisIsoMomentum, axisIsoTrack, axisEta, axisDedx}); registry.add("hTHnTrMatch", "Track EMC Match", HistType::kTHnSparseF, {axisPt, axisdPhi, axisdEta}); // Z-hadron correlation histograms - registry.add("hZHadronDphi", "Z-hadron #Delta#phi correlation", HistType::kTHnSparseF, {axisCentrality, axisSign, axisPtZ, axisDPhiZh, axisZfrag, axisPtHadron}); + registry.add("hZHadronDphi", "Z-hadron #Delta#phi correlation", HistType::kTHnSparseF, {axisCentrality, axisSign, axisPtZ, axisDPhiZh, axisDEtaZh, axisZfrag, axisPtHadron}); registry.add("hZptSpectrum", "Z boson p_{T} spectrum", kTH2F, {{axisSign}, {axisPtZ}}); // hisotgram for EMCal trigger @@ -356,7 +358,7 @@ struct HfTaskElectronWeakBoson { float energyUE) { double energySum = 0.0; - double energySum_excl = 0.0; + double energySumExcl = 0.0; double isoEnergy = 10.0; double const etaAssCluster = cluster.eta(); double const phiAssCluster = cluster.phi(); @@ -377,9 +379,9 @@ struct HfTaskElectronWeakBoson { energySum += associateCluster.energy(); } } - energySum_excl = energySum - cluster.energy(); + energySumExcl = energySum - cluster.energy(); if (energySum > 0) { - isoEnergy = (energySum_excl - energyUE) / cluster.energy(); + isoEnergy = (energySumExcl - energyUE) / cluster.energy(); } // LOG(info) <<"clustE = " << cluster.energy() << " ; energySum = " << energySum << " ; nclust in Cone = " << nclustSum - 1 << " ; UE = " << energyUE << " ; isoEnergy = " << isoEnergy; @@ -671,6 +673,7 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hTPCNsigma"), track.p(), track.tpcNSigmaEl()); float eop = -0.01; + float m02 = -0.01; float isoEnergy = 99.0; // track isolation auto [trackCount, isoMomentum] = getIsolatedTrack(track.eta(), track.phi(), track.p(), tracks); @@ -686,6 +689,8 @@ struct HfTaskElectronWeakBoson { eop, isoEnergy, isoMomentum, + track.tpcNSigmaEl(), + m02, trackCount, track.tpcNClsCrossedRows(), track.itsNCls()); @@ -758,6 +763,7 @@ struct HfTaskElectronWeakBoson { const auto& cluster = match.emcalcluster_as(); eop = energyEmc / match.track_as().p(); + m02 = m02Emc; // LOG(info) << "eop = " << eop; isoEnergy = getIsolatedCluster(cluster, emcClusters, energyUE); @@ -807,7 +813,7 @@ struct HfTaskElectronWeakBoson { // LOG(info) << "R mim = " << rMin; registry.fill(HIST("hTrMatch_mim"), dPhiMin, dEtaMin); } - if (enableZeeRecoQA && track.pt() > ptZeeMin) { + if ((enableZeeTrkRecoQA || enableZeeEmcRecoQA) && track.pt() > ptZeeMin) { if (track.sign() < 0) { selectedElectronsIso.emplace_back( track.pt(), @@ -818,6 +824,8 @@ struct HfTaskElectronWeakBoson { eop, isoEnergy, isoMomentum, + track.tpcNSigmaEl(), + m02, trackCount, track.tpcNClsFound(), track.itsNCls()); @@ -831,6 +839,8 @@ struct HfTaskElectronWeakBoson { eop, isoEnergy, isoMomentum, + track.tpcNSigmaEl(), + m02, trackCount, track.tpcNClsFound(), track.itsNCls()); @@ -856,12 +866,13 @@ struct HfTaskElectronWeakBoson { // calculate Z-h correlation double const deltaPhi = RecoDecay::constrainAngle(trackAss.phi - zBoson.phi, -o2::constants::math::PIHalf); double const ptRatio = trackAss.pt / zBoson.pt; - registry.fill(HIST("hZHadronDphi"), centrality, zBoson.charge, zBoson.pt, deltaPhi, ptRatio, trackAss.pt); + double const deltaEta = zBoson.eta - trackAss.eta; + registry.fill(HIST("hZHadronDphi"), centrality, zBoson.charge, zBoson.pt, deltaPhi, deltaEta, ptRatio, trackAss.pt); } } } // end of Z-hadron correlation // Z->ee QA - if (enableZeeRecoQA) { + if (enableZeeTrkRecoQA || enableZeeEmcRecoQA) { if (!selectedElectronsIso.empty() && !selectedPositronsIso.empty()) { // signal for (const auto& trackEle : selectedElectronsIso) { @@ -872,7 +883,12 @@ struct HfTaskElectronWeakBoson { double const invMass = RecoDecay::m(std::array{child1, child2}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); float const sectorpos = trackPos.phi / o2::constants::math::SectorSpanRad; if (invMass > massZMinQA) { - registry.fill(HIST("hInvMassZeeQA"), invMass, trackEle.pt, trackPos.pt, trackEle.dcaxyTrk, trackPos.dcaxyTrk, trackPos.dcazTrk, trackEle.nclusterTPC, trackPos.nclusterTPC, trackEle.nclusterITS, trackPos.nclusterITS, sectorneg, sectorpos, trackEle.eop, trackPos.eop, trackEle.energyIso, trackPos.energyIso, trackEle.momIso, trackPos.momIso, trackEle.ntrackIso, trackPos.ntrackIso); + if (enableZeeTrkRecoQA) { + registry.fill(HIST("hInvMassZeeTrkQA"), invMass, trackEle.pt, trackPos.pt, trackEle.dcaxyTrk, trackPos.dcaxyTrk, trackPos.dcazTrk, trackEle.nclusterTPC, trackPos.nclusterTPC, trackEle.nclusterITS, trackPos.nclusterITS, sectorneg, sectorpos, trackEle.eop, trackPos.eop, trackEle.energyIso, trackPos.energyIso, trackEle.momIso, trackPos.momIso, trackEle.ntrackIso, trackPos.ntrackIso); + } + if (enableZeeEmcRecoQA) { + registry.fill(HIST("hInvMassZeeEmcQA"), invMass, trackEle.pt, trackPos.pt, trackEle.eop, trackPos.eop, trackEle.m02Emc, trackPos.m02Emc, trackEle.dedxTrk, trackPos.dedxTrk, trackEle.energyIso, trackPos.energyIso, trackEle.momIso, trackPos.momIso, trackEle.ntrackIso, trackPos.ntrackIso); + } } } } @@ -887,7 +903,12 @@ struct HfTaskElectronWeakBoson { float const sectorpos = trackEle2.phi / o2::constants::math::SectorSpanRad; double const invMass = RecoDecay::m(std::array{child1, child2}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); if (invMass > massZMinQA) { - registry.fill(HIST("hInvMassZeeQAbg"), invMass, trackEle.pt, trackEle2.pt, trackEle.dcaxyTrk, trackEle2.dcaxyTrk, trackEle2.dcazTrk, trackEle.nclusterTPC, trackEle2.nclusterTPC, trackEle.nclusterITS, trackEle2.nclusterITS, sectorneg, sectorpos, trackEle.eop, trackEle2.eop, trackEle.energyIso, trackEle2.energyIso, trackEle.momIso, trackEle2.momIso, trackEle.ntrackIso, trackEle2.ntrackIso); + if (enableZeeTrkRecoQA) { + registry.fill(HIST("hInvMassZeeTrkQAbg"), invMass, trackEle.pt, trackEle2.pt, trackEle.dcaxyTrk, trackEle2.dcaxyTrk, trackEle2.dcazTrk, trackEle.nclusterTPC, trackEle2.nclusterTPC, trackEle.nclusterITS, trackEle2.nclusterITS, sectorneg, sectorpos, trackEle.eop, trackEle2.eop, trackEle.energyIso, trackEle2.energyIso, trackEle.momIso, trackEle2.momIso, trackEle.ntrackIso, trackEle2.ntrackIso); + } + if (enableZeeEmcRecoQA) { + registry.fill(HIST("hInvMassZeeEmcQAbg"), invMass, trackEle.pt, trackEle2.pt, trackEle.eop, trackEle2.eop, trackEle.m02Emc, trackEle2.m02Emc, trackEle.dedxTrk, trackEle2.dedxTrk, trackEle.energyIso, trackEle2.energyIso, trackEle.momIso, trackEle2.momIso, trackEle.ntrackIso, trackEle2.ntrackIso); + } } } } @@ -902,10 +923,15 @@ struct HfTaskElectronWeakBoson { float const sectorpos = trackPos2.phi / o2::constants::math::SectorSpanRad; double const invMass = RecoDecay::m(std::array{child1, child2}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); if (invMass > massZMinQA) { - registry.fill(HIST("hInvMassZeeQAbg"), invMass, trackPos.pt, trackPos2.pt, trackPos.dcaxyTrk, trackPos2.dcaxyTrk, trackPos2.dcazTrk, trackPos.nclusterTPC, trackPos2.nclusterTPC, trackPos.nclusterITS, trackPos2.nclusterITS, sectorneg, sectorpos, trackPos.eop, trackPos2.eop, trackPos.energyIso, trackPos2.energyIso, trackPos.momIso, trackPos2.momIso, trackPos.ntrackIso, trackPos2.ntrackIso); + if (enableZeeTrkRecoQA) { + registry.fill(HIST("hInvMassZeeTrkQAbg"), invMass, trackPos.pt, trackPos2.pt, trackPos.dcaxyTrk, trackPos2.dcaxyTrk, trackPos2.dcazTrk, trackPos.nclusterTPC, trackPos2.nclusterTPC, trackPos.nclusterITS, trackPos2.nclusterITS, sectorneg, sectorpos, trackPos.eop, trackPos2.eop, trackPos.energyIso, trackPos2.energyIso, trackPos.momIso, trackPos2.momIso, trackPos.ntrackIso, trackPos2.ntrackIso); + } + if (enableZeeEmcRecoQA) { + registry.fill(HIST("hInvMassZeeEmcQAbg"), invMass, trackPos.pt, trackPos2.pt, trackPos.eop, trackPos2.eop, trackPos.m02Emc, trackPos2.m02Emc, trackPos.dedxTrk, trackPos2.dedxTrk, trackPos.energyIso, trackPos2.energyIso, trackPos.momIso, trackPos2.momIso, trackPos.ntrackIso, trackPos2.ntrackIso); + } } } - } + } // end of pos-pos paring } // check arrays aren't empty } // end of Z->ee QA } // process From 3cc17fcd379808c95687534e3fad786a49c07986 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 16 May 2026 10:43:31 +0200 Subject: [PATCH 186/449] [Common] Forgot to fill two histograms: fixed (#16268) --- Common/Tasks/centralityStudypp.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index cb37808c8d4..53ed17648be 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -454,6 +454,8 @@ struct centralityStudypp { getHist(TH1, histPath + "hFT0A_Collisions")->Fill(multFT0A); getHist(TH1, histPath + "hFT0C_Collisions")->Fill(multFT0C); getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C)); + getHist(TH1, histPath + "hFDDA_Collisions")->Fill(multFDDA); + getHist(TH1, histPath + "hFDDC_Collisions")->Fill(multFDDC); getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A); getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); From e453d8160eba17424082106163a60ffa562a6140 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 16 May 2026 11:44:32 +0200 Subject: [PATCH 187/449] [Common] fix one more typo (#16269) --- Common/Tasks/centralityStudypp.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index 53ed17648be..ce1b1afb89e 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -272,7 +272,7 @@ struct centralityStudypp { histPointers.insert({histPath + "hCentralityDistributionFT0C", histos.add((histPath + "hCentralityDistributionFT0C").c_str(), "hCentralityDistributionFT0C", {kTH1D, {{axisCentrality}}})}); histPointers.insert({histPath + "hCentralityDistributionFT0M", histos.add((histPath + "hCentralityDistributionFT0M").c_str(), "hCentralityDistributionFT0M", {kTH1D, {{axisCentrality}}})}); histPointers.insert({histPath + "hCentralityDistributionFDDM", histos.add((histPath + "hCentralityDistributionFDDM").c_str(), "hCentralityDistributionFDDM", {kTH1D, {{axisCentrality}}})}); - histPointers.insert({histPath + "hCentralityDistributionNPTV", histos.add((histPath + "hCentralityDistributionNPTV").c_str(), "hCentralityDistributionNPTV", {kTH1D, {{axisCentrality}}})}); + histPointers.insert({histPath + "hCentralityDistributionNTPV", histos.add((histPath + "hCentralityDistributionNTPV").c_str(), "hCentralityDistributionNTPV", {kTH1D, {{axisCentrality}}})}); histPointers.insert({histPath + "hCentralityDistributionNGlobal", histos.add((histPath + "hCentralityDistributionNGlobal").c_str(), "hCentralityDistributionNGlobal", {kTH1D, {{axisCentrality}}})}); histPointers.insert({histPath + "hCentralityDistributionMFT", histos.add((histPath + "hCentralityDistributionMFT").c_str(), "hCentralityDistributionMFT", {kTH1D, {{axisCentrality}}})}); } From 0aa30c8c86b49e469d6703503de3808f74427d89 Mon Sep 17 00:00:00 2001 From: HANSEO PARK <53218370+hanseopark@users.noreply.github.com> Date: Sat, 16 May 2026 19:33:29 +0900 Subject: [PATCH 188/449] [PWGJE] Add Sumw2() for error propagation (#16193) --- PWGJE/Tasks/bjetCentMult.cxx | 97 ++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/PWGJE/Tasks/bjetCentMult.cxx b/PWGJE/Tasks/bjetCentMult.cxx index 545fd434db0..f7d7b2286e2 100644 --- a/PWGJE/Tasks/bjetCentMult.cxx +++ b/PWGJE/Tasks/bjetCentMult.cxx @@ -51,6 +51,7 @@ struct BjetCentMultTask { Configurable fillGeneralSVQA{"fillGeneralSVQA", true, "process of general QA for sv"}; Configurable fillSVxyz{"fillSVxyz", true, "process of decay lenngth of xyz for sv"}; Configurable useEventWeight{"useEventWeight", true, "Flag whether to scale histograms with the event weight"}; + Configurable doSumw2{"doSumw2", true, "Flag whether to set Sumw2()"}; // Cut configuration Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -137,86 +138,86 @@ struct BjetCentMultTask { AxisSpec axisPercentileMultiplicity = {110, -5., 105., "Percentile multiplicity"}; if (doprocessCentMultQa) { - registry.add("h_amplitude_FT0A", "", {HistType::kTH1F, {{axisFT0}}}); - registry.add("h_amplitude_FT0C", "", {HistType::kTH1F, {{axisFT0}}}); - registry.add("h_scaled_FT0M", "", {HistType::kTH1F, {{axisMultScaledFT0M}}}); - registry.add("h_scaled_FT0M_class", "", {HistType::kTH1F, {{axisMultScaledFT0MClass}}}); - registry.add("h2_centrality_percentile_multiplicity", "mcd collision centrality; centrality; counts", {HistType::kTH2F, {{axisRebinnedCentrality}, {axisPercentileMultiplicity}}}); + registry.add("h_amplitude_FT0A", "", {HistType::kTH1F, {{axisFT0}}}, doSumw2); + registry.add("h_amplitude_FT0C", "", {HistType::kTH1F, {{axisFT0}}}, doSumw2); + registry.add("h_scaled_FT0M", "", {HistType::kTH1F, {{axisMultScaledFT0M}}}, doSumw2); + registry.add("h_scaled_FT0M_class", "", {HistType::kTH1F, {{axisMultScaledFT0MClass}}}, doSumw2); + registry.add("h2_centrality_percentile_multiplicity", "mcd collision centrality; centrality; counts", {HistType::kTH2F, {{axisRebinnedCentrality}, {axisPercentileMultiplicity}}}, doSumw2); } if (doprocessSVData) { - registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); - registry.add("h2_jet_pt_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); - registry.add("h2_jet_eta_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); - registry.add("h2_jet_phi_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); + registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}, doSumw2); + registry.add("h2_jet_pt_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}, doSumw2); + registry.add("h2_jet_eta_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}, doSumw2); + registry.add("h2_jet_phi_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}, doSumw2); if (fillGeneralSVQA) { - registry.add("h2_nprongs_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); - registry.add("hn_jet_Sxy_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); + registry.add("h2_nprongs_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}, doSumw2); + registry.add("hn_jet_Sxy_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}, doSumw2); } } - registry.add("hn_jet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}, doSumw2); + registry.add("hn_taggedjet_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}, doSumw2); + registry.add("hn_taggedjet_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}, doSumw2); } } if (doprocessRhoAreaSubSVData) { - registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); - registry.add("h2_jet_pt_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); - registry.add("h2_jet_eta_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); - registry.add("h2_jet_phi_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); + registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}, doSumw2); + registry.add("h2_jet_pt_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}, doSumw2); + registry.add("h2_jet_eta_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}, doSumw2); + registry.add("h2_jet_phi_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}, doSumw2); if (fillGeneralSVQA) { - registry.add("h2_nprongs_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); - registry.add("hn_jet_Sxy_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); + registry.add("h2_nprongs_rhoareasubtracted_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}, doSumw2); + registry.add("hn_jet_Sxy_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}, doSumw2); } } - registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}, doSumw2); + registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); - registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}, doSumw2); + registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}, doSumw2); } } if (doprocessSVMCD || doprocessSVMCPMCDMatched) { registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); - registry.add("h3_jet_pt_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("h3_jet_eta_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("h3_jet_phi_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_jet_pt_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("h3_jet_eta_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("h3_jet_phi_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillGeneralSVQA) { - registry.add("h3_nprongs_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_jet_Sxy_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_nprongs_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_jet_Sxy_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); } } - registry.add("hn_jet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_taggedjet_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_taggedjet_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); } } if (doprocessRhoAreaSubSVMCD || doprocessRhoAreaSubSVMCPMCDMatched) { - registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); - registry.add("h3_jet_pt_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("h3_jet_eta_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("h3_jet_phi_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}, doSumw2); + registry.add("h3_jet_pt_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("h3_jet_eta_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("h3_jet_phi_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillGeneralSVQA) { - registry.add("h3_nprongs_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_jet_Sxy_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_nprongs_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_jet_Sxy_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); } } - registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_taggedjet_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); if (fillSVxyz) { - registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); + registry.add("hn_taggedjet_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}, doSumw2); } } } From c95a68d724360d749cdebef16244a7ca74dd8c22 Mon Sep 17 00:00:00 2001 From: wefeng1110 <147308878+wefeng1110@users.noreply.github.com> Date: Sat, 16 May 2026 12:34:17 +0200 Subject: [PATCH 189/449] [PWGJE] Add jet angularity histograms (#16256) --- PWGJE/Tasks/jetSpectraCharged.cxx | 57 +++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index bd055c36f2a..adc4fde7839 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -15,6 +15,7 @@ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" @@ -81,6 +82,8 @@ struct JetSpectraCharged { Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events; jet-level rejection can also be applied at the jet finder level for jets only, here rejection is applied for collision and track process functions for the first time, and on jets in case it was set to false at the jet finder level"}; Configurable checkLeadConstituentPtForMcpJets{"checkLeadConstituentPtForMcpJets", false, "flag to choose whether particle level jets should have their lead track pt above leadingConstituentPtMin to be accepted; off by default, as leadingConstituentPtMin cut is only applied on MCD jets for the Pb-Pb analysis using pp MC anchored to Pb-Pb for the response matrix"}; Configurable isMCGenOnly{"isMCGenOnly", false, "analysis is run over mcGen only"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -166,6 +169,7 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_jet_area", "jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet} (GeV/#it{c}); Area_{jet}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}, doSumw2); registry.add("h2_jet_pt_jet_ntracks", "jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}, doSumw2); registry.add("h2_jet_pt_track_pt", "jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}, doSumw2); + registry.add("h2_jet_pt_jet_angularity", "jet #it{p}_{T,jet} vs. angularity;#it{p}_{T,jet} (GeV/#it{c});angularity", {HistType::kTH2F, {jetPtAxis, {30, 0., 1.}}}, doSumw2); registry.add("h3_jet_pt_jet_eta_jet_phi", "jet pt vs. eta vs. phi", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, phiAxis}}, doSumw2); } @@ -180,6 +184,7 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_jet_ntracks_rhoareasubtracted", "jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}, doSumw2); registry.add("h2_jet_pt_jet_corr_pt_rhoareasubtracted", "jet #it{p}_{T,jet} vs. #it{p}_{T,corr}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,corr} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxisRhoAreaSub}}, doSumw2); registry.add("h2_jet_pt_track_pt_rhoareasubtracted", "jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, trackPtAxis}}, doSumw2); + registry.add("h2_jet_pt_jet_angularity_rhoareasubtracted", "jet #it{p}_{T,jet} vs. angularity;#it{p}_{T,jet} (GeV/#it{c});angularity", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {30, 0., 1.}}}, doSumw2); registry.add("h3_jet_pt_jet_eta_jet_phi_rhoareasubtracted", "jet_pt_eta_phi_rhoareasubtracted", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetEtaAxis, phiAxis}}, doSumw2); } @@ -190,6 +195,7 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_part_jet_area_part", "part jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet}^{part} (GeV/#it{c}); Area_{jet}^{part}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}, doSumw2); registry.add("h2_jet_pt_part_jet_ntracks_part", "part jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet, tracks}^{part}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}, doSumw2); registry.add("h2_jet_pt_part_track_pt_part", "part jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, trackPtAxis}}, doSumw2); + registry.add("h2_jet_pt_jet_angularity_part", "part jet #it{p}_{T,jet} vs. angularity;#it{p}_{T,jet} (GeV/#it{c});angularity", {HistType::kTH2F, {jetPtAxis, {30, 0., 1.}}}, doSumw2); registry.add("h3_jet_pt_jet_eta_jet_phi_part", "part jet pt vs. eta vs. phi", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, phiAxis}}, doSumw2); if (doprocessSpectraMCPWeighted) { registry.add("h2_jet_ptcut_part", "p_{T} cut;p_{T,jet}^{part} (GeV/#it{c});N;entries", {HistType::kTH2F, {{300, 0, 300}, {20, 0, 5}}}, doSumw2); @@ -234,6 +240,8 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo", "jet mcp pT vs. delta pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo", "jet mcd pT vs. delta pT / jet mcd pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo", "jet mcp pT vs. jet mcd pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); #it{p}_{T,jet}^{mcd} (GeV/#it{c}) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 5.0}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_mcdetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_mcpetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); } if (checkPtMatched) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); @@ -245,6 +253,8 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedpt", "jet mcp pT vs. delta pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedpt", "jet mcd pT vs. delta pT / jet mcd pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedpt", "jet mcp pT vs. jet mcd pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); #it{p}_{T,jet}^{mcd} (GeV/#it{c}) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 5.0}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedpt_mcdetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedpt_mcpetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); } if (checkGeoPtMatched) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); @@ -256,6 +266,8 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeopt", "jet mcp pT vs. delta pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeopt", "jet mcd pT vs. delta pT / jet mcd pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 2.0}}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeopt", "jet mcp pT vs. jet mcd pT / jet mcp pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); #it{p}_{T,jet}^{mcd} (GeV/#it{c}) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, {1000, -5.0, 5.0}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeopt_mcdetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeopt_mcpetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxis, jetPtAxis, {30, 0., 1.}}}, doSumw2); } } @@ -266,6 +278,8 @@ struct JetSpectraCharged { registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcp corr pT vs. corr delta pT / jet mcp corr pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcd corr pT vs. corr delta pT / jet mcd corr pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_rhoareasubtracted", "jet mcp corr pT vs. jet mcd corr pT / jet mcp corr pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); #it{p}_{T,jet}^{mcd} (GeV/#it{c}) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_rhoareasubtracted_mcdetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, {30, 0., 1.}}}, doSumw2); + registry.add("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_rhoareasubtracted_mcpetaconstraint", "pT mcd vs. pT mcp vs. angularity mcd;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c});angularity", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, {30, 0., 1.}}}, doSumw2); } if (!(acceptSplitCollisions == NonSplitOnly || acceptSplitCollisions == SplitOkCheckAnyAssocColl || acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly)) { @@ -483,9 +497,13 @@ struct JetSpectraCharged { registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi"), jet.pt(), jet.eta(), jet.phi(), weight); } + float angularity = 0.; for (const auto& constituent : jet.template tracks_as()) { registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h2_jet_pt_jet_angularity"), jet.pt(), angularity, weight); } template @@ -511,9 +529,13 @@ struct JetSpectraCharged { } } + float angularity = 0.; for (const auto& constituent : jet.template tracks_as()) { registry.fill(HIST("h2_jet_pt_track_pt_rhoareasubtracted"), jetcorrpt, constituent.pt(), weight); + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h2_jet_pt_jet_angularity_rhoareasubtracted"), jetcorrpt, angularity, weight); } template @@ -531,10 +553,13 @@ struct JetSpectraCharged { registry.fill(HIST("h2_jet_pt_part_jet_area_part"), jet.pt(), jet.area(), weight); registry.fill(HIST("h2_jet_pt_part_jet_ntracks_part"), jet.pt(), jet.tracksIds().size(), weight); } - + float angularity = 0.; for (const auto& constituent : jet.template tracks_as()) { registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h2_jet_pt_jet_angularity_part"), jet.pt(), angularity, weight); } template @@ -584,17 +609,24 @@ struct JetSpectraCharged { } if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { double dpt = jetMCD.pt() - jetMCP.pt(); + float angularityMcd = 0.; + for (auto& constituent : jetMCD.template tracks_as()) { + angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); + } + angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeo_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedgeo"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeo_mcpetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedgeo"), jetMCP.pt(), dpt / jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo"), jetMCP.pt(), jetMCD.pt() / jetMCP.pt(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } registry.fill(HIST("h2_jet_eta_mcd_jet_eta_mcp_matchedgeo"), jetMCD.eta(), jetMCP.eta(), weight); } @@ -613,17 +645,24 @@ struct JetSpectraCharged { } if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { double dpt = jetMCD.pt() - jetMCP.pt(); + float angularityMcd = 0.; + for (auto& constituent : jetMCD.template tracks_as()) { + angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); + } + angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedpt_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedpt"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedpt"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedpt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedpt_mcpetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedpt"), jetMCP.pt(), dpt / jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedpt"), jetMCP.pt(), jetMCD.pt() / jetMCP.pt(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedpt_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } registry.fill(HIST("h2_jet_eta_mcd_jet_eta_mcp_matchedpt"), jetMCD.eta(), jetMCP.eta(), weight); } @@ -642,19 +681,26 @@ struct JetSpectraCharged { } if (jetMCD.template matchedJetGeo_first_as>().globalIndex() == jetMCD.template matchedJetPt_first_as>().globalIndex()) { // not a good way to do this double dpt = jetMCD.pt() - jetMCP.pt(); + float angularityMcd = 0.; + for (auto& constituent : jetMCD.template tracks_as()) { + angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); + } + angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeopt_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeopt"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedgeopt"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeopt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeopt_mcpetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedgeopt"), jetMCP.pt(), dpt / jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedgeopt"), jetMCP.pt(), jetMCD.pt() / jetMCP.pt(), weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeopt_mcpetaconstraint"), jetMCD.pt(), jetMCP.pt(), angularityMcd, weight); } - registry.fill(HIST("h2_jet_eta_mcd_jet_eta_mcp_matchedpt"), jetMCD.eta(), jetMCP.eta(), weight); + registry.fill(HIST("h2_jet_eta_mcd_jet_eta_mcp_matchedgeopt"), jetMCD.eta(), jetMCP.eta(), weight); } } } @@ -676,15 +722,22 @@ struct JetSpectraCharged { double corrTagjetpt = jetMCP.pt() - (mcrho * jetMCP.area()); double corrBasejetpt = jetMCD.pt() - (rho * jetMCD.area()); double dcorrpt = corrBasejetpt - corrTagjetpt; + float angularityMcd = 0.; + for (auto& constituent : jetMCD.template tracks_as()) { + angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); + } + angularityMcd /= (corrBasejetpt * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); registry.fill(HIST("h2_jet_pt_mcd_rhoareasubtracted_jet_pt_mcp_matchedgeo_mcdetaconstraint"), corrBasejetpt, jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted"), corrBasejetpt, dcorrpt / corrBasejetpt, weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, angularityMcd, weight); } if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcpetaconstraint"), corrBasejetpt, corrTagjetpt, weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_rhoareasubtracted"), corrTagjetpt, dcorrpt / corrTagjetpt, weight); registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_rhoareasubtracted"), corrTagjetpt, corrBasejetpt / corrTagjetpt, weight); + registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_rhoareasubtracted_mcpetaconstraint"), corrBasejetpt, corrTagjetpt, angularityMcd, weight); } } } From afd15565b653e0539cd2fe60d6ca65070a93a395 Mon Sep 17 00:00:00 2001 From: ynishida-style Date: Sat, 16 May 2026 19:34:30 +0900 Subject: [PATCH 190/449] [PWGJE] Update analysis code based on ARC comments (#16250) --- PWGJE/Tasks/jetShape.cxx | 687 ++++++++++++++++++++++++--------------- 1 file changed, 432 insertions(+), 255 deletions(-) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index 887cdad8de5..f0f8c6f4574 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -99,12 +99,12 @@ struct JetShapeTask { Configurable> distanceCategory{"distanceCategory", {0.00f, 0.05f, 0.10f, 0.15f, 0.20f, 0.25f, 0.30f, 0.35f, 0.40f, 0.45f, 0.50f, 0.55f, 0.60f, 0.65f, 0.70f}, "distance of category"}; // for ppi production - Configurable etaTrUp{"etaTrUp", 0.7f, "maximum track eta"}; + Configurable etaTrUp{"etaTrUp", 0.9f, "maximum track eta"}; Configurable dcaxyCutMax{"dcaxyCutMax", 2.0f, "maximum DCA xy"}; Configurable chi2ItsMax{"chi2ItsMax", 15.0f, "its chi2 cut"}; Configurable chi2TpcMax{"chi2TpcMax", 4.0f, "tpc chi2 cut"}; Configurable nclItsMin{"nclItsMin", 2.0f, "its # of cluster cut"}; - Configurable nclTpcMin{"nclTpcMin", 100.0f, "tpc # if cluster cut"}; + Configurable nclTpcMin{"nclTpcMin", 70.0f, "tpc # if cluster cut"}; Configurable nclcrossTpcMin{"nclcrossTpcMin", 70.0f, "tpc # of crossedRows cut"}; Configurable mcRapidityMax{"mcRapidityMax", 0.5f, "maximum mctrack y"}; Configurable epsilon{"epsilon", 1e-6, "standard for aboid division of zero"}; @@ -113,85 +113,7 @@ struct JetShapeTask { Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; - HistogramRegistry registry{ - "registry", - {{"tpcTofPi", "tpcTofPi", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcTofPr", "tpcTofPr", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcPi", "tpcPi", {HistType::kTH2F, {{nBinsP, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"tofPi", "tofPi", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"tpcPr", "tpcPr", {HistType::kTH2F, {{nBinsP, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"tofPr", "tofPr", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"tpcDedx", "tpcDedx", {HistType::kTHnSparseD, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tofBeta", "tofBeta", {HistType::kTHnSparseD, {{nBinsPForBeta, 0, pMax}, {nBinsTofBeta, 0.4, 1.1}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPr", "pVsPtForPr", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPi", "pVsPtPi", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"trackPhi", "trackPhi", {HistType::kTH1F, {{80, -1, 7}}}}, - {"trackEta", "trackEta", {HistType::kTH1F, {{100, -1, 1}}}}, - {"trackTpcNClsCrossedRows", "trackTpcNClsCrossedRows", {HistType::kTH1F, {{50, 0, 200}}}}, - {"trackDcaXY", "trackDcaXY", {HistType::kTH1F, {{40, -10, 10}}}}, - {"trackItsChi2NCl", "trackItsChi2NCl", {HistType::kTH1F, {{60, 0, 30}}}}, - {"trackTpcChi2NCl", "trackTpcChi2NCl", {HistType::kTH1F, {{100, 0, 50}}}}, - {"trackTpcNClsFound", "trackTpcNClsFound", {HistType::kTH1F, {{100, 0, 200}}}}, - {"trackItsNCls", "trackItsNCls", {HistType::kTH1F, {{10, 0, 10}}}}, - {"jetTpcTofPi", "jetTpcTofPi", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetTpcTofPr", "jetTpcTofPr", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcTofPiPerpJet", "tpcTofPiPerpJet", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcTofPrPerpJet", "tpcTofPrPerpJet", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetTpcPi", "jetTpcPi", {HistType::kTH2F, {{nBinsP, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"jetTofPi", "jetTofPi", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"jetTpcPr", "jetTpcPr", {HistType::kTH2F, {{nBinsP, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"jetTofPr", "jetTofPr", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"jetTpcDedx", "jetTpcDedx", {HistType::kTHnSparseD, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}, {nBinsDistance, 0, distanceMax}}}}, - {"tpcDedxPerpJet", "tpcDedxPerpJet", {HistType::kTH2F, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}}}}, - {"jetTofBeta", "jetTofBeta", {HistType::kTH2F, {{nBinsPForBeta, 0, pMax}, {nBinsTofBeta, 0.4, 1.1}}}}, - {"jetpVsPtForPr", "jetpVsPtForPr", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetpVsPtForPi", "jetpVsPtPi", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPrPerpJet", "pVsPtForPrPerpJet", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPiPerpJet", "pVsPtPionPerpJet", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetDcaPr", "jetDcaPr", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetDcaPi", "jetDcaPi", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaPrPerpJet", "dcaPrPerpJet", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaPiPerpJet", "dcaPiPerpJet", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcTofPiRandCone", "tpcTofPiRandCone", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tpcTofPrRandCone", "tpcTofPrRandCone", {HistType::kTHnSparseD, {{nBinsPForCut, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPrRandCone", "pVsPtForPrRandCone", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"pVsPtForPiRandCone", "pVsPtPionRandCone", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaPrRandCone", "dcaPrRandCone", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaPiRandCone", "dcaPiRandCone", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"jetPt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, - {"jetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"jetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"area", "area", {HistType::kTH2F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}, {100, 0, 2}}}}, - {"rho", "rho", {HistType::kTH1F, {{120, 0, 300}}}}, - {"ptCorr", "Corrected jet pT; p_{T}^{corr} (GeV/c); Counts", {HistType::kTH1F, {{200, 0, 200}}}}, - {"ptCorrVsDistance", "ptcorr_vs_distance", {HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}}}, - {"jetDistanceVsTrackpt", "trackpt_vs_distance_injet", {HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}}}, - {"ptSum", "ptSum", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptSumBg1", "ptSumBg1", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptSumBg2", "ptSumBg2", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"event/vertexz", ";Vtx_{z} (cm);Entries", {HistType::kTH1F, {{100, -20, 20}}}}, - {"eventCounterJetShape", "eventCounterJetShape", {HistType::kTH1F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"eventCounterJet", "eventCounterJet", {HistType::kTH1F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"eventCounterInc", "eventCounterInc", {HistType::kTH1F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"eventCounterRandCone", "Number of Random Cones;Centrality (%);Count", {HistType::kTH1F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"eventCounterMc", "eventCounterMc", {HistType::kTH1F, {{nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptVsCentrality", "ptvscentrality", {HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}}}, - {"ptResolution", "ptResolution", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {100, -1.0, +1.0}}}}, - {"mcCentralityReco", "mcCentralityReco", {HistType::kTH1F, {{100, 0, 100}}}}, - {"mcCentralitySim", "mcCentralitySim", {HistType::kTH1F, {{100, 0, 100}}}}, - {"ptHistogramPion", "ptHistogramPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramKaon", "ptHistogramKaon", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramProton", "ptHistogramProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramPionTof", "ptHistogramPionTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramKaonTof", "ptHistogramKaonTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramProtonTof", "ptHistogramProtonTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaDecayPion", "dcaDecayPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaDecayProton", "dcaDecayProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaMaterialPion", "dcaMaterialPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"dcaMaterialProton", "dcaMaterialProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptGeneratedPion", "ptGeneratedPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptGeneratedKaon", "ptGeneratedKaon", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptGeneratedProton", "ptGeneratedProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}}}; + HistogramRegistry registry{"registry"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -202,6 +124,145 @@ struct JetShapeTask { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + + // Histograms definition + registry.add("tpcTofPi", "tpcTofPi", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPr", "tpcTofPr", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcPi", "tpcPi", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("tofPi", "tofPi", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("tpcPr", "tpcPr", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("tofPr", "tofPr", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("tpcDedx", "tpcDedx", HistType::kTHnSparseD, {{nBinsPForDedx.value, 0, pMax.value}, {nBinsTpcDedx.value, 0, 1000}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tofBeta", "tofBeta", HistType::kTHnSparseD, {{nBinsPForBeta.value, 0, pMax.value}, {nBinsTofBeta.value, 0.4, 1.1}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPr", "pVsPtForPr", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPi", "pVsPtPi", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("trackPhi", "trackPhi", HistType::kTH1F, {{80, -1, 7}}); + registry.add("trackEta", "trackEta", HistType::kTH1F, {{100, -1, 1}}); + registry.add("trackTpcNClsCrossedRows", "trackTpcNClsCrossedRows", HistType::kTH1F, {{50, 0, 200}}); + registry.add("trackDcaXY", "trackDcaXY", HistType::kTH1F, {{40, -10, 10}}); + registry.add("trackItsChi2NCl", "trackItsChi2NCl", HistType::kTH1F, {{60, 0, 30}}); + registry.add("trackTpcChi2NCl", "trackTpcChi2NCl", HistType::kTH1F, {{100, 0, 50}}); + registry.add("trackTpcNClsFound", "trackTpcNClsFound", HistType::kTH1F, {{100, 0, 200}}); + registry.add("trackItsNCls", "trackItsNCls", HistType::kTH1F, {{10, 0, 10}}); + + registry.add("jetTpcTofPi", "jetTpcTofPi", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetTpcTofPr", "jetTpcTofPr", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPiPerpJet", "tpcTofPiPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPrPerpJet", "tpcTofPrPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("jetTpcPi", "jetTpcPi", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("jetTofPi", "jetTofPi", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("jetTpcPr", "jetTpcPr", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + registry.add("jetTofPr", "jetTofPr", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); + + registry.add("jetTpcDedx", "jetTpcDedx", HistType::kTHnSparseD, {{nBinsPForDedx.value, 0, pMax.value}, {nBinsTpcDedx.value, 0, 1000}, {nBinsDistance.value, 0, distanceMax.value}}); + registry.add("tpcDedxPerpJet", "tpcDedxPerpJet", HistType::kTH2F, {{nBinsPForDedx.value, 0, pMax.value}, {nBinsTpcDedx.value, 0, 1000}}); + registry.add("jetTofBeta", "jetTofBeta", HistType::kTH2F, {{nBinsPForBeta.value, 0, pMax.value}, {nBinsTofBeta.value, 0.4, 1.1}}); + + registry.add("jetpVsPtForPr", "jetpVsPtForPr", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetpVsPtForPi", "jetpVsPtPi", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPrPerpJet", "pVsPtForPrPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPiPerpJet", "pVsPtPionPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("jetDcaPr", "jetDcaPr", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetDcaPi", "jetDcaPi", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrPerpJet", "dcaPrPerpJet", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPiPerpJet", "dcaPiPerpJet", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("tpcTofPiRandCone", "tpcTofPiRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPrRandCone", "tpcTofPrRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPrRandCone", "pVsPtForPrRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPiRandCone", "pVsPtPionRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrRandCone", "dcaPrRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPiRandCone", "dcaPiRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("jetPt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", HistType::kTH2F, {{200, 0., 200.}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetPtMc", "MC jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", HistType::kTH2F, {{200, 0., 200.}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetEta", "jet #eta;#eta_{jet};entries", HistType::kTH1F, {{100, -1.0, 1.0}}); + registry.add("jetPhi", "jet #phi;#phi_{jet};entries", HistType::kTH1F, {{80, -1.0, 7.}}); + registry.add("area", "area", HistType::kTH2F, {{100, 0, 2}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("rho", "rho", HistType::kTH2F, {{120, 0, 300}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptCorr", "Corrected jet pT; p_{T}^{corr} (GeV/c); Counts", HistType::kTH1F, {{200, 0, 200}}); + registry.add("ptCorrVsDistance", "ptcorr_vs_distance", HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}); + registry.add("jetDistanceVsTrackpt", "trackpt_vs_distance_injet", HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}); + registry.add("ptSum", "ptSum", HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc.value, 0, jetShapeFuncMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptSumBg1", "ptSumBg1", HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc.value, 0, jetShapeFuncMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptSumBg2", "ptSumBg2", HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc.value, 0, jetShapeFuncMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("event/vertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); + registry.add("eventCounterJetShape", "eventCounterJetShape", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("eventCounterJet", "eventCounterJet", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("eventCounterInc", "eventCounterInc", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("eventCounterRandCone", "Number of Random Cones;Centrality (%);Count", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("eventCounterMc", "eventCounterMc", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + registry.add("ptVsCentrality", "ptvscentrality", HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}); + registry.add("ptResolution", "ptResolution", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {100, -1.0, +1.0}}); + registry.add("mcCentralityReco", "mcCentralityReco", HistType::kTH1F, {{100, 0, 100}}); + + // MC Efficiency Denominators + // Jet (In-cone) + registry.add("ptGenPi", "ptGenPi", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenKa", "ptGenKa", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenPr", "ptGenPr", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + // Perp Cone + registry.add("ptGenPiPerp", "ptGenPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenKaPerp", "ptGenKaPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenPrPerp", "ptGenPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + // Inclusive (No JetPt axis) + registry.add("ptGenPiInc", "ptGenPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenKaInc", "ptGenKaInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("ptGenPrInc", "ptGenPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // MC Efficiency Numerators + // Inclusive + registry.add("effNumTpcPiInc", "effNumTpcPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcKaInc", "effNumTpcKaInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcPrInc", "effNumTpcPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPiInc", "effNumTofPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofKaInc", "effNumTofKaInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPrInc", "effNumTofPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // Jet (In-cone) + registry.add("effNumTpcPiJet", "effNumTpcPiJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcKaJet", "effNumTpcKaJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcPrJet", "effNumTpcPrJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPiJet", "effNumTofPiJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofKaJet", "effNumTofKaJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPrJet", "effNumTofPrJet", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // Perp Cone + registry.add("effNumTpcPiPerp", "effNumTpcPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcKaPerp", "effNumTpcKaPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTpcPrPerp", "effNumTpcPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPiPerp", "effNumTofPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofKaPerp", "effNumTofKaPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("effNumTofPrPerp", "effNumTofPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // DCA Templates for Primary Fraction + // Jet (In-cone) + registry.add("dcaPrimPi", "dcaPrimPi", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPi", "dcaDecayPi", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPi", "dcaMatPi", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrimPr", "dcaPrimPr", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPr", "dcaDecayPr", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPr", "dcaMatPr", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // Perp Cone + registry.add("dcaPrimPiPerp", "dcaPrimPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPiPerp", "dcaDecayPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPiPerp", "dcaMatPiPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrimPrPerp", "dcaPrimPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPrPerp", "dcaDecayPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPrPerp", "dcaMatPrPerp", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // Inclusive + registry.add("dcaPrimPiInc", "dcaPrimPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPiInc", "dcaDecayPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPiInc", "dcaMatPiInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrimPrInc", "dcaPrimPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaDecayPrInc", "dcaDecayPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaMatPrInc", "dcaMatPrInc", HistType::kTHnSparseD, {{nBinsPt.value, 0, ptMax.value}, {nBinsDcaxyForMc.value, dcaxyMin.value, dcaxyMax.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); } template @@ -249,13 +310,13 @@ struct JetShapeTask { return true; } - Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == - nround(jetR.node() * 100.0f); + Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); Filter jetCollisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; Filter collisionFilter = nabs(aod::collision::posZ) < vertexZCut; Filter mcCollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; using FullTrackInfo = soa::Join; + using FullTrackInfoMC = soa::Join; void processJetShape(soa::Filtered>::iterator const& collision, aod::JetTracks const& tracks, soa::Join const& jets) { @@ -373,8 +434,6 @@ struct JetShapeTask { for (size_t i = 0; i < cachedJets.size(); ++i) { const auto& jet = cachedJets[i]; - registry.fill(HIST("rho"), rho); - registry.fill(HIST("jetPt"), jet.pt); registry.fill(HIST("ptCorr"), jet.ptCorr); for (size_t k = 0; k < nBins; k++) { @@ -434,7 +493,9 @@ struct JetShapeTask { registry.fill(HIST("jetEta"), jet.eta()); registry.fill(HIST("jetPhi"), jet.phi()); - registry.fill(HIST("area"), centrality, jet.area()); + registry.fill(HIST("area"), jet.area(), centrality); + registry.fill(HIST("rho"), rho, centrality); + registry.fill(HIST("jetPt"), jet.pt(), centrality); cachedJets.push_back( {jet.pt(), jet.eta(), jet.phi(), ptCorr, phiBg1, phiBg2}); @@ -533,9 +594,6 @@ struct JetShapeTask { bool isTpcPiRange = (tpcPi > tpcNSigmaPiMin && tpcPi < tpcNSigmaPiMax); bool isTpcPrRange = (tpcPr > tpcNSigmaPrMin && tpcPr < tpcNSigmaPrMax); - float nSigmaSqPr = tpcPr * tpcPr + tofPr * tofPr; - float nSigmaSqPi = tpcPi * tpcPi + tofPi * tofPi; - for (const auto& jet : cachedJets) { float dEta = trkEta - jet.eta; @@ -551,31 +609,38 @@ struct JetShapeTask { float distBg1 = std::sqrt(dEta * dEta + deltaPhiBg1 * deltaPhiBg1); float distBg2 = std::sqrt(dEta * dEta + deltaPhiBg2 * deltaPhiBg2); + float distBg = -1.0f; + if (distBg1 < distanceMax) { + distBg = distBg1; + } else if (distBg2 < distanceMax) { + distBg = distBg2; + } + // --- Background Fill --- - if (distBg1 < distanceMax || distBg2 < distanceMax) { + if (distBg >= 0.0f) { registry.fill(HIST("tpcDedxPerpJet"), trkP, tpcSig); // dcaXY if (track.hasTOF()) { - if (nSigmaSqPr < nSigmaMaxForDcaxy) { - registry.fill(HIST("dcaPrPerpJet"), trkPt, track.dcaXY(), jet.ptCorr, centrality); + if (hasTofPr && isTpcPrRange) { + registry.fill(HIST("dcaPrPerpJet"), trkPt, track.dcaXY(), distBg, jet.ptCorr, centrality); } - if (nSigmaSqPi < nSigmaMaxForDcaxy) { - registry.fill(HIST("dcaPiPerpJet"), trkPt, track.dcaXY(), jet.ptCorr, centrality); + if (hasTofPi && isTpcPiRange) { + registry.fill(HIST("dcaPiPerpJet"), trkPt, track.dcaXY(), distBg, jet.ptCorr, centrality); } } if (hasTofPi) { - registry.fill(HIST("tpcTofPiPerpJet"), trkP, tpcPi, jet.ptCorr, centrality); + registry.fill(HIST("tpcTofPiPerpJet"), trkP, tpcPi, distBg, jet.ptCorr, centrality); if (isTpcPiRange) { - registry.fill(HIST("pVsPtForPiPerpJet"), trkP, trkPt, jet.ptCorr, centrality); + registry.fill(HIST("pVsPtForPiPerpJet"), trkP, trkPt, distBg, jet.ptCorr, centrality); } } if (hasTofPr) { - registry.fill(HIST("tpcTofPrPerpJet"), trkP, tpcPr, jet.ptCorr, centrality); + registry.fill(HIST("tpcTofPrPerpJet"), trkP, tpcPr, distBg, jet.ptCorr, centrality); if (isTpcPrRange) { - registry.fill(HIST("pVsPtForPrPerpJet"), trkP, trkPt, jet.ptCorr, centrality); + registry.fill(HIST("pVsPtForPrPerpJet"), trkP, trkPt, distBg, jet.ptCorr, centrality); } } } @@ -593,10 +658,10 @@ struct JetShapeTask { // dcaXY if (track.hasTOF()) { - if (nSigmaSqPr < nSigmaMaxForDcaxy) { + if (hasTofPr && isTpcPrRange) { registry.fill(HIST("dcaPrRandCone"), trkPt, track.dcaXY(), leadJet.ptCorr, centrality); } - if (nSigmaSqPi < nSigmaMaxForDcaxy) { + if (hasTofPi && isTpcPiRange) { registry.fill(HIST("dcaPiRandCone"), trkPt, track.dcaXY(), leadJet.ptCorr, centrality); } } @@ -623,11 +688,11 @@ struct JetShapeTask { // dcaXY if (track.hasTOF()) { - if (nSigmaSqPr < nSigmaMaxForDcaxy) { + if (hasTofPr && isTpcPrRange) { registry.fill(HIST("jetDcaPr"), trkPt, track.dcaXY(), distance, jet.ptCorr, centrality); } - if (nSigmaSqPi < nSigmaMaxForDcaxy) { + if (hasTofPi && isTpcPiRange) { registry.fill(HIST("jetDcaPi"), trkPt, track.dcaXY(), distance, jet.ptCorr, centrality); } } @@ -715,45 +780,128 @@ struct JetShapeTask { } PROCESS_SWITCH(JetShapeTask, processInclusiveProductionRatio, "inclusive Production ratio", false); - void processReco(soa::Filtered>::iterator const& collision, soa::Join const& tracks, aod::ChargedMCDetectorLevelJets const& jets, aod::McParticles const& mcParticles) + void processEfficiencyAndPurity( + soa::Filtered>::iterator const& collision, + soa::Join const& jetTracks, + FullTrackInfoMC const&, + soa::Filtered> const& mcdJets, + aod::ChargedMCParticleLevelJets const& mcpJets, + aod::McParticles const& mcParticles) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) return; - } - (void)mcParticles; + (void)mcpJets; float centrality = collision.centFT0M(); float rho = collision.rho(); + float distMax = distanceMax; + float maxR2 = distMax * distMax; - registry.fill(HIST("eventCounterMc"), 0.5); - registry.fill(HIST("mcCentralityReco"), centrality); + registry.fill(HIST("eventCounterMc"), centrality); - struct CachedJet { - float pt; - float eta; - float phi; - float ptCorr; + // jet matching + struct MatchedJet { + float detPtCorr, partEta, partPhi, partPhiBg1, partPhiBg2; }; - std::vector cachedJets; - cachedJets.reserve(jets.size()); + std::vector validJets; + validJets.reserve(mcdJets.size()); - for (const auto& jet : jets) { - float mcdPtCorr = jet.pt() - rho * jet.area(); - cachedJets.push_back({jet.pt(), jet.eta(), jet.phi(), mcdPtCorr}); - registry.fill(HIST("jetPt"), jet.pt()); + for (auto const& detJet : mcdJets) { + auto matchedIndices = detJet.matchedJetGeo(); + + if (matchedIndices.size() > 0) { + auto const& partJet = matchedIndices[0]; + + float detPtCorr = detJet.pt() - rho * detJet.area(); + float partPhi = partJet.phi(); + float phiBg1 = RecoDecay::constrainAngle(partPhi + o2::constants::math::PIHalf); + float phiBg2 = RecoDecay::constrainAngle(partPhi - o2::constants::math::PIHalf); + + validJets.push_back({detPtCorr, partJet.eta(), partPhi, phiBg1, phiBg2}); + registry.fill(HIST("jetPtMc"), detJet.pt(), centrality); + } } - // reco track loop - for (const auto& track : tracks) { + // Denominator: True Primary Particles + for (const auto& mcParticle : mcParticles) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + if (mcParticle.mcCollisionId() != collision.globalIndex()) continue; + + if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.y()) > mcRapidityMax) + continue; + + int absPdg = std::abs(mcParticle.pdgCode()); + bool isPi = (absPdg == PDG_t::kPiPlus); + bool isKa = (absPdg == PDG_t::kKPlus); + bool isPr = (absPdg == PDG_t::kProton); + if (!isPi && !isKa && !isPr) + continue; + + float mcPt = mcParticle.pt(); + + if (isPi) + registry.fill(HIST("ptGenPiInc"), mcPt, centrality); + else if (isKa) + registry.fill(HIST("ptGenKaInc"), mcPt, centrality); + else if (isPr) + registry.fill(HIST("ptGenPrInc"), mcPt, centrality); + + for (const auto& jet : validJets) { + float dEta = mcParticle.eta() - jet.partEta; + + // Jet In-cone + float dPhiJet = std::abs(mcParticle.phi() - jet.partPhi); + if (dPhiJet > o2::constants::math::PI) + dPhiJet = o2::constants::math::TwoPI - dPhiJet; + + float distJetGen = std::sqrt(dEta * dEta + dPhiJet * dPhiJet); + + if ((dEta * dEta + dPhiJet * dPhiJet) < maxR2) { + if (isPi) + registry.fill(HIST("ptGenPi"), mcPt, distJetGen, jet.detPtCorr, centrality); + else if (isKa) + registry.fill(HIST("ptGenKa"), mcPt, distJetGen, jet.detPtCorr, centrality); + else if (isPr) + registry.fill(HIST("ptGenPr"), mcPt, distJetGen, jet.detPtCorr, centrality); + } + + // Perp Cone + float dPhiBg1 = std::abs(mcParticle.phi() - jet.partPhiBg1); + if (dPhiBg1 > o2::constants::math::PI) + dPhiBg1 = o2::constants::math::TwoPI - dPhiBg1; + float dPhiBg2 = std::abs(mcParticle.phi() - jet.partPhiBg2); + if (dPhiBg2 > o2::constants::math::PI) + dPhiBg2 = o2::constants::math::TwoPI - dPhiBg2; + + float distBg1Sq = dEta * dEta + dPhiBg1 * dPhiBg1; + float distBg2Sq = dEta * dEta + dPhiBg2 * dPhiBg2; + + float distBgGen = -1.0f; + if (distBg1Sq < maxR2) + distBgGen = std::sqrt(distBg1Sq); + else if (distBg2Sq < maxR2) + distBgGen = std::sqrt(distBg2Sq); + + if (distBgGen >= 0.0f) { + if (isPi) + registry.fill(HIST("ptGenPiPerp"), mcPt, distBgGen, jet.detPtCorr, centrality); + else if (isKa) + registry.fill(HIST("ptGenKaPerp"), mcPt, distBgGen, jet.detPtCorr, centrality); + else if (isPr) + registry.fill(HIST("ptGenPrPerp"), mcPt, distBgGen, jet.detPtCorr, centrality); + } } + } - if (!track.has_mcParticle()) + // Numerator + for (const auto& jetTrack : jetTracks) { + if (!jetderiveddatautilities::selectTrack(jetTrack, trackSelection)) continue; + auto track = jetTrack.track_as(); + if (std::abs(track.eta()) > etaTrUp) continue; if (track.tpcNClsCrossedRows() < nclcrossTpcMin) @@ -769,157 +917,186 @@ struct JetShapeTask { if (track.itsNCls() < nclItsMin) continue; - auto mcParticle = track.mcParticle(); - registry.fill(HIST("ptResolution"), track.pt(), track.pt() - mcParticle.pt()); - - if (std::fabs(mcParticle.y()) >= mcRapidityMax) + if (!track.has_mcParticle()) continue; + auto mcParticle = track.mcParticle(); - const int producedByDecay = 4; - - bool isPrimary = mcParticle.isPhysicalPrimary(); - bool isSecondDecay = !isPrimary && (mcParticle.getProcess() == producedByDecay); - bool isSecondMaterial = !isPrimary && !isSecondDecay; - - int pdg = std::abs(mcParticle.pdgCode()); - bool isPion = (pdg == PDG_t::kPiPlus); - bool isKaon = (pdg == PDG_t::kKPlus); - bool isProton = (pdg == PDG_t::kProton); - - if (!isPion && !isKaon && !isProton) + if (mcParticle.mcCollisionId() != collision.globalIndex()) continue; - bool hasTof = track.hasTOF(); - - for (const auto& jet : cachedJets) { - - float dEta = std::abs(track.eta() - jet.eta); - if (dEta > distanceMax) - continue; - - float dPhi = std::abs(track.phi() - jet.phi); - if (dPhi > o2::constants::math::PI) { - dPhi = o2::constants::math::TwoPI - dPhi; - } - - if (dPhi > distanceMax) - continue; - - float deltaR = std::sqrt(dEta * dEta + dPhi * dPhi); - if (deltaR > distanceMax) - continue; - - if (isPrimary) { - // Tracking - if (isPion) - registry.fill(HIST("ptHistogramPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - else if (isKaon) - registry.fill(HIST("ptHistogramKaon"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - else if (isProton) - registry.fill(HIST("ptHistogramProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - - // TOF matched - if (hasTof) { - if (isPion) - registry.fill(HIST("ptHistogramPionTof"), mcParticle.pt(), jet.ptCorr, centrality); - else if (isKaon) - registry.fill(HIST("ptHistogramKaonTof"), mcParticle.pt(), jet.ptCorr, centrality); - else if (isProton) - registry.fill(HIST("ptHistogramProtonTof"), mcParticle.pt(), jet.ptCorr, centrality); - } - } else { // Secondary - if (isSecondDecay) { - // from Decay - if (isPion) - registry.fill(HIST("dcaDecayPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - else if (isProton) - registry.fill(HIST("dcaDecayProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - } else if (isSecondMaterial) { - // from Material - if (isPion) - registry.fill(HIST("dcaMaterialPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - else if (isProton) - registry.fill(HIST("dcaMaterialProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); - } - } - } - } - } - PROCESS_SWITCH(JetShapeTask, processReco, "process reconstructed simulation information", true); - - void processSim(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::ChargedMCParticleLevelJets const& mcpjets, aod::JetParticles const& mcParticles) - { - if (std::abs(mcCollision.posZ()) > vertexZCut) { - return; - } - - if (collisions.size() == 0) { - return; - } - - // --- centrality --- - float centrality = collisions.begin().centFT0M(); - registry.fill(HIST("mcCentralitySim"), centrality); - const float maxR2 = distanceMax * distanceMax; - - // --- loop over MC particles only once --- - for (const auto& mcParticle : mcParticles) { - - // --- early cuts on particle --- - if (!mcParticle.isPhysicalPrimary()) { - continue; - } + registry.fill(HIST("ptResolution"), track.pt(), track.pt() - mcParticle.pt()); - if (std::abs(mcParticle.y()) > mcRapidityMax) { + if (std::abs(mcParticle.y()) >= mcRapidityMax) continue; - } int absPdg = std::abs(mcParticle.pdgCode()); - if (absPdg != PDG_t::kPiPlus && - absPdg != PDG_t::kKPlus && - absPdg != PDG_t::kProton) { + bool isTruePi = (absPdg == PDG_t::kPiPlus); + bool isTrueKa = (absPdg == PDG_t::kKPlus); + bool isTruePr = (absPdg == PDG_t::kProton); + if (!isTruePi && !isTrueKa && !isTruePr) continue; - } - - const float partPt = mcParticle.pt(); - const float partEta = mcParticle.eta(); - const float partPhi = mcParticle.phi(); - // --- loop over jets --- - for (const auto& mcpjet : mcpjets) { + const int producedByDecay = 4; + bool isPrimary = mcParticle.isPhysicalPrimary(); + bool isDecay = !isPrimary && (mcParticle.getProcess() == producedByDecay); + bool isMaterial = !isPrimary && !isDecay; - // --- delta eta cut first --- - float dEta = partEta - mcpjet.eta(); - if (std::abs(dEta) > distanceMax) { - continue; - } + float mcPt = mcParticle.pt(); + float recoPt = track.pt(); + float dcaXy = track.dcaXY(); + bool hasTof = track.hasTOF(); - // --- delta phi --- - float dPhi = std::abs(partPhi - mcpjet.phi()); - if (dPhi > o2::constants::math::PI) { - dPhi = o2::constants::math::TwoPI - dPhi; - } + // PID flag + // TPC nsigma + bool passTpcPiOnly = (track.tpcNSigmaPi() > tpcNSigmaPiMin && track.tpcNSigmaPi() < tpcNSigmaPiMax); + bool passTpcPrOnly = (track.tpcNSigmaPr() > tpcNSigmaPrMin && track.tpcNSigmaPr() < tpcNSigmaPrMax); + + // TPC + TOF + bool isRecoPi = passTpcPiOnly && hasTof && (std::abs(track.tofNSigmaPi()) < nSigmaTofCut); + bool isRecoPr = passTpcPrOnly && hasTof && (std::abs(track.tofNSigmaPr()) < nSigmaTofCut); + + if (isPrimary) { + // Inclusive + // TPC Efficiency + if (isTruePi) + registry.fill(HIST("effNumTpcPiInc"), mcPt, centrality); + if (isTrueKa) + registry.fill(HIST("effNumTpcKaInc"), mcPt, centrality); + if (isTruePr) + registry.fill(HIST("effNumTpcPrInc"), mcPt, centrality); + + // TOF Matching Efficiency + if (isTruePi && hasTof) + registry.fill(HIST("effNumTofPiInc"), mcPt, centrality); + if (isTrueKa && hasTof) + registry.fill(HIST("effNumTofKaInc"), mcPt, centrality); + if (isTruePr && hasTof) + registry.fill(HIST("effNumTofPrInc"), mcPt, centrality); + + // Purity DCA + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaPrimPiInc"), recoPt, dcaXy, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaPrimPrInc"), recoPt, dcaXy, centrality); + } else if (isDecay) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaDecayPiInc"), recoPt, dcaXy, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaDecayPrInc"), recoPt, dcaXy, centrality); + } else if (isMaterial) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaMatPiInc"), recoPt, dcaXy, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaMatPrInc"), recoPt, dcaXy, centrality); + } - // --- delta R^2 --- - float dR2 = dEta * dEta + dPhi * dPhi; - if (dR2 > maxR2) { - continue; + for (const auto& jet : validJets) { + float dEta = mcParticle.eta() - jet.partEta; + + // --- Jet In-cone distance check --- + float dPhiJet = std::abs(mcParticle.phi() - jet.partPhi); + if (dPhiJet > o2::constants::math::PI) + dPhiJet = o2::constants::math::TwoPI - dPhiJet; + + float distJetReco = std::sqrt(dEta * dEta + dPhiJet * dPhiJet); + bool inJet = (distJetReco < distanceMax); + + // --- Perp Cone distance check --- + float dPhiBg1 = std::abs(mcParticle.phi() - jet.partPhiBg1); + if (dPhiBg1 > o2::constants::math::PI) + dPhiBg1 = o2::constants::math::TwoPI - dPhiBg1; + float dPhiBg2 = std::abs(mcParticle.phi() - jet.partPhiBg2); + if (dPhiBg2 > o2::constants::math::PI) + dPhiBg2 = o2::constants::math::TwoPI - dPhiBg2; + + float distBg1Sq = dEta * dEta + dPhiBg1 * dPhiBg1; + float distBg2Sq = dEta * dEta + dPhiBg2 * dPhiBg2; + + float distBgReco = -1.0f; + if (distBg1Sq < maxR2) + distBgReco = std::sqrt(distBg1Sq); + else if (distBg2Sq < maxR2) + distBgReco = std::sqrt(distBg2Sq); + + bool inPerp = (distBgReco >= 0.0f); + + if (inJet) { + if (isPrimary) { + // --- Jet In-cone 分子 --- + // TPC Efficiency + if (isTruePi) + registry.fill(HIST("effNumTpcPiJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + if (isTrueKa) + registry.fill(HIST("effNumTpcKaJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + if (isTruePr) + registry.fill(HIST("effNumTpcPrJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + + // TOF Matching Efficiency + if (isTruePi && hasTof) + registry.fill(HIST("effNumTofPiJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + if (isTrueKa && hasTof) + registry.fill(HIST("effNumTofKaJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + if (isTruePr && hasTof) + registry.fill(HIST("effNumTofPrJet"), mcPt, distJetReco, jet.detPtCorr, centrality); + + // Purity DCA + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaPrimPi"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaPrimPr"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + } else if (isDecay) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaDecayPi"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaDecayPr"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + } else if (isMaterial) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaMatPi"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaMatPr"), recoPt, dcaXy, distJetReco, jet.detPtCorr, centrality); + } } - const float jetPt = mcpjet.pt(); - - // --- histogram fill --- - if (absPdg == PDG_t::kPiPlus) { - registry.fill(HIST("ptGeneratedPion"), partPt, jetPt, centrality); - } else if (absPdg == PDG_t::kKPlus) { - registry.fill(HIST("ptGeneratedKaon"), partPt, jetPt, centrality); - } else if (absPdg == PDG_t::kProton) { - registry.fill(HIST("ptGeneratedProton"), partPt, jetPt, centrality); + if (inPerp) { + if (isPrimary) { + // Perp Cone + // TPC Efficiency + if (isTruePi) + registry.fill(HIST("effNumTpcPiPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + if (isTrueKa) + registry.fill(HIST("effNumTpcKaPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + if (isTruePr) + registry.fill(HIST("effNumTpcPrPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + + // TOF Matching Efficiency + if (isTruePi && hasTof) + registry.fill(HIST("effNumTofPiPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + if (isTrueKa && hasTof) + registry.fill(HIST("effNumTofKaPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + if (isTruePr && hasTof) + registry.fill(HIST("effNumTofPrPerp"), mcPt, distBgReco, jet.detPtCorr, centrality); + + // Purity DCA + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaPrimPiPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaPrimPrPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + } else if (isDecay) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaDecayPiPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaDecayPrPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + } else if (isMaterial) { + if (isRecoPi && isTruePi) + registry.fill(HIST("dcaMatPiPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + if (isRecoPr && isTruePr) + registry.fill(HIST("dcaMatPrPerp"), recoPt, dcaXy, distBgReco, jet.detPtCorr, centrality); + } } } } } - PROCESS_SWITCH(JetShapeTask, processSim, "process pure simulation information", true); + PROCESS_SWITCH(JetShapeTask, processEfficiencyAndPurity, "process MC information for Efficiency and Purity", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From bb08a2e021f17f0c53ae1614353929755ce8d9db Mon Sep 17 00:00:00 2001 From: sejeong8 Date: Sat, 16 May 2026 19:37:03 +0900 Subject: [PATCH 191/449] [PWGHF] taskSingleElectron: Fix names and descriptions of configurables (#16210) --- PWGHF/HFL/Tasks/taskSingleElectron.cxx | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/PWGHF/HFL/Tasks/taskSingleElectron.cxx b/PWGHF/HFL/Tasks/taskSingleElectron.cxx index c519765e688..f50b521c1db 100644 --- a/PWGHF/HFL/Tasks/taskSingleElectron.cxx +++ b/PWGHF/HFL/Tasks/taskSingleElectron.cxx @@ -81,16 +81,16 @@ struct HfTaskSingleElectron { Configurable ptTrackMax{"ptTrackMax", 10., "max pt cut"}; Configurable ptTrackMin{"ptTrackMin", 0.5, "min pt cut"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "eta cut"}; - Configurable nCrossedRowTPCMin{"nCrossedRowTPCMin", 70, "max of TPC n cluster crossed rows"}; + Configurable nCrossedRowTpcMin{"nCrossedRowTpcMin", 70, "min # of TPC n cluster crossed rows"}; Configurable nClsFoundOverFindableTpcMin{"nClsFoundOverFindableTpcMin", 0.8, "min # of TPC found/findable clusters"}; - Configurable Chi2pernClTpcMax{"Chi2pernClTpcMax", 4., "min # of tpc chi2 per clusters"}; - Configurable ClsIBItsMin{"ClsIBItsMin", 3, "min # of its clusters in IB"}; - Configurable Chi2pernClItsMax{"Chi2pernClItsMax", 6., "min # of tpc chi2 per clusters"}; + Configurable chi2PerNClTpcMax{"chi2PerNClTpcMax", 4., "max # of tpc chi2 per clusters"}; + Configurable clsIbItsMin{"clsIbItsMin", 3, "min # of its clusters in IB"}; + Configurable chi2PerNClItsMax{"chi2PerNClItsMax", 6., "min # of its chi2 per clusters"}; Configurable dcaxyMax{"dcaxyMax", 1., "max of track dca in xy"}; Configurable dcazMax{"dcazMax", 2., "max of track dca in z"}; Configurable nSigmaTofMax{"nSigmaTofMax", 3., "max of tof nsigma"}; Configurable nSigmaTpcMin{"nSigmaTpcMin", -1., "min of tpc nsigma"}; - Configurable nSigmaTPCMax{"nSigmaTPCMax", 3., "max of tpc nsigma"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 3., "max of tpc nsigma"}; Configurable nBinsP{"nBinsP", 1500, "number of bins of particle momentum"}; Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; @@ -139,7 +139,7 @@ struct HfTaskSingleElectron { histos.add("hNClsTpcTrack", "hNClsTpcTrack", kTH1D, {{200, 0, 200}}); histos.add("hNClsFoundFindableTpcTrack", "", kTH1D, {{10, 0, 1}}); histos.add("hChi2TpcTrack", "", kTH1D, {{100, 0, 10}}); - histos.add("hibClsItsTrack", "", kTH1D, {{10, 0, 10}}); + histos.add("hIbClsItsTrack", "", kTH1D, {{10, 0, 10}}); histos.add("hChi2ItsTrack", "", kTH1D, {{50, 0, 50}}); histos.add("hDcaXYTrack", "", kTH1D, {{600, -3, 3}}); histos.add("hDcaZTrack", "", kTH1D, {{600, -3, 3}}); @@ -147,16 +147,16 @@ struct HfTaskSingleElectron { // pid histos.add("hTofNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); histos.add("hTofNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("hTPCNSigP", "", kTH2D, {{axisP}, {axisNsig}}); - histos.add("hTPCNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("hTPCNSigPAfterTofCut", "", kTH2D, {{axisP}, {axisNsig}}); - histos.add("hTPCNSigPtAfterTofCut", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("hTPCNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTpcNSigP", "", kTH2D, {{axisP}, {axisNsig}}); + histos.add("hTpcNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTpcNSigPAfterTofCut", "", kTH2D, {{axisP}, {axisNsig}}); + histos.add("hTpcNSigPtAfterTofCut", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTpcNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); // track impact parameter histos.add("hDcaTrack", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); histos.add("hDcaBeauty", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); - histos.add("hDcaChram", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaCharm", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); histos.add("hDcaDalitz", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); histos.add("hDcaConv", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); histos.add("hDcaHadron", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); @@ -178,7 +178,7 @@ struct HfTaskSingleElectron { return false; } - if (track.tpcNClsCrossedRows() < nCrossedRowTPCMin) { + if (track.tpcNClsCrossedRows() < nCrossedRowTpcMin) { return false; } @@ -186,15 +186,15 @@ struct HfTaskSingleElectron { return false; } - if (track.tpcChi2NCl() > Chi2pernClTpcMax) { + if (track.tpcChi2NCl() > chi2PerNClTpcMax) { return false; } - if (!(track.itsNClsInnerBarrel() == ClsIBItsMin)) { + if (!(track.itsNClsInnerBarrel() == clsIbItsMin)) { return false; } - if (track.itsChi2NCl() > Chi2pernClItsMax) { + if (track.itsChi2NCl() > chi2PerNClItsMax) { return false; } @@ -450,23 +450,23 @@ struct HfTaskSingleElectron { histos.fill(HIST("hNClsTpcTrack"), track.tpcNClsCrossedRows()); histos.fill(HIST("hNClsFoundFindableTpcTrack"), track.tpcCrossedRowsOverFindableCls()); histos.fill(HIST("hChi2TpcTrack"), track.tpcChi2NCl()); - histos.fill(HIST("hibClsItsTrack"), track.itsNClsInnerBarrel()); + histos.fill(HIST("hIbClsItsTrack"), track.itsNClsInnerBarrel()); histos.fill(HIST("hChi2ItsTrack"), track.itsChi2NCl()); histos.fill(HIST("hDcaXYTrack"), track.dcaXY()); histos.fill(HIST("hDcaZTrack"), track.dcaZ()); histos.fill(HIST("hTofNSigPt"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("hTPCNSigP"), track.p(), track.tpcNSigmaEl()); - histos.fill(HIST("hTPCNSigPt"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigP"), track.p(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPt"), track.pt(), track.tpcNSigmaEl()); if (std::abs(track.tofNSigmaEl()) > nSigmaTofMax) { continue; } histos.fill(HIST("hTofNSigPtQA"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("hTPCNSigPAfterTofCut"), track.p(), track.tpcNSigmaEl()); - histos.fill(HIST("hTPCNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPAfterTofCut"), track.p(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); - if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTPCMax) { + if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTpcMax) { continue; } @@ -475,7 +475,7 @@ struct HfTaskSingleElectron { histos.fill(HIST("hDcaHadron"), track.pt(), track.dcaXY()); } - histos.fill(HIST("hTPCNSigPtQA"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPtQA"), track.pt(), track.tpcNSigmaEl()); histos.fill(HIST("hDcaTrack"), track.pt(), track.dcaXY()); } @@ -511,12 +511,12 @@ struct HfTaskSingleElectron { histos.fill(HIST("hNClsTpcTrack"), track.tpcNClsCrossedRows()); histos.fill(HIST("hNClsFoundFindableTpcTrack"), track.tpcCrossedRowsOverFindableCls()); histos.fill(HIST("hChi2TpcTrack"), track.tpcChi2NCl()); - histos.fill(HIST("hibClsItsTrack"), track.itsNClsInnerBarrel()); + histos.fill(HIST("hIbClsItsTrack"), track.itsNClsInnerBarrel()); histos.fill(HIST("hDcaXYTrack"), track.dcaXY()); histos.fill(HIST("hDcaZTrack"), track.dcaZ()); histos.fill(HIST("hTofNSigPt"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("hTPCNSigPt"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPt"), track.pt(), track.tpcNSigmaEl()); int mpdg{}; // electron source pdg code double mpt{}; // electron source pt @@ -529,7 +529,7 @@ struct HfTaskSingleElectron { if (source == DirectCharm) { histos.fill(HIST("hPdgC"), mpdg); - histos.fill(HIST("hDcaChram"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaCharm"), track.pt(), track.dcaXY()); } if (source >= GammaPi0 && source <= GammaSigma) { @@ -549,12 +549,12 @@ struct HfTaskSingleElectron { continue; } histos.fill(HIST("hTofNSigPtQA"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("hTPCNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); - if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTPCMax) { + if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTpcMax) { continue; } - histos.fill(HIST("hTPCNSigPtQA"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTpcNSigPtQA"), track.pt(), track.tpcNSigmaEl()); histos.fill(HIST("hDcaTrack"), track.pt(), track.dcaXY()); } From 9700d3739cdd155bee6dcad42c293a1824783a5c Mon Sep 17 00:00:00 2001 From: Antonio Palasciano <52152842+apalasciano@users.noreply.github.com> Date: Sat, 16 May 2026 12:44:25 +0200 Subject: [PATCH 192/449] [PWGHF] add pT(p) axes to THnSparse in dataCreatorHiddenCharm (#16270) Co-authored-by: ALICE Action Bot --- .../TableProducer/dataCreatorHiddenCharmReduced.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx index 5d28bd3b4dc..f4284717c95 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx @@ -147,6 +147,7 @@ struct HfDataCreatorHiddenCharmReduced { if (config.fillHistograms) { const AxisSpec axisPt{360, 0., 36., "#it{p}_{T}^{proton} (GeV/#it{c})"}; + const AxisSpec axisPtEtaC{100, 0., 10., "#it{p}_{T}^{#eta_{c}} (GeV/#it{c})"}; const AxisSpec axisEta{100, -1., 1., "#eta"}; const AxisSpec axisDca{400, -2., 2., "DCA_{xy} to primary vertex (cm)"}; const AxisSpec axisNSigmaTPC{100, -5., 5., "n#sigma_{TPC}"}; @@ -169,10 +170,9 @@ struct HfDataCreatorHiddenCharmReduced { registry.add("hTpcChi2NCl", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); TpcChi2NCl", {HistType::kTH2D, {axisPt, {10, 0., 10, "TpcChi2NCl"}}}); registry.add("hItsNCls", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});ItsNCls", {HistType::kTH2D, {axisPt, {7, 0, 7, "ItsNCls"}}}); registry.add("hItsChi2NCl", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c}); ItsChi2NCl", {HistType::kTH2D, {axisPt, {10, 0., 10, "ItsChi2NCl"}}}); - registry.add("hInvMass", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});", {HistType::kTH2D, {axisPt, axisMass}}); - registry.add("hInvMassSparse", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});", {HistType::kTH2D, {axisPt, axisMass}}); + registry.add("hInvMass", "Invariant mass of selected protons pairs;#it{p}_{T}^{#eta_{c}} (GeV/#it{c});", {HistType::kTH2D, {axisPtEtaC, axisMass}}); registry.add("hDeDxTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});TPC dE/dx (a.u.)", {HistType::kTH2D, {axisPt, AxisSpec{100, 0., 200., "TPC dE/dx (a.u.)"}}}); - registry.add("hMassPtCutVars", "Charmonia candidates;#it{M} (p#overline{p}) (GeV/#it{c}^{2});#it{p}_{T}(cc) (GeV/#it{c}); n#sigma_{TPC}^{p1}; n#sigma_{TOF}^{p1}; dca_{xy}^{p1}; n#sigma_{TPC}^{p2}; n#sigma_{TOF}^{p2}; dca_{xy}^{p2}", {HistType::kTHnSparseF, {axisMass, axisPt, axisNSigmaTPC, axisNSigmaTOF, axisDca, axisNSigmaTPC, axisNSigmaTOF, axisDca}}); + registry.add("hMassPtCutVars", "Charmonia candidates;#it{M} (p#overline{p}) (GeV/#it{c}^{2});#it{p}_{T}(cc) (GeV/#it{c}); p_{T}^{p}; n#sigma_{TPC}^{p}; n#sigma_{TOF}^{p}; dca_{xy}^{p}; p_{T}^{#overline{p}}; n#sigma_{TPC}^{#overline{p}}; n#sigma_{TOF}^{#overline{p}}; dca_{xy}^{#overline{p}}", {HistType::kTHnSparseF, {axisMass, axisPtEtaC, axisPt, axisNSigmaTPC, axisNSigmaTOF, axisDca, axisPt, axisNSigmaTPC, axisNSigmaTOF, axisDca}}); } // init HF event selection helper @@ -340,6 +340,7 @@ struct HfDataCreatorHiddenCharmReduced { registry.fill(HIST("hTpcChi2NCl"), trk.pt(), trk.tpcChi2NCl()); registry.fill(HIST("hItsNCls"), trk.pt(), trk.itsNCls()); registry.fill(HIST("hItsChi2NCl"), trk.pt(), trk.itsChi2NCl()); + registry.fill(HIST("hDeDxTPCProton"), trk.pt(), trk.tpcSignal()); } } // skip event if not at least a pair of tracks skimming selection @@ -368,7 +369,11 @@ struct HfDataCreatorHiddenCharmReduced { float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); registry.fill(HIST("hInvMass"), ptEtac, invMass); if (config.fillSparses.value) { - registry.fill(HIST("hMassPtCutVars"), invMass, ptEtac, t1.tpcNSigmaPr(), t1.tofNSigmaPr(), t1.dcaXY(), t2.tpcNSigmaPr(), t2.tofNSigmaPr(), t2.dcaXY()); + if (t1.sign() > 0) { + registry.fill(HIST("hMassPtCutVars"), invMass, ptEtac, t1.pt(), t1.tpcNSigmaPr(), t1.tofNSigmaPr(), t1.dcaXY(), t2.pt(), t2.tpcNSigmaPr(), t2.tofNSigmaPr(), t2.dcaXY()); + } else { + registry.fill(HIST("hMassPtCutVars"), invMass, ptEtac, t2.pt(), t2.tpcNSigmaPr(), t2.tofNSigmaPr(), t2.dcaXY(), t1.pt(), t1.tpcNSigmaPr(), t1.tofNSigmaPr(), t1.dcaXY()); + } } } } From 9b1d9c71657bb2f391c9f49e0bb7e87451417852 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 16 May 2026 18:21:28 +0200 Subject: [PATCH 193/449] [Common] Add extra debug printouts for QA (#16272) Co-authored-by: ALICE Builder --- Common/Tasks/centralityStudypp.cxx | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index ce1b1afb89e..20aa28e585a 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -208,21 +208,38 @@ struct centralityStudypp { } if (doCentralityQA.value) { - // acquire vertex-Z equalization histograms if requested - LOGF(info, "Acquiring vertex-Z profiles for run %i", mRunNumber); + LOGF(info, "Acquiring centrality calibration for run %i", mRunNumber); TList* hCentralityObjects = nullptr; hCentralityObjects = ccdb->getForRun(pathCentrality, mRunNumber); - hCentralityFV0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFV0")); - hCentralityFT0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0A")); - hCentralityFT0C = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0C")); - hCentralityFT0M = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0")); - hCentralityFDDM = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFDD")); - hCentralityNTPV = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNTracksPV")); - hCentralityNGlo = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNGlobal")); - hCentralityMFT = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqMFT")); + hCentralityFV0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFV0")); + hCentralityFT0A = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0A")); + hCentralityFT0C = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0C")); + hCentralityFT0M = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFT0")); + hCentralityFDDM = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqFDD")); + hCentralityNTPV = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNTracksPV")); + hCentralityNGlo = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqNGlobal")); + hCentralityMFT = dynamic_cast(hCentralityObjects->FindObject("hCalibZeqMFT")); // won't capture null pointers -> explicitly check for those when attempting to evaluate + auto reportSuccess = [](TH1* a, std::string name) { + if (!a) { + LOGF(info, "Calibration missing for %s", name); + } else { + LOGF(info, "Calibration loaded for %s", name); + } + }; + + reportSuccess(hCentralityFV0A, "FV0A"); + reportSuccess(hCentralityFT0A, "FT0A"); + reportSuccess(hCentralityFT0C, "FT0C"); + reportSuccess(hCentralityFT0M, "FT0M"); + reportSuccess(hCentralityFDDM, "FDDM"); + reportSuccess(hCentralityNTPV, "NTPV"); + reportSuccess(hCentralityNGlo, "NGlobals"); + reportSuccess(hCentralityMFT, "MFT"); + + LOGF(info, "Centrality calibration loading done."); } histPath = std::format("Run_{}/", mRunNumber); From 8ca7d14804b48311c970a85d6adf306c973ba48e Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 16 May 2026 23:41:56 +0200 Subject: [PATCH 194/449] [Common] Add run 3 hyperfine percentiling (#16275) Co-authored-by: ALICE Builder --- Common/Tasks/centralityStudypp.cxx | 17 +-- Common/Tools/Multiplicity/multCalibrator.cxx | 105 +++++++++++++++++-- Common/Tools/Multiplicity/multCalibrator.h | 2 + 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index 20aa28e585a..df4d2f9fbf4 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -263,6 +263,7 @@ struct centralityStudypp { histPointers.insert({histPath + "hFDDA_Collisions", histos.add((histPath + "hFDDA_Collisions").c_str(), "hFDDA_Collisions", {kTH1D, {{axisMultUltraFineFDDA}}})}); histPointers.insert({histPath + "hFDDC_Collisions", histos.add((histPath + "hFDDC_Collisions").c_str(), "hFDDC_Collisions", {kTH1D, {{axisMultUltraFineFDDC}}})}); + histPointers.insert({histPath + "hFDDM_Collisions", histos.add((histPath + "hFDDM_Collisions").c_str(), "hFDDM_Collisions", {kTH1D, {{axisMultUltraFineFDDC}}})}); histPointers.insert({histPath + "hFV0A_Collisions", histos.add((histPath + "hFV0A_Collisions").c_str(), "hFV0A_Collisions", {kTH1D, {{axisMultUltraFineFV0A}}})}); histPointers.insert({histPath + "hNGlobalTracks", histos.add((histPath + "hNGlobalTracks").c_str(), "hNGlobalTracks", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); @@ -276,6 +277,7 @@ struct centralityStudypp { histPointers.insert({histPath + "hFDDA_Collisions_Unequalized", histos.add((histPath + "hFDDA_Collisions_Unequalized").c_str(), "hFDDA_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFDDA}}})}); histPointers.insert({histPath + "hFDDC_Collisions_Unequalized", histos.add((histPath + "hFDDC_Collisions_Unequalized").c_str(), "hFDDC_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFDDC}}})}); + histPointers.insert({histPath + "hFDDM_Collisions_Unequalized", histos.add((histPath + "hFDDM_Collisions_Unequalized").c_str(), "hFDDM_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFDDC}}})}); histPointers.insert({histPath + "hFV0A_Collisions_Unequalized", histos.add((histPath + "hFV0A_Collisions_Unequalized").c_str(), "hFV0A_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFV0A}}})}); histPointers.insert({histPath + "hNGlobalTracks_Unequalized", histos.add((histPath + "hNGlobalTracks_Unequalized").c_str(), "hNGlobalTracks_Unequalized", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); @@ -456,13 +458,13 @@ struct centralityStudypp { getHist(TH1, histPath + "hCollisionSelection")->Fill(11); // if we got here, we also finally fill the FT0C histogram, please - histos.fill(HIST("hNPVContributors"), collision.multNTracksPV()); - histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A()); - histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C()); - histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C())); - histos.fill(HIST("hFDDA_Collisions"), collision.multFDDA()); - histos.fill(HIST("hFDDC_Collisions"), collision.multFDDC()); - histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A()); + histos.fill(HIST("hNPVContributors"), multNTracksPV); + histos.fill(HIST("hFT0A_Collisions"), multFT0A); + histos.fill(HIST("hFT0C_Collisions"), multFT0C); + histos.fill(HIST("hFT0M_Collisions"), multFT0A + multFT0C); + histos.fill(HIST("hFDDA_Collisions"), multFDDA); + histos.fill(HIST("hFDDC_Collisions"), multFDDC); + histos.fill(HIST("hFV0A_Collisions"), multFV0A); histos.fill(HIST("hNGlobalTracks"), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracks"), collision.mftNtracks()); @@ -473,6 +475,7 @@ struct centralityStudypp { getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C)); getHist(TH1, histPath + "hFDDA_Collisions")->Fill(multFDDA); getHist(TH1, histPath + "hFDDC_Collisions")->Fill(multFDDC); + getHist(TH1, histPath + "hFDDM_Collisions")->Fill(multFDDA + multFDDC); getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A); getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); diff --git a/Common/Tools/Multiplicity/multCalibrator.cxx b/Common/Tools/Multiplicity/multCalibrator.cxx index e54a3d5a0aa..0d4ed69bd8d 100644 --- a/Common/Tools/Multiplicity/multCalibrator.cxx +++ b/Common/Tools/Multiplicity/multCalibrator.cxx @@ -40,7 +40,7 @@ const TString multCalibrator::fCentEstimName[kNCentEstim] = { multCalibrator::multCalibrator() : TNamed(), lDesiredBoundaries(0), lNDesiredBoundaries(0), - fkPrecisionWarningThreshold(1.0), + fkPrecisionWarningThreshold(1000.0), fInputFileName("AnalysisResults.root"), fOutputFileName("CCDB-objects.root"), fAnchorPointValue(-1), @@ -57,7 +57,7 @@ multCalibrator::multCalibrator() : TNamed(), multCalibrator::multCalibrator(const char* name, const char* title) : TNamed(name, title), lDesiredBoundaries(0), lNDesiredBoundaries(0), - fkPrecisionWarningThreshold(1.0), + fkPrecisionWarningThreshold(1000.0), fInputFileName("AnalysisResults.root"), fOutputFileName("CCDB-objects.root"), fAnchorPointValue(-1), @@ -230,6 +230,54 @@ void multCalibrator::SetStandardAdaptiveBoundaries() cout << "Set standard adaptive percentile boundaries! Nboundaries: " << lNDesiredBoundaries << endl; } +//________________________________________________________________ +void multCalibrator::SetRun3AdaptiveBoundaries() +{ + // Function to set standard adaptive boundaries + // Run 3 exclusive: goes to 0.00001% binning for highest multiplicity + // Warning: this setting requires well filled input histograms + // + // -> at 0.00001%, one needs 10 million events to get a single one in the highest + // category. In Run 3, at 500 kHz, this corresponds to 20 seconds of dataking; + // any run lasting over 5 minutes should have enough to calibrate to the highest + // boundary. + // + // QA when using hyperfine binning is still advised: + // Selecting very fine percentages may select on spurious situations + // such as beam-background, pileup, etc. + + lNDesiredBoundaries = 0; + lDesiredBoundaries = new Double_t[1100]; + lDesiredBoundaries[0] = 100; + // From Low To High Multiplicity + for (Int_t ib = 1; ib < 91; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 1.0; + } + for (Int_t ib = 1; ib < 91; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 0.1; + } + for (Int_t ib = 1; ib < 91; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 0.01; + } + for (Int_t ib = 1; ib < 91; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 0.001; + } + for (Int_t ib = 1; ib < 91; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 0.0001; + } + for (Int_t ib = 1; ib < 101; ib++) { + lNDesiredBoundaries++; + lDesiredBoundaries[lNDesiredBoundaries] = lDesiredBoundaries[lNDesiredBoundaries - 1] - 0.00001; + } + lNDesiredBoundaries++; + cout << "Set run 3 adaptive percentile boundaries! Nboundaries: " << lNDesiredBoundaries << endl; +} + //________________________________________________________________ void multCalibrator::SetStandardOnePercentBoundaries() { @@ -244,6 +292,32 @@ void multCalibrator::SetStandardOnePercentBoundaries() cout << "Set standard 1%-wide percentile boundaries! Nboundaries: " << lNDesiredBoundaries << endl; } +//________________________________________________________________ +bool multCalibrator::IsBinningSane(TH1* histogram) +{ + // check if binning that will be attempted is too fine for this histogram + double minimumBinWidth = 1000.0f; + for (int ib = 0; ib < lNDesiredBoundaries - 1; ib++) { + if (std::abs(lDesiredBoundaries[ib + 1] - lDesiredBoundaries[ib]) < minimumBinWidth) { + minimumBinWidth = std::abs(lDesiredBoundaries[ib + 1] - lDesiredBoundaries[ib]); + } + } + if (minimumBinWidth < 1e-9) { + cout << "Excessively fine binning requested: minimum bin width registers as " << minimumBinWidth << endl; + return false; // not reasonable + } + if (histogram->GetEntries() < 1000.0 / minimumBinWidth) { + cout << "Histogram " << histogram->GetName() << " does not have enough entries (" << histogram->GetEntries() << ") to calibrate!" << endl; + return false; + } + if (std::abs(histogram->GetMean()) < 1e-9) { + cout << "Histogram " << histogram->GetName() << " has suspicious mean: " << histogram->GetMean() << endl; + return false; + } + cout << "Sanity check: " << histogram->GetName() << ", entries = " << histogram->GetEntries() << ", 1/(min bin width) = " << 100.0 / minimumBinWidth << " -> OK ! " << endl; + return true; +} + //________________________________________________________________ TH1F* multCalibrator::GetCalibrationHistogram(TH1* histoRaw, TString lHistoName) { @@ -260,6 +334,19 @@ TH1F* multCalibrator::GetCalibrationHistogram(TH1* histoRaw, TString lHistoName) cout << "Last boundary: " << lDesiredBoundaries[0] << endl; } + // binning check + if (!IsBinningSane(histoRaw)) { + cout << "Requested binning is not viable for input histogram named " << histoRaw->GetName() << "! Will return 100.5 for all requests." << endl; + Double_t lDummyBounds[2]; + lDummyBounds[0] = 0; + lDummyBounds[1] = 1.0; + TH1F* hCalib = new TH1F(lHistoName.Data(), "", 1, lDummyBounds); + hCalib->SetBinContent(0, 100.5); + hCalib->SetBinContent(1, 100.5); + hCalib->SetBinContent(2, 100.5); + return hCalib; + } + // Aux vars Double_t lMiddleOfBins[1000]; for (Long_t lB = 1; lB < lNDesiredBoundaries; lB++) { @@ -278,15 +365,22 @@ TH1F* multCalibrator::GetCalibrationHistogram(TH1* histoRaw, TString lHistoName) if (fAnchorPointValue > 0) lDisplacedii++; lBounds[lDisplacedii] = GetBoundaryForPercentile(histoRaw, lDesiredBoundaries[ii], lPrecision[ii]); + bool warnUser = false; TString lPrecisionString = "(Precision OK)"; if (ii != 0 && ii != lNDesiredBoundaries - 1) { // check precision, please - if (lPrecision[ii] / TMath::Abs(lDesiredBoundaries[ii + 1] - lDesiredBoundaries[ii]) > fkPrecisionWarningThreshold) + if ((lPrecision[ii] / TMath::Abs(lDesiredBoundaries[ii + 1] - lDesiredBoundaries[ii])) > fkPrecisionWarningThreshold) { lPrecisionString = "(WARNING: BINNING MAY LEAD TO IMPRECISION!)"; - if (lPrecision[ii] / TMath::Abs(lDesiredBoundaries[ii - 1] - lDesiredBoundaries[ii]) > fkPrecisionWarningThreshold) + warnUser = true; + } + if ((lPrecision[ii] / TMath::Abs(lDesiredBoundaries[ii - 1] - lDesiredBoundaries[ii])) > fkPrecisionWarningThreshold) { lPrecisionString = "(WARNING: BINNING MAY LEAD TO IMPRECISION!)"; + warnUser = true; + } + } + if (warnUser) { + cout << histoRaw->GetName() << " boundaries, percentile: " << lDesiredBoundaries[ii] << "%\t Signal value = " << lBounds[lDisplacedii] << "\tprecision = " << lPrecision[ii] << "% " << lPrecisionString.Data() << endl; } - cout << histoRaw->GetName() << " boundaries, percentile: " << lDesiredBoundaries[ii] << "%\t Signal value = " << lBounds[lDisplacedii] << "\tprecision = " << lPrecision[ii] << "% " << lPrecisionString.Data() << endl; } TH1F* hCalib = new TH1F(lHistoName.Data(), "", fAnchorPointValue < 0 ? lNDesiredBoundaries - 1 : lNDesiredBoundaries, lBounds); hCalib->SetDirectory(0); @@ -311,7 +405,6 @@ void multCalibrator::ResetPrecisionHistogram() Double_t lInverseDesiredBoundaries[1100]; for (Int_t ii = 0; ii < lNDesiredBoundaries; ii++) { lInverseDesiredBoundaries[ii] = lDesiredBoundaries[lNDesiredBoundaries - (ii + 1)]; - cout << "Boundary " << ii << " is " << lInverseDesiredBoundaries[ii] << endl; } fPrecisionHistogram = new TH1D("hPrecisionHistogram", "", lNDesiredBoundaries - 1, lInverseDesiredBoundaries); } diff --git a/Common/Tools/Multiplicity/multCalibrator.h b/Common/Tools/Multiplicity/multCalibrator.h index a4e38ae1fd2..6d4b24ba5e4 100644 --- a/Common/Tools/Multiplicity/multCalibrator.h +++ b/Common/Tools/Multiplicity/multCalibrator.h @@ -60,7 +60,9 @@ class multCalibrator : public TNamed void SetAnchorPointPercentage(Float_t lPer) { fAnchorPointPercentage = lPer; } void SetStandardAdaptiveBoundaries(); // standard adaptive (pp-like) + void SetRun3AdaptiveBoundaries(); // Run 3 adaptive (down to 0.00001%) void SetStandardOnePercentBoundaries(); // standard 1% (Pb-Pb like) + bool IsBinningSane(TH1* histogram); // for safety // Master Function in this Class: To be called once filenames are set Bool_t Calibrate(); From 9ffea323ddda3f161f55512d788df6234bce9e9d Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sun, 17 May 2026 03:57:33 +0530 Subject: [PATCH 195/449] [PWGLF/Utils] mcParticle: Add anti-particles for K*0, K*+-, Xi and Lambda (#16188) --- PWGLF/Utils/mcParticle.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/PWGLF/Utils/mcParticle.h b/PWGLF/Utils/mcParticle.h index 745fcd94fbf..0209ff4e500 100644 --- a/PWGLF/Utils/mcParticle.h +++ b/PWGLF/Utils/mcParticle.h @@ -337,14 +337,22 @@ class PIDExtended return XiC0; case o2::constants::physics::Pdg::kK0Star892: return Kstar; - case 323: + case -o2::constants::physics::Pdg::kK0Star892: + return Kstar; + case o2::constants::physics::Pdg::kKPlusStar892: + return KstarPM; + case -o2::constants::physics::Pdg::kKPlusStar892: return KstarPM; case 310: return Kshort; case 3324: return Xi1530; + case -3324: + return Xi1530; case 3124: return Lambda1520; + case -3124: + return Lambda1520; default: LOG(debug) << "Cannot identify particle with PDG code " << particle.pdgCode(); break; From 417bdea90cf9ab1538ea56ae0d855737d638c941 Mon Sep 17 00:00:00 2001 From: Deependra Sharma <38365215+deependra170598@users.noreply.github.com> Date: Sun, 17 May 2026 13:37:40 +0530 Subject: [PATCH 196/449] [PWGHF/D2H] removing di-quark contribution from non-prompt Dstar (#16273) --- PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index fb3c05176cf..08492f1e7fb 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -555,6 +555,11 @@ struct HfTaskDstarToD0Pi { auto indexMother = RecoDecay::getMother(rowsMcPartilces, prong0.template mcParticle_as(), o2::constants::physics::Pdg::kDStar, true, &signDstar, 2); auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? auto ptMother = particleMother.pt(); + int const pdgBhadMother = candDstarMcRec.pdgBhadMotherPart(); + // For unknown reasons there are charm hadrons coming directly from beauty diquarks without an intermediate B-hadron which have an unreasonable correlation between the pT of the charm hadron and the beauty mother. We also remove charm hadrons from quarkonia. + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt && (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 557)) { // o2-linter: disable=pdg/explicit-code, magic-number (constants not in the PDG header) + continue; + } if (qaEnabled) { registry.fill(HIST("QA/hPtSkimDstarGenSig"), ptMother); // generator level pt registry.fill(HIST("QA/hPtVsCentSkimDstarGenSig"), ptMother, centrality); @@ -745,6 +750,12 @@ struct HfTaskDstarToD0Pi { auto idxBhadMotherPart = mcParticle.idxBhadMotherPart(); auto bMother = rowsMcPartilces.rawIteratorAt(idxBhadMotherPart); auto ptBMother = bMother.pt(); + int const pdgBhadMother = std::abs(bMother.pdgCode()); + + // For unknown reasons there are charm hadrons coming directly from beauty diquarks without an intermediate B-hadron which have an unreasonable correlation between the pT of the charm hadron and the beauty mother. We also remove charm hadrons from quarkonia. + if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt && (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 557)) { // o2-linter: disable=pdg/explicit-code, magic-number (constants not in the PDG header) + continue; + } auto yGen = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDStar); if (yCandDstarGenMax >= 0. && std::abs(yGen) > yCandDstarGenMax) { From 4119b16a9edad95a79c3d411a5bc84825f91b835 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski <63045530+Steffimro@users.noreply.github.com> Date: Sun, 17 May 2026 14:14:55 +0200 Subject: [PATCH 197/449] [PWGEM] Add LS QA plots (#16261) --- PWGEM/PhotonMeson/Tasks/photonhbt.cxx | 263 +++++++++++++++++++++++++- 1 file changed, 261 insertions(+), 2 deletions(-) diff --git a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx index 0abc24b3cad..5aeef49481d 100644 --- a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx @@ -171,8 +171,8 @@ struct Photonhbt { ConfigurableAxis confPtBins{"confPtBins", {100, 0.f, 2.f}, "pT bins (GeV/c)"}; ConfigurableAxis confEtaBins{"confEtaBins", {80, -0.8f, 0.8f}, "eta bins"}; ConfigurableAxis confPhiBins{"confPhiBins", {90, 0.f, o2::constants::math::TwoPI}, "phi bins (rad)"}; - ConfigurableAxis confDeltaEtaBins{"confDeltaEtaBins", {180, -1.6f, +1.6f}, "Delta-eta bins"}; - ConfigurableAxis confDeltaPhiBins{"confDeltaPhiBins", {180, -o2::constants::math::PI, o2::constants::math::PI}, "Delta-phi bins (rad)"}; + ConfigurableAxis confDeltaEtaBins{"confDeltaEtaBins", {360, -1.6f, +1.6f}, "Delta-eta bins"}; + ConfigurableAxis confDeltaPhiBins{"confDeltaPhiBins", {360, -o2::constants::math::PI, o2::constants::math::PI}, "Delta-phi bins (rad)"}; ConfigurableAxis confEllipseValBins{"confEllipseValBins", {200, 0.f, 10.f}, "ellipse value bins"}; ConfigurableAxis confCosThetaBins{"confCosThetaBins", {100, 0.f, 1.f}, "cos(theta*) bins"}; ConfigurableAxis confOpeningAngleBins{"confOpeningAngleBins", {100, 0.f, o2::constants::math::PI}, "opening angle bins (rad)"}; @@ -184,6 +184,8 @@ struct Photonhbt { ConfigurableAxis confDeltaZBins{"confDeltaZBins", {200, -100.f, 100.f}, "#Deltaz bins (cm)"}; ConfigurableAxis confOccupancyQA{"confOccupancyQA", {100, 0.f, 50000.f}, "occupancy"}; ConfigurableAxis confCentQABins{"confCentQABins", {110, 0.f, 110.f}, "centrality (%)"}; + ConfigurableAxis confLegPtBins{"confLegPtBins", {40, 0.f, 2.f}, "leg p_{T} bins (GeV/c)"}; + ConfigurableAxis confLegDRBins{"confLegDRBins", {200, 0.f, 1.0f}, "#DeltaR_{legs} bins"}; // ─── Axis specs ──────────────────────────────────────────────────────────── @@ -209,6 +211,8 @@ struct Photonhbt { const AxisSpec axisDeltaZ{confDeltaZBins, "#Delta z (cm)"}; const AxisSpec axisOccupancy{confOccupancyQA, "occupancy"}; const AxisSpec axisCentQA{confCentQABins, "centrality (%)"}; + const AxisSpec axisLegPt{confLegPtBins, "p_{T,leg} (GeV/c)"}; + const AxisSpec axisLegDR{confLegDRBins, "#DeltaR_{legs}"}; // ─── Configurables: QA flags ─────────────────────────────────────────────── @@ -545,6 +549,45 @@ struct Photonhbt { bool valid = true; }; + struct LegPairObservables { + float dEtaPP = 0.f, dPhiPP = 0.f, dRPP = 0.f; + float dEtaNN = 0.f, dPhiNN = 0.f, dRNN = 0.f; + float dEtaPN12 = 0.f, dPhiPN12 = 0.f, dRPN12 = 0.f; + float dEtaNP12 = 0.f, dPhiNP12 = 0.f, dRNP12 = 0.f; + float minDR_LS = 0.f; + float minLegPt_PP = 0.f, maxLegPt_PP = 0.f; + float minLegPt_NN = 0.f, maxLegPt_NN = 0.f; + float ptG1 = 0.f; + float ptG2 = 0.f; + }; + + template + static LegPairObservables buildLegPairObservables(TGamma const& g1, TGamma const& g2, + TLeg const& pos1, TLeg const& ele1, + TLeg const& pos2, TLeg const& ele2) + { + LegPairObservables o{}; + auto comp = [](auto const& a, auto const& b, float& de, float& dp, float& dr) { + de = a.eta() - b.eta(); + dp = RecoDecay::constrainAngle(a.phi() - b.phi(), -o2::constants::math::PI); + dr = std::sqrt(de * de + dp * dp); + }; + comp(pos1, pos2, o.dEtaPP, o.dPhiPP, o.dRPP); + comp(ele1, ele2, o.dEtaNN, o.dPhiNN, o.dRNN); + comp(pos1, ele2, o.dEtaPN12, o.dPhiPN12, o.dRPN12); + comp(ele1, pos2, o.dEtaNP12, o.dPhiNP12, o.dRNP12); + o.minDR_LS = std::min(o.dRPP, o.dRNN); + + o.minLegPt_PP = std::min(static_cast(pos1.pt()), static_cast(pos2.pt())); + o.maxLegPt_PP = std::max(static_cast(pos1.pt()), static_cast(pos2.pt())); + o.minLegPt_NN = std::min(static_cast(ele1.pt()), static_cast(ele2.pt())); + o.maxLegPt_NN = std::max(static_cast(ele1.pt()), static_cast(ele2.pt())); + + o.ptG1 = static_cast(g1.pt()); + o.ptG2 = static_cast(g2.pt()); + return o; + } + struct TruthGamma { int id = -1, posId = -1, negId = -1; float eta = 0.f, phi = 0.f, pt = 0.f; @@ -620,6 +663,70 @@ struct Photonhbt { fRegistryPairQA.add((path + "hSparseDeltaRDeltaZKt").c_str(), "|R_{1}-R_{2}|,#Delta z,k_{T}", kTHnSparseD, {axisDeltaR, axisDeltaZ, axisKt}, true); } + void addLegPairQAForStep(const std::string& path) + { + // LS positive + fRegistryPairQA.add((path + "LegLS/hDEtaDPhi_PP").c_str(), + "e^{+}e^{+} #Delta#eta vs #Delta#phi;#Delta#eta;#Delta#phi (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairQA.add((path + "LegLS/hSparse_DEtaDPhi_kT_minLegPt_PP").c_str(), + "e^{+}e^{+} #Delta#eta,#Delta#phi,k_{T},min(p_{T,leg})", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt, axisLegPt}, true); + fRegistryPairQA.add((path + "LegLS/hDR_PP").c_str(), + "e^{+}e^{+} #DeltaR;#DeltaR;counts", + kTH1D, {axisLegDR}, true); + fRegistryPairQA.add((path + "LegLS/hLegPtLow_vs_LegPtHigh_PP").c_str(), + "e^{+}e^{+} p_{T,low} vs p_{T,high};p_{T,low}^{leg};p_{T,high}^{leg}", + kTH2D, {axisLegPt, axisLegPt}, true); + fRegistryPairQA.add((path + "LegLS/hDR_PP_vs_minLegPt").c_str(), + "e^{+}e^{+} #DeltaR vs min(p_{T,leg});#DeltaR;min(p_{T,leg}) (GeV/c)", + kTH2D, {axisLegDR, axisLegPt}, true); + + // LS negative + fRegistryPairQA.add((path + "LegLS/hDEtaDPhi_NN").c_str(), + "e^{-}e^{-} #Delta#eta vs #Delta#phi;#Delta#eta;#Delta#phi (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairQA.add((path + "LegLS/hSparse_DEtaDPhi_kT_minLegPt_NN").c_str(), + "e^{-}e^{-} #Delta#eta,#Delta#phi,k_{T},min(p_{T,leg})", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt, axisLegPt}, true); + fRegistryPairQA.add((path + "LegLS/hDR_NN").c_str(), + "e^{-}e^{-} #DeltaR;#DeltaR;counts", + kTH1D, {axisLegDR}, true); + fRegistryPairQA.add((path + "LegLS/hLegPtLow_vs_LegPtHigh_NN").c_str(), + "e^{-}e^{-} p_{T,low} vs p_{T,high};p_{T,low}^{leg};p_{T,high}^{leg}", + kTH2D, {axisLegPt, axisLegPt}, true); + fRegistryPairQA.add((path + "LegLS/hDR_NN_vs_minLegPt").c_str(), + "e^{-}e^{-} #DeltaR vs min(p_{T,leg});#DeltaR;min(p_{T,leg}) (GeV/c)", + kTH2D, {axisLegDR, axisLegPt}, true); + + fRegistryPairQA.add((path + "LegLS/hMinDR_LS_vs_Kt").c_str(), + "min(#DeltaR_{LS}) vs k_{T};#DeltaR_{LS}^{min};k_{T} (GeV/c)", + kTH2D, {axisLegDR, axisKt}, true); + + // US cross + fRegistryPairQA.add((path + "LegUScross/hDEtaDPhi_PN12").c_str(), + "pos1-ele2 #Delta#eta vs #Delta#phi;#Delta#eta;#Delta#phi (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairQA.add((path + "LegUScross/hDEtaDPhi_NP12").c_str(), + "ele1-pos2 #Delta#eta vs #Delta#phi;#Delta#eta;#Delta#phi (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + + // 4D Photon-pT diagnostics + fRegistryPairQA.add((path + "LegLS/hSparse_DEtaDPhi_PtG1_PtG2_PP").c_str(), + "e^{+}e^{+} #Delta#eta,#Delta#phi,p_{T,#gamma 1},p_{T,#gamma 2};" + "#Delta#eta;#Delta#phi (rad);p_{T,#gamma 1} (GeV/c);p_{T,#gamma 2} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisPt, axisPt}, true); + fRegistryPairQA.add((path + "LegLS/hSparse_DEtaDPhi_PtG1_PtG2_NN").c_str(), + "e^{-}e^{-} #Delta#eta,#Delta#phi,p_{T,#gamma 1},p_{T,#gamma 2};" + "#Delta#eta;#Delta#phi (rad);p_{T,#gamma 1} (GeV/c);p_{T,#gamma 2} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisPt, axisPt}, true); + + // Photon-pT Scatter (Sanity) + fRegistryPairQA.add((path + "LegLS/hPtG1_vs_PtG2").c_str(), + "p_{T,#gamma 1} vs p_{T,#gamma 2};p_{T,#gamma 1} (GeV/c);p_{T,#gamma 2} (GeV/c)", + kTH2D, {axisPt, axisPt}, true); + } + void addhistograms() { static constexpr std::string_view det[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; @@ -660,10 +767,15 @@ struct Photonhbt { addQAHistogramsForStep("Pair/same/QA/AfterRZ/"); addQAHistogramsForStep("Pair/same/QA/AfterEllipse/"); + addLegPairQAForStep("Pair/same/QA/Before/"); + addLegPairQAForStep("Pair/same/QA/AfterEllipse/"); + addMCHistograms(); + fRegistryPairQA.addClone("Pair/same/QA/", "Pair/mix/QA/"); fRegistryPairMC.addClone("Pair/same/MC/", "Pair/mix/MC/"); addFullRangeHistograms("Pair/same/FullRange/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); fRegistry.add("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_sameSideV0_sameSideLegs", @@ -949,6 +1061,43 @@ struct Photonhbt { fRegistryPairQA.fill(HIST(base) + HIST("hEllipseVal"), (o.deta / sE) * (o.deta / sE) + (o.dphi / sP) * (o.dphi / sP)); } + template + inline void fillLegPairQAStep(LegPairObservables const& lo, float kt) + { + if (!qaflags.doPairQa) + return; + constexpr auto base = qaPrefix<0, step_id>(); + + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDEtaDPhi_PP"), lo.dEtaPP, lo.dPhiPP); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hSparse_DEtaDPhi_kT_minLegPt_PP"), + lo.dEtaPP, lo.dPhiPP, kt, lo.minLegPt_PP); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDR_PP"), lo.dRPP); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hLegPtLow_vs_LegPtHigh_PP"), + lo.minLegPt_PP, lo.maxLegPt_PP); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDR_PP_vs_minLegPt"), + lo.dRPP, lo.minLegPt_PP); + + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDEtaDPhi_NN"), lo.dEtaNN, lo.dPhiNN); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hSparse_DEtaDPhi_kT_minLegPt_NN"), + lo.dEtaNN, lo.dPhiNN, kt, lo.minLegPt_NN); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDR_NN"), lo.dRNN); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hLegPtLow_vs_LegPtHigh_NN"), + lo.minLegPt_NN, lo.maxLegPt_NN); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hDR_NN_vs_minLegPt"), + lo.dRNN, lo.minLegPt_NN); + + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hMinDR_LS_vs_Kt"), lo.minDR_LS, kt); + + fRegistryPairQA.fill(HIST(base) + HIST("LegUScross/hDEtaDPhi_PN12"), lo.dEtaPN12, lo.dPhiPN12); + fRegistryPairQA.fill(HIST(base) + HIST("LegUScross/hDEtaDPhi_NP12"), lo.dEtaNP12, lo.dPhiNP12); + + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hSparse_DEtaDPhi_PtG1_PtG2_PP"), + lo.dEtaPP, lo.dPhiPP, lo.ptG1, lo.ptG2); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hSparse_DEtaDPhi_PtG1_PtG2_NN"), + lo.dEtaNN, lo.dPhiNN, lo.ptG1, lo.ptG2); + fRegistryPairQA.fill(HIST(base) + HIST("LegLS/hPtG1_vs_PtG2"), lo.ptG1, lo.ptG2); + } + template static PhotonMCInfo buildPhotonMCInfo(TPhoton const& g, TMCParticles const& mcParticles) { @@ -1304,6 +1453,107 @@ struct Photonhbt { kTH2D, {axisKt, AxisSpec{3, -0.5f, 2.5f, "N correctly built"}}, true); } + void addLegPairMCHistograms() + { + static constexpr std::array kTypes = { + "TrueTrueDistinct/", "TrueTrueSamePhoton/", "SharedMcLeg/", + "TrueFake/", "FakeFake/", "Pi0Daughters/"}; + + for (const auto& label : kTypes) { + const std::string base = std::string("Pair/same/MC/") + std::string(label) + "LegLS/"; + fRegistryPairMC.add((base + "hDR_PP_vs_minLegPt").c_str(), + "e^{+}e^{+} #DeltaR vs min(p_{T,leg});#DeltaR;min(p_{T,leg}) (GeV/c)", + kTH2D, {axisLegDR, axisLegPt}, true); + fRegistryPairMC.add((base + "hDR_NN_vs_minLegPt").c_str(), + "e^{-}e^{-} #DeltaR vs min(p_{T,leg});#DeltaR;min(p_{T,leg}) (GeV/c)", + kTH2D, {axisLegDR, axisLegPt}, true); + fRegistryPairMC.add((base + "hSparse_DR_kT_minLegPt_PP").c_str(), + "e^{+}e^{+} #DeltaR,k_{T},min(p_{T,leg})", + kTHnSparseD, {axisLegDR, axisKt, axisLegPt}, true); + fRegistryPairMC.add((base + "hSparse_DR_kT_minLegPt_NN").c_str(), + "e^{-}e^{-} #DeltaR,k_{T},min(p_{T,leg})", + kTHnSparseD, {axisLegDR, axisKt, axisLegPt}, true); + fRegistryPairMC.add((base + "hDEtaDPhi_PP").c_str(), + "e^{+}e^{+} #Delta#eta vs #Delta#phi", kTH2D, + {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairMC.add((base + "hDEtaDPhi_NN").c_str(), + "e^{-}e^{-} #Delta#eta vs #Delta#phi", kTH2D, + {axisDeltaEta, axisDeltaPhi}, true); + + fRegistryPairMC.add((base + "hSparse_DEtaDPhi_PtG1_PtG2_PP").c_str(), + "e^{+}e^{+} #Delta#eta,#Delta#phi,p_{T,#gamma 1},p_{T,#gamma 2}", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisPt, axisPt}, true); + fRegistryPairMC.add((base + "hSparse_DEtaDPhi_PtG1_PtG2_NN").c_str(), + "e^{-}e^{-} #Delta#eta,#Delta#phi,p_{T,#gamma 1},p_{T,#gamma 2}", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisPt, axisPt}, true); + fRegistryPairMC.add((base + "hPtG1_vs_PtG2").c_str(), + "p_{T,#gamma 1} vs p_{T,#gamma 2};p_{T,#gamma 1} (GeV/c);p_{T,#gamma 2} (GeV/c)", + kTH2D, {axisPt, axisPt}, true); + } + + const AxisSpec axisTruthType{{0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5}, "truth type"}; + fRegistryPairMC.add("Pair/same/MC/hMinDR_LS_vs_Kt_TruthType", + "min(#DeltaR_{LS}) vs k_{T} vs truth type", + kTHnSparseD, {axisLegDR, axisKt, axisTruthType}, true); + } + + template + inline void fillLegPairMCTyped(LegPairObservables const& lo, float kt) + { + constexpr auto base = []() constexpr -> const char* { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/same/MC/TrueTrueDistinct/LegLS/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/same/MC/TrueTrueSamePhoton/LegLS/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/same/MC/SharedMcLeg/LegLS/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/same/MC/TrueFake/LegLS/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/same/MC/FakeFake/LegLS/"; + return "Pair/same/MC/Pi0Daughters/LegLS/"; + }(); + fRegistryPairMC.fill(HIST(base) + HIST("hDR_PP_vs_minLegPt"), lo.dRPP, lo.minLegPt_PP); + fRegistryPairMC.fill(HIST(base) + HIST("hDR_NN_vs_minLegPt"), lo.dRNN, lo.minLegPt_NN); + fRegistryPairMC.fill(HIST(base) + HIST("hSparse_DR_kT_minLegPt_PP"), lo.dRPP, kt, lo.minLegPt_PP); + fRegistryPairMC.fill(HIST(base) + HIST("hSparse_DR_kT_minLegPt_NN"), lo.dRNN, kt, lo.minLegPt_NN); + fRegistryPairMC.fill(HIST(base) + HIST("hDEtaDPhi_PP"), lo.dEtaPP, lo.dPhiPP); + fRegistryPairMC.fill(HIST(base) + HIST("hDEtaDPhi_NN"), lo.dEtaNN, lo.dPhiNN); + fRegistryPairMC.fill(HIST(base) + HIST("hSparse_DEtaDPhi_PtG1_PtG2_PP"), + lo.dEtaPP, lo.dPhiPP, lo.ptG1, lo.ptG2); + fRegistryPairMC.fill(HIST(base) + HIST("hSparse_DEtaDPhi_PtG1_PtG2_NN"), + lo.dEtaNN, lo.dPhiNN, lo.ptG1, lo.ptG2); + fRegistryPairMC.fill(HIST(base) + HIST("hPtG1_vs_PtG2"), lo.ptG1, lo.ptG2); + } + + inline void fillLegPairMC(PairTruthType t, LegPairObservables const& lo, float kt) + { + switch (t) { + case PairTruthType::TrueTrueDistinct: + fillLegPairMCTyped(lo, kt); + break; + case PairTruthType::TrueTrueSamePhoton: + fillLegPairMCTyped(lo, kt); + break; + case PairTruthType::SharedMcLeg: + fillLegPairMCTyped(lo, kt); + break; + case PairTruthType::TrueFake: + fillLegPairMCTyped(lo, kt); + break; + case PairTruthType::FakeFake: + fillLegPairMCTyped(lo, kt); + break; + case PairTruthType::Pi0Daughters: + fillLegPairMCTyped(lo, kt); + break; + default: + break; + } + fRegistryPairMC.fill(HIST("Pair/same/MC/hMinDR_LS_vs_Kt_TruthType"), + lo.minDR_LS, kt, static_cast(t)); + } + template inline void fillMCPairQATyped(PairQAObservables const& obs, bool doSparse, bool doMCQA) { @@ -1542,8 +1792,11 @@ struct Photonhbt { if (!obs.valid) continue; const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + const auto legObs = buildLegPairObservables(g1, g2, pos1, ele1, pos2, ele2); if (doQA) fillPairQAStep<0, 0>(obs, centForQA, occupancy); + if (doQA) + fillLegPairQAStep<0>(legObs, obs.kt); if (doFR) fillFullRangeDeltaRCosOA<0>(obs.qinv, obs.drOverCosOA); fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), obs.drOverCosOA); @@ -1565,6 +1818,8 @@ struct Photonhbt { idsAfterEllipse.insert(g2.globalIndex()); if (doQA) fillPairQAStep<0, 3>(obs, centForQA, occupancy); + if (doQA) + fillLegPairQAStep<3>(legObs, obs.kt); if (doFR) fillFullRangeQA<0>(obs, centForQA, occupancy); fillPairHistogram<0>(collision, obs.v1, obs.v2, 1.f); @@ -1714,8 +1969,10 @@ struct Photonhbt { if (!obs.valid) continue; const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + const auto legObs = buildLegPairObservables(g1, g2, pos1, ele1, pos2, ele2); if (doQA) fillPairQAStep<0, 0>(obs, centForQA, occupancy); + fillLegPairQAStep<0>(legObs, obs.kt); if (doFR) fillFullRangeDeltaRCosOA<0>(obs.qinv, obs.drOverCosOA); fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), obs.drOverCosOA); @@ -1737,6 +1994,7 @@ struct Photonhbt { idsAfterEllipse.insert(g2.globalIndex()); if (doQA) fillPairQAStep<0, 3>(obs, centForQA, occupancy); + fillLegPairQAStep<3>(legObs, obs.kt); if (doFR) fillFullRangeQA<0>(obs, centForQA, occupancy); fillPairHistogram<0>(collision, obs.v1, obs.v2, 1.f); @@ -1757,6 +2015,7 @@ struct Photonhbt { } else { const bool doMCQA = passQinvMCQAGate(obs.qinv); fillMCPairQA(truthType, obs, doQA, doMCQA); + fillLegPairMC(truthType, legObs, obs.kt); if (doFR) fillMCPairQAFullRange(truthType, obs); const bool isTruePair = (truthType == PairTruthType::TrueTrueDistinct || From 0f88b2d812a7a1ea05ae3fe399e12f7967755b3a Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Sun, 17 May 2026 16:01:06 +0200 Subject: [PATCH 198/449] [Common,PWGDQ,PWGJE,PWGLF] Preslice requires table type rather than iterator type (#16258) --- Common/TableProducer/mcCollsExtra.cxx | 2 +- Common/TableProducer/muonRealignment.cxx | 2 +- Common/Tasks/qaMuon.cxx | 2 +- PWGDQ/Tasks/mchAlignRecord.cxx | 2 +- PWGDQ/Tasks/muonGlobalAlignment.cxx | 2 +- PWGJE/TableProducer/jetTrackDerived.cxx | 2 +- PWGJE/Tasks/trackJetQA.cxx | 2 +- PWGLF/TableProducer/Nuspex/threebodymcfinder.cxx | 2 +- PWGLF/TableProducer/Strangeness/cascademcfinder.cxx | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Common/TableProducer/mcCollsExtra.cxx b/Common/TableProducer/mcCollsExtra.cxx index b5588317894..4b7a0f8287e 100644 --- a/Common/TableProducer/mcCollsExtra.cxx +++ b/Common/TableProducer/mcCollsExtra.cxx @@ -50,7 +50,7 @@ struct mcCollisionExtra { Configurable poiEtaWindow{"poiEtaWindow", 0.8, "PDG code requirement within this eta window"}; // For manual sliceBy - Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; template std::vector sort_indices(const std::vector& v) diff --git a/Common/TableProducer/muonRealignment.cxx b/Common/TableProducer/muonRealignment.cxx index 3fa9b462c0f..f15780546b2 100644 --- a/Common/TableProducer/muonRealignment.cxx +++ b/Common/TableProducer/muonRealignment.cxx @@ -104,7 +104,7 @@ struct MuonRealignment { TGeoManager* geoNew = nullptr; TGeoManager* geoRef = nullptr; - Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; int GetDetElemId(int iDetElemNumber) { diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index d96f05fc2a6..370c61f7afe 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -278,7 +278,7 @@ struct muonQa { TGeoManager* geoNew = nullptr; TGeoManager* geoRef = nullptr; - Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; Preslice fwdtracksPerCollision = aod::fwdtrack::collisionId; Preslice mftPerCollision = aod::fwdtrack::collisionId; diff --git a/PWGDQ/Tasks/mchAlignRecord.cxx b/PWGDQ/Tasks/mchAlignRecord.cxx index e2a9814bd20..5f610a20c98 100644 --- a/PWGDQ/Tasks/mchAlignRecord.cxx +++ b/PWGDQ/Tasks/mchAlignRecord.cxx @@ -113,7 +113,7 @@ struct mchAlignRecordTask { "List of param mask for d.o.f to be fixed"}; } fFixDetElem; - Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; void init(InitContext& ic) { diff --git a/PWGDQ/Tasks/muonGlobalAlignment.cxx b/PWGDQ/Tasks/muonGlobalAlignment.cxx index 5f9dcbea5a5..9eb13445756 100644 --- a/PWGDQ/Tasks/muonGlobalAlignment.cxx +++ b/PWGDQ/Tasks/muonGlobalAlignment.cxx @@ -237,7 +237,7 @@ struct muonGlobalAlignment { }; std::map mMchAlignmentCorrections; - Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT_muon_glo", false, false, true}; diff --git a/PWGJE/TableProducer/jetTrackDerived.cxx b/PWGJE/TableProducer/jetTrackDerived.cxx index db9a7f5325b..694f2487598 100644 --- a/PWGJE/TableProducer/jetTrackDerived.cxx +++ b/PWGJE/TableProducer/jetTrackDerived.cxx @@ -159,7 +159,7 @@ struct jetspectraDerivedMaker { return true; } - Preslice trackPerColl = aod::track::collisionId; + Preslice trackPerColl = aod::track::collisionId; Produces tableTrack; Produces tableColl; using CollisionCandidate = soa::Join; diff --git a/PWGJE/Tasks/trackJetQA.cxx b/PWGJE/Tasks/trackJetQA.cxx index 3b7eafded61..26668e5bf87 100644 --- a/PWGJE/Tasks/trackJetQA.cxx +++ b/PWGJE/Tasks/trackJetQA.cxx @@ -350,7 +350,7 @@ struct TrackJetQa { histos.fill(HIST("TPC/tpcChi2NCl"), track.pt(), track.sigma1Pt() * track.pt(), track.tpcChi2NCl(), collision.centFT0A(), collision.centFT0C()); } - Preslice trackPerColl = aod::track::collisionId; + Preslice trackPerColl = aod::track::collisionId; using CollisionCandidate = soa::Join; using TrackCandidates = soa::Join; diff --git a/PWGLF/TableProducer/Nuspex/threebodymcfinder.cxx b/PWGLF/TableProducer/Nuspex/threebodymcfinder.cxx index 47c8a72c420..4c2c2dc2ef3 100644 --- a/PWGLF/TableProducer/Nuspex/threebodymcfinder.cxx +++ b/PWGLF/TableProducer/Nuspex/threebodymcfinder.cxx @@ -59,7 +59,7 @@ struct threebodymcfinder { Configurable requireITS{"requireITS", false, "require ITS information used in tracks"}; - Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; std::vector d3bcollisionId; std::vector d3bprong0Index; diff --git a/PWGLF/TableProducer/Strangeness/cascademcfinder.cxx b/PWGLF/TableProducer/Strangeness/cascademcfinder.cxx index e732b79adce..8c95a1579d4 100644 --- a/PWGLF/TableProducer/Strangeness/cascademcfinder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascademcfinder.cxx @@ -67,7 +67,7 @@ struct cascademcfinder { Configurable doQA{"doQA", true, "do qa plots"}; // For manual sliceBy - Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; std::vector casccollisionId; std::vector cascv0Index; From 60eb13a855b066a585193d41241eb11cfecd2cec Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Sun, 17 May 2026 16:02:52 +0200 Subject: [PATCH 199/449] [Common] [O2-6910] DPL Analysis: add decay chain cycle check to checkDataModelMC (#16191) --- Common/Tasks/checkDataModelMC.cxx | 79 +++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/Common/Tasks/checkDataModelMC.cxx b/Common/Tasks/checkDataModelMC.cxx index 612f2b8da1e..343c577853d 100644 --- a/Common/Tasks/checkDataModelMC.cxx +++ b/Common/Tasks/checkDataModelMC.cxx @@ -38,12 +38,12 @@ using namespace o2::framework::expressions; /// \param particle MC particle /// \param debugMode flag for debug mode /// \param debugHisto histo to fill for debug -template +template void checkDaughters(const T& particlesMC, const typename T::iterator& particle, - long unsigned int offset, - bool& debugMode, - H debugHisto) + uint64_t offset, + bool debugMode, + std::shared_ptr& debugHisto) { auto firstDauIdx = particle.daughtersIds().front(); auto lastDauIdx = particle.daughtersIds().back(); @@ -55,7 +55,7 @@ void checkDaughters(const T& particlesMC, } } for (const auto& idxDau : particle.daughtersIds()) { - if (idxDau >= 0 && ((unsigned long int)idxDau > offset + particlesMC.size() || (unsigned long int)idxDau < offset)) { + if (idxDau >= 0 && ((uint64_t)idxDau > offset + particlesMC.size() || (uint64_t)idxDau < offset)) { if (debugMode) { debugHisto->Fill(1); } else { @@ -71,7 +71,49 @@ void checkDaughters(const T& particlesMC, } } -template +/// Check for cycles in the decay chain +/// \param particlesMC table with MC particles +template +bool checkCycles(T const& particlesMC) +{ + auto slow = particlesMC.begin(); + auto fast = particlesMC.begin(); + auto probe = particlesMC.begin(); + bool hasCycle = false; + for (auto start = 0U; start < particlesMC.size(); ++start) { + probe.setCursor(start); + if (!probe.has_mothers() || probe.mothersIds()[0] == -1) { + continue; + } + slow.setCursor(start); + fast.setCursor(start); + + while (true) { + if (!slow.has_mothers() || slow.mothersIds()[0] < 0) { + break; + } + slow.setCursor(slow.mothersIds()[0]); + + if (!fast.has_mothers() || fast.mothersIds()[0] < 0) { + break; + } + fast.setCursor(fast.mothersIds()[0]); + if (!fast.has_mothers() || fast.mothersIds()[0] < 0) { + break; + } + fast.setCursor(fast.mothersIds()[0]); + + if (slow.globalIndex() == fast.globalIndex()) { + LOGP(error, "Cycle found: particle: {} | cycle starts at: {}", start, slow.globalIndex()); + hasCycle = true; + break; + } + } + } + return hasCycle; +} + +template struct LoadTable { OutputObj counter{TH1F("counter", "counter", 2, 0., 2)}; void process(Table const& table) @@ -82,6 +124,16 @@ struct LoadTable { } }; +std::shared_ptr defineHistogram(HistogramRegistry& registry) +{ + std::shared_ptr hDebug; + hDebug = registry.add("hDebug", "debug histo;;counts", HistType::kTH1F, {{3, -0.5, 2.5}}); + hDebug->GetXaxis()->SetBinLabel(1, "(-X, Y) or (X, -Y)"); + hDebug->GetXaxis()->SetBinLabel(2, "out of range"); + hDebug->GetXaxis()->SetBinLabel(3, "#minus max integer"); + return hDebug; +} + struct CheckMcParticlesIndices { Configurable debugMode{"debugMode", false, "flag to enable debug mode"}; @@ -91,15 +143,15 @@ struct CheckMcParticlesIndices { void init(o2::framework::InitContext&) { - hDebug = registry.add("hDebug", "debug histo;;counts", HistType::kTH1F, {{3, -0.5, 2.5}}); - hDebug->GetXaxis()->SetBinLabel(1, "(-X, Y) or (X, -Y)"); - hDebug->GetXaxis()->SetBinLabel(2, "out of range"); - hDebug->GetXaxis()->SetBinLabel(3, "#minus max integer"); + hDebug = defineHistogram(registry); } void process(aod::McParticles const& particlesMC) { - long unsigned int offset = 0; + if (checkCycles(particlesMC)) { + LOG(fatal) << "Cycles found, aborting."; + } + uint64_t offset = 0; for (const auto& particle : particlesMC) { checkDaughters(particlesMC, particle, offset, debugMode.value, hDebug); } @@ -115,10 +167,7 @@ struct CheckMcParticlesIndicesGrouped { void init(o2::framework::InitContext&) { - hDebug = registry.add("hDebug", "debug histo;;counts", HistType::kTH1F, {{3, -0.5, 2.5}}); - hDebug->GetXaxis()->SetBinLabel(1, "(-X, Y) or (X, -Y)"); - hDebug->GetXaxis()->SetBinLabel(2, "out of range"); - hDebug->GetXaxis()->SetBinLabel(3, "#minus max integer"); + hDebug = defineHistogram(registry); } void process(aod::McCollision const&, From 8071e39c3d1df73043a4f199fc100c9bf35cd5e7 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sun, 17 May 2026 22:20:28 +0530 Subject: [PATCH 200/449] [PWGLF] Added new PID method for kaon identification (#16274) --- PWGLF/Tasks/Resonances/doublephimeson.cxx | 54 +++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/PWGLF/Tasks/Resonances/doublephimeson.cxx b/PWGLF/Tasks/Resonances/doublephimeson.cxx index 61b181646cf..0c5fa519efe 100644 --- a/PWGLF/Tasks/Resonances/doublephimeson.cxx +++ b/PWGLF/Tasks/Resonances/doublephimeson.cxx @@ -510,6 +510,60 @@ struct doublephimeson { } } } + if (PIDStrategy == 4) { + // pT <= 0.5 GeV/c (TPC-only) + if (ptcand <= 0.5f) { + if (ptcand < 0.4f) { + if (nsigmaTPC > -2.7f && nsigmaTPC < 2.3f) + return true; + } else { + if (nsigmaTPC > -2.5f && nsigmaTPC < 2.5f) + return true; + } + } else if (ptcand > 0.5f && ptcand < 1.0f) { + // 0.5 < pT < 1.0 GeV/c + if (TOFHit == 1) { + if (TMath::Sqrt(nsigmaTPC * nsigmaTPC + nsigmaTOF * nsigmaTOF) < 2.5f) + return true; + } else { + if (ptcand >= 0.5f && ptcand < 0.6f) { + if (nsigmaTPC > -1.5f && nsigmaTPC < 2.5f) + return true; + } else if (ptcand >= 0.6f && ptcand < 0.7f) { + if (nsigmaTPC > -0.75f && nsigmaTPC < 2.5f) + return true; + } else if (ptcand >= 0.7f && ptcand < 0.8f) { + if (nsigmaTPC > -0.3f && nsigmaTPC < 2.5f) + return true; + } else { // 0.8 - 1.0 + if (nsigmaTPC > 0.0f && nsigmaTPC < 2.5f) + return true; + } + } + } else if (ptcand >= 1.0f && ptcand < 1.8f) { + // 1.0 <= pT < 1.8 GeV/c + if (TOFHit == 1) { + if (TMath::Sqrt(nsigmaTPC * nsigmaTPC + nsigmaTOF * nsigmaTOF) < 2.5f) + return true; + } else { + if (nsigmaTPC > -2.0f && nsigmaTPC < 0.0f) + return true; + } + } else if (ptcand >= 1.8f && ptcand < 5.0f) { + // 1.8 < pT < 5.0 GeV/c + if (TOFHit == 1) { + if (TMath::Sqrt(nsigmaTPC * nsigmaTPC + nsigmaTOF * nsigmaTOF) < 2.0f) + return true; + } else { + if (nsigmaTPC > -2.5f && nsigmaTPC < 1.0f) + return true; + } + } else { + // pT >= 5.0 GeV/c (TPC-only, low stats) + if (nsigmaTPC > -2.5f && nsigmaTPC < 1.5f) + return true; + } + } return false; } From 8901608579697d107f326f72ebc97b831146dbb5 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Mon, 18 May 2026 08:17:24 +0200 Subject: [PATCH 201/449] [Common] Fix MFT pseudorapidity cut + add configurables (#14943) --- Common/Tools/Multiplicity/MultModule.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Common/Tools/Multiplicity/MultModule.h b/Common/Tools/Multiplicity/MultModule.h index 0f4e768926b..9ac88e93d59 100644 --- a/Common/Tools/Multiplicity/MultModule.h +++ b/Common/Tools/Multiplicity/MultModule.h @@ -319,6 +319,12 @@ struct standardConfigurables : o2::framework::ConfigurableGroup { o2::framework::Configurable minNclsITSGlobalTrack{"minNclsITSGlobalTrack", 5, "min. number of ITS clusters for global tracks"}; o2::framework::Configurable minNclsITSibGlobalTrack{"minNclsITSibGlobalTrack", 1, "min. number of ITSib clusters for global tracks"}; + // MFT track counter configurables + o2::framework::Configurable minNclsMFTTrack{"minNclsMFTTrack", 5, "min. number of MFT clusters for MFT tracks"}; + o2::framework::Configurable maxDCAxyToPVMFTTrack{"maxDCAxyToPVMFTTrack", 2.0f, "max DCAxy to PV for MFT tracks (cm)"}; + o2::framework::Configurable minEtaMFTTrack{"minEtaMFTTrack", -3.9f, "min. pseudorapidity for MFT tracks (nominal: -3.6)"}; + o2::framework::Configurable maxEtaMFTTrack{"maxEtaMFTTrack", -2.0f, "max. pseudorapidity for MFT tracks (nominal: -2.45)"}; + // ccdb information o2::framework::Configurable ccdbPathVtxZ{"ccdbPathVtxZ", "Centrality/Calibration", "The CCDB path for vertex-Z calibration"}; o2::framework::Configurable ccdbPathCentrality{"ccdbPathCentrality", "Centrality/Estimators", "The CCDB path for centrality information"}; @@ -988,7 +994,7 @@ class MultModule int nTracks = 0; for (const auto& track : mfttracks) { - if (track.nClusters() >= 5) { // hardcoded for now + if (track.nClusters() >= internalOpts.minNclsMFTTrack.value) { nAllTracks++; } } @@ -996,13 +1002,13 @@ class MultModule if (retracks.size() > 0) { for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); - if (track.nClusters() < 5) { + if (track.nClusters() < internalOpts.minNclsMFTTrack.value) { continue; // min cluster requirement } - if ((track.eta() > -2.0f) && (track.eta() < -3.9f)) { + if (track.eta() > internalOpts.maxEtaMFTTrack.value || track.eta() < internalOpts.minEtaMFTTrack.value) { continue; // too far to be of true interest } - if (std::abs(retrack.bestDCAXY()) > 2.0f) { + if (std::abs(retrack.bestDCAXY()) > internalOpts.maxDCAxyToPVMFTTrack.value) { continue; // does not point to PV properly } nTracks++; From 1e2ca56f0e9decae5b4f83b915a41601dfcb1826 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski <63045530+Steffimro@users.noreply.github.com> Date: Mon, 18 May 2026 09:04:06 +0200 Subject: [PATCH 202/449] [PWGEM] add MC histograms (#16281) --- PWGEM/PhotonMeson/Tasks/photonhbt.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx index 5aeef49481d..d8f2c5c7da8 100644 --- a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx @@ -775,6 +775,7 @@ struct Photonhbt { fRegistryPairQA.addClone("Pair/same/QA/", "Pair/mix/QA/"); fRegistryPairMC.addClone("Pair/same/MC/", "Pair/mix/MC/"); addFullRangeHistograms("Pair/same/FullRange/"); + addLegPairMCHistograms(); fRegistry.addClone("Pair/same/", "Pair/mix/"); From 66b71305138a71ab2ad8e9cb9f8cc7552b1edce1 Mon Sep 17 00:00:00 2001 From: Shunsuke-Kurita <135583712+Shunsuke-Kurita@users.noreply.github.com> Date: Mon, 18 May 2026 16:35:39 +0900 Subject: [PATCH 203/449] [PWGDQ] Add e-mu pairing with MC matching to dqEfficiency_withAssoc (#16276) --- PWGDQ/Core/HistogramsLibrary.cxx | 9 + PWGDQ/Core/MCSignalLibrary.cxx | 24 ++ PWGDQ/Core/VarManager.h | 8 + PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 489 ++++++++++++++++++++++++- 4 files changed, 520 insertions(+), 10 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 462360e5364..6bba77c8d40 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1971,6 +1971,15 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("correlation-emu")) { hm->AddHistogram(histClass, "DeltaPhiPair2_DeltaEtaPair2", "", false, 600, -o2::constants::math::PIHalf, 1.5 * o2::constants::math::PI, VarManager::kDeltaPhiPair2, 350, 1.5, 5.0, VarManager::kDeltaEtaPair2); hm->AddHistogram(histClass, "DeltaPhiPair2_Pt", "", false, 600, -o2::constants::math::PIHalf, 1.5 * o2::constants::math::PI, VarManager::kDeltaPhiPair2, 200, 0.0, 20.0, VarManager::kPt); + // 4D correlation map: (Delta phi_pair, Delta eta_pair, p_T^{e}, p_T^{mu}). Per-track pT axes use kPt1/kPt2, + // which FillPair populates for SE and FillPairME (patched in this PR) populates for ME. Stored as THnSparse so + // running with many MC-matched hist classes (track cut x muon cut x signal x QA variant) does not blow the + // 1 GB TBufferFile limit during the final ROOT serialization. + int varsEmu4D[4] = {VarManager::kDeltaPhiPair2, VarManager::kDeltaEtaPair2, VarManager::kPt1, VarManager::kPt2}; + int binsEmu4D[4] = {60, 35, 20, 20}; + double xminEmu4D[4] = {-o2::constants::math::PIHalf, 1.5, 0.0, 0.0}; + double xmaxEmu4D[4] = {1.5 * o2::constants::math::PI, 5.0, 20.0, 20.0}; + hm->AddHistogram(histClass, "DeltaPhiPair2_DeltaEtaPair2_PtE_PtMu", "", 4, varsEmu4D, binsEmu4D, xminEmu4D, xmaxEmu4D, nullptr, -1, kTRUE); } if (subGroupStr.Contains("dielectrons")) { if (subGroupStr.Contains("prefilter")) { diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index 0bc89619d35..e41ed34ed03 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -459,6 +459,30 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Electron-muon pair", {electron, muon}, {-1, -1}); return signal; } + if (!nameStr.compare("emuFromOpenHFhadron")) { + MCProng electron(2, {11, 902}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + electron.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng muon(2, {13, 902}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + muon.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "e and mu each from an open charm or beauty hadron decay", {electron, muon}, {-1, -1}); + return signal; + } + if (!nameStr.compare("emuFromOpenCharmHadron")) { + MCProng electron(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + electron.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng muon(2, {13, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + muon.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "e and mu each from an open charm hadron decay", {electron, muon}, {-1, -1}); + return signal; + } + if (!nameStr.compare("emuFromOpenBeautyHadron")) { + MCProng electron(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + electron.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng muon(2, {13, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + muon.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "e and mu each from an open beauty hadron decay", {electron, muon}, {-1, -1}); + return signal; + } if (!nameStr.compare("dielectronFromPC")) { MCProng prong(2, {11, 22}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "dielectron from a photon conversion", {prong, prong}, {1, 1}); diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 91759494f18..9287ef77749 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -3998,6 +3998,14 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; values[kRap] = -v12.Rapidity(); + // Per-track quantities so ME histograms can use kPt1/kPt2/kEta1/kEta2/kPhi1/kPhi2 just like SE FillPair does. + values[kPt1] = t1.pt(); + values[kEta1] = t1.eta(); + values[kPhi1] = t1.phi(); + values[kPt2] = t2.pt(); + values[kEta2] = t2.eta(); + values[kPhi2] = t2.phi(); + if (fgUsedVars[kDeltaPhiPair2]) { double phipair2ME = v1.Phi() - v2.Phi(); if (phipair2ME > 3 * TMath::Pi() / 2) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 8c33763ce96..ebeb6b0399a 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -1410,6 +1410,8 @@ struct AnalysisSameEventPairing { Configurable genSignalsJSON{"cfgMCGenSignalsJSON", "", "Additional list of MC signals (generated) via JSON"}; Configurable recSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable recSignalsJSON{"cfgMCRecSignalsJSON", "", "Comma separated list of MC signals (reconstructed) via JSON"}; + Configurable emuRecSignals{"cfgEmuMCRecSignals", "", "Comma separated list of MC signals (reconstructed) for e-mu pairs"}; + Configurable emuRecSignalsJSON{"cfgEmuMCRecSignalsJSON", "", "Additional list of MC signals (reconstructed) for e-mu pairs via JSON"}; Configurable finalStateSignals{"cfgBarrelMCFinalStateSignals", "eFromJpsi", "Comma separated list of MC signals (final state particles)"}; Configurable skimSignalOnly{"cfgSkimSignalOnly", false, "Configurable to select only matched candidates"}; } fConfigMC; @@ -1438,7 +1440,10 @@ struct AnalysisSameEventPairing { std::map> fBarrelHistNamesMCmatched; std::map> fMuonHistNames; std::map> fMuonHistNamesMCmatched; + std::map> fTrackMuonHistNames; + std::map> fTrackMuonHistNamesMCmatched; std::vector fRecMCSignals; + std::vector fEmuRecMCSignals; std::vector fGenMCSignals; std::vector fFinalStateMCSignals; @@ -1455,10 +1460,15 @@ struct AnalysisSameEventPairing { bool fEnableBarrelHistos; bool fEnableMuonHistos; + bool fEnableBarrelMuonHistos; + bool fEnableBarrelMuonMixingHistos; Preslice> trackAssocsPerCollision = aod::reducedtrack_association::reducedeventId; Preslice> muonAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; + NoBinningPolicy hashBin; + void init(o2::framework::InitContext& context) { if (context.mOptions.get("processDummy")) { @@ -1469,6 +1479,8 @@ struct AnalysisSameEventPairing { fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed"); + fEnableBarrelMuonHistos = context.mOptions.get("processElectronMuonSkimmed"); + fEnableBarrelMuonMixingHistos = context.mOptions.get("processMixingElectronMuonSkimmed"); // Keep track of all the histogram class names to avoid composing strings in the pairing loop TString histNames = ""; @@ -1518,6 +1530,29 @@ struct AnalysisSameEventPairing { } } + // Setting the MC rec signal names for e-mu pairs (independent list; the pair has leg1=electron, leg2=muon) + TString emuSigNamesStr = fConfigMC.emuRecSignals.value; + std::unique_ptr objEmuRecSigArray(emuSigNamesStr.Tokenize(",")); + for (int isig = 0; isig < objEmuRecSigArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objEmuRecSigArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required + continue; + } + fEmuRecMCSignals.push_back(sig); + } + } + TString addEmuMCSignalsStr = fConfigMC.emuRecSignalsJSON.value; + if (addEmuMCSignalsStr != "") { + std::vector addEmuMCSignals = dqmcsignals::GetMCSignalsFromJSON(addEmuMCSignalsStr.Data()); + for (auto& mcIt : addEmuMCSignals) { + if (mcIt->GetNProngs() != 2) { + continue; + } + fEmuRecMCSignals.push_back(mcIt); + } + } + // get the barrel track selection cuts string tempCuts; getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCuts, false); @@ -1700,6 +1735,115 @@ struct AnalysisSameEventPairing { } // end loop over cuts } // end if (muonCutsStr) + // build the hist directories for e-mu pairs (track cut x muon cut [x pair cut]) and for the MC matched variants + if (fEnableBarrelMuonHistos || fEnableBarrelMuonMixingHistos) { + // re-fetch the barrel cut list from upstream (we lost it when the muon block reused tempCuts/tempCutsStr) + string tempBarrelCutsStr; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempBarrelCutsStr, false); + TString barrelCutsAll = tempBarrelCutsStr; + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", tempBarrelCutsStr, false); + TString barrelCutsJSONStr = tempBarrelCutsStr; + if (barrelCutsJSONStr != "") { + std::vector addCuts = dqcuts::GetCutsFromJSON(barrelCutsJSONStr.Data()); + for (auto& t : addCuts) { + barrelCutsAll += Form(",%s", t->GetName()); + } + } + std::unique_ptr objArrayBarrel(barrelCutsAll.Tokenize(",")); + + string tempMuonCutsStr; + getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCuts", tempMuonCutsStr, false); + TString muonCutsAll = tempMuonCutsStr; + getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCutsJSON", tempMuonCutsStr, false); + TString muonCutsJSONStr = tempMuonCutsStr; + if (muonCutsJSONStr != "") { + std::vector addCuts = dqcuts::GetCutsFromJSON(muonCutsJSONStr.Data()); + for (auto& t : addCuts) { + muonCutsAll += Form(",%s", t->GetName()); + } + } + std::unique_ptr objArrayMuon(muonCutsAll.Tokenize(",")); + + TString pairCutNamesStr = fConfigCuts.pair.value; + std::unique_ptr objArrayPair(pairCutNamesStr.IsNull() ? nullptr : pairCutNamesStr.Tokenize(",")); + int nPairCuts = (objArrayPair && objArrayPair->GetEntries() > 0) ? objArrayPair->GetEntries() : 1; + + for (int iTrack = 0; iTrack < objArrayBarrel->GetEntries(); ++iTrack) { + TString trackCutName = objArrayBarrel->At(iTrack)->GetName(); + if (objArrayTrackCuts == nullptr || objArrayTrackCuts->FindObject(trackCutName.Data()) == nullptr) { + continue; + } + + for (int iMuon = 0; iMuon < objArrayMuon->GetEntries(); ++iMuon) { + TString muonCutName = objArrayMuon->At(iMuon)->GetName(); + if (objArrayMuonCuts == nullptr || objArrayMuonCuts->FindObject(muonCutName.Data()) == nullptr) { + continue; + } + + // base (no pair-cut) entry + std::vector names = { + Form("PairsEleMuSEPM_%s_%s", trackCutName.Data(), muonCutName.Data()), + Form("PairsEleMuSEPP_%s_%s", trackCutName.Data(), muonCutName.Data()), + Form("PairsEleMuSEMM_%s_%s", trackCutName.Data(), muonCutName.Data())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + if (fEnableBarrelMuonMixingHistos) { + names.push_back(Form("PairsEleMuMEPM_%s_%s", trackCutName.Data(), muonCutName.Data())); + names.push_back(Form("PairsEleMuMEPP_%s_%s", trackCutName.Data(), muonCutName.Data())); + names.push_back(Form("PairsEleMuMEMM_%s_%s", trackCutName.Data(), muonCutName.Data())); + histNames += Form("%s;%s;%s;", names[3].Data(), names[4].Data(), names[5].Data()); + } + // NOTE: the map key encodes (iTrack, iMuon) without a pair-cut axis, so this base entry sits at iTrack*fNCutsMuon + iMuon. + // Pair-cut entries below use a different stride so they do not collide. + fTrackMuonHistNames[iTrack * fNCutsMuon + iMuon] = names; + + // (track cut, muon cut, pair cut) entries + if (objArrayPair && objArrayPair->GetEntries() > 0) { + for (int iPairCut = 0; iPairCut < objArrayPair->GetEntries(); ++iPairCut) { + names = { + Form("PairsEleMuSEPM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsEleMuSEPP_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsEleMuSEMM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + if (fEnableBarrelMuonMixingHistos) { + names.push_back(Form("PairsEleMuMEPM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName())); + names.push_back(Form("PairsEleMuMEPP_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName())); + names.push_back(Form("PairsEleMuMEMM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName())); + histNames += Form("%s;%s;%s;", names[3].Data(), names[4].Data(), names[5].Data()); + } + int index = fNCutsBarrel * fNCutsMuon + iTrack * (fNCutsMuon * nPairCuts) + iMuon * nPairCuts + iPairCut; + fTrackMuonHistNames[index] = names; + } + } + + // (track cut, muon cut, MC rec signal) MC-matched entries + if (!fEmuRecMCSignals.empty()) { + for (unsigned int isig = 0; isig < fEmuRecMCSignals.size(); isig++) { + auto sig = fEmuRecMCSignals.at(isig); + names = { + Form("PairsEleMuSEPM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName()), + Form("PairsEleMuSEPP_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName()), + Form("PairsEleMuSEMM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())}; + if (fConfigQA) { + names.push_back(Form("PairsEleMuSEPMCorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPMIncorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousInBunch_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousInBunchCorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousInBunchIncorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousOutOfBunch_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousOutOfBunchCorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + names.push_back(Form("PairsEleMuSEPM_ambiguousOutOfBunchIncorrectAssoc_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), sig->GetName())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + int index = iTrack * (fNCutsMuon * fEmuRecMCSignals.size()) + iMuon * fEmuRecMCSignals.size() + isig; + fTrackMuonHistNamesMCmatched.try_emplace(index, names); + } + } + } + } + } + // get the mc generated acceptance cuts TString mcgenCutsStr = fConfigCuts.MCgenAcc.value; if (!mcgenCutsStr.IsNull()) { @@ -2077,11 +2221,6 @@ struct AnalysisSameEventPairing { } } } - // TODO: the model for the electron-muon combination has to be thought through - /*if constexpr (TPairType == VarManager::kElectronMuon) { - twoTrackFilter = a1.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & a2.isMuonSelected_raw() & fTwoTrackFilterMask; - }*/ - // Fill histograms bool isAmbiInBunch = false; bool isAmbiOutOfBunch = false; @@ -2345,6 +2484,324 @@ struct AnalysisSameEventPairing { // cout << "AnalysisSameEventPairing::runMCGen() completed" << endl; } + // Run same-event e-mu pairing on reconstructed tracks. Logic mirrors runEmuSameEventPairing in tableReader_withAssoc.cxx + // with MC matching added: for each pair we evaluate the user-supplied fEmuRecMCSignals (2-prong, leg1=e, leg2=µ) + // and fill an MC-matched histogram per (track cut, muon cut, signal) when CheckSignal returns true on the linked + // ReducedMCTracks. Mixed events are handled in runEmuMixedPairing / runEmuSameSideMixing and do not perform MC matching. + template + void runEmuSameEventPairing(TEvents const& events, Preslice& preslice1, TTrackAssocs const& assocs1, TTracks const& /*tracks1*/, Preslice& preslice2, TMuonAssocs const& assocs2, TMuons const& /*tracks2*/, ReducedMCEvents const& /*mcEvents*/, ReducedMCTracks const& /*mcTracks*/) + { + if (events.size() > 0) { + if (fCurrentRun != events.begin().runNumber()) { + initParamsFromCCDB(events.begin().timestamp(), true); + fCurrentRun = events.begin().runNumber(); + } + } + + const auto& histNames = fTrackMuonHistNames; + const auto& histNamesMC = fTrackMuonHistNamesMCmatched; + int nPairCuts = (fPairCuts.size() > 0) ? static_cast(fPairCuts.size()) : 1; + + uint32_t twoTrackFilter = 0; + uint32_t mcDecision = 0; + bool isCorrectAssoc_leg1 = false; + bool isCorrectAssoc_leg2 = false; + int sign1 = 0; + int sign2 = 0; + + constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); + constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); + + for (auto& event : events) { + if (!event.has_reducedMCevent() || !event.isEventSelected_bit(0)) { + continue; + } + + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + VarManager::FillEvent(event.reducedMCevent(), VarManager::fgValues); + + auto groupedAssocs1 = assocs1.sliceBy(preslice1, event.globalIndex()); + if (groupedAssocs1.size() == 0) { + continue; + } + auto groupedAssocs2 = assocs2.sliceBy(preslice2, event.globalIndex()); + if (groupedAssocs2.size() == 0) { + continue; + } + + for (auto& [a1, a2] : o2::soa::combinations(soa::CombinationsFullIndexPolicy(groupedAssocs1, groupedAssocs2))) { + if (!(a1.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & fTrackFilterMask)) { + continue; + } + if (!(a2.isMuonSelected_raw() & fMuonFilterMask)) { + continue; + } + + auto t1 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedmuon_as(); + sign1 = t1.sign(); + sign2 = t2.sign(); + + // build the per-pair filter: a bit is set iff the same bit index is set in both the barrel and muon raw selections + twoTrackFilter = 0; + int minCuts = std::min(fNCutsBarrel, fNCutsMuon); + for (int i = 0; i < minCuts; ++i) { + if ((a1.isBarrelSelected_raw() & (static_cast(1) << i)) && (a2.isMuonSelected_raw() & (static_cast(1) << i))) { + twoTrackFilter |= (static_cast(1) << i); + } + } + // ambiguity bits in the upper 4 slots, matching the convention used by dilepton MC histograms + if (t1.barrelAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 28); + } + if (t2.muonAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 29); + } + if (t1.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 30); + } + if (t2.muonAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 31); + } + + // MC matching: pass the legs in fixed order (electron, muon) to satisfy the 2-prong template ordering + mcDecision = 0; + isCorrectAssoc_leg1 = false; + isCorrectAssoc_leg2 = false; + if (t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + int isig = 0; + for (auto sig = fEmuRecMCSignals.begin(); sig != fEmuRecMCSignals.end(); sig++, isig++) { + if ((*sig)->CheckSignal(true, t1.reducedMCTrack(), t2.reducedMCTrack())) { + mcDecision |= (static_cast(1) << isig); + } + } + isCorrectAssoc_leg1 = (t1.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + isCorrectAssoc_leg2 = (t2.reducedMCTrack().reducedMCevent() == event.reducedMCevent()); + } + + VarManager::FillPair(t1, t2); + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } + if constexpr (eventHasQvector) { + VarManager::FillPairVn(t1, t2); + } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } + + bool isAmbiInBunch = (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)); + bool isAmbiOutOfBunch = (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)); + bool isCorrectPair = isCorrectAssoc_leg1 && isCorrectAssoc_leg2; + + // fill reco histograms per (track cut, muon cut[, pair cut]) and the MC-matched variants per signal + for (int iTrack = 0; iTrack < fNCutsBarrel; ++iTrack) { + if (!(a1.isBarrelSelected_raw() & (static_cast(1) << iTrack))) { + continue; + } + for (int iMuon = 0; iMuon < fNCutsMuon; ++iMuon) { + if (!(a2.isMuonSelected_raw() & (static_cast(1) << iMuon))) { + continue; + } + + // base reco entry (no pair-cut) + auto itHistBase = histNames.find(iTrack * fNCutsMuon + iMuon); + if (itHistBase != histNames.end()) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(itHistBase->second[0].Data(), VarManager::fgValues); + } else if (sign1 > 0) { + fHistMan->FillHistClass(itHistBase->second[1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(itHistBase->second[2].Data(), VarManager::fgValues); + } + } + + // pair-cut reco entries + for (int iPairCut = 0; iPairCut < nPairCuts; ++iPairCut) { + if (!fPairCuts.empty()) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!cut.IsSelected(VarManager::fgValues)) { + continue; + } + } + if (fPairCuts.empty()) { + continue; // already filled above + } + int index = fNCutsBarrel * fNCutsMuon + iTrack * (fNCutsMuon * nPairCuts) + iMuon * nPairCuts + iPairCut; + auto itHist = histNames.find(index); + if (itHist == histNames.end()) { + continue; + } + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(itHist->second[0].Data(), VarManager::fgValues); + } else if (sign1 > 0) { + fHistMan->FillHistClass(itHist->second[1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(itHist->second[2].Data(), VarManager::fgValues); + } + } + + // MC-matched entries (only when at least one signal fired and both legs have MC links) + if (mcDecision == 0 || fEmuRecMCSignals.empty()) { + continue; + } + for (unsigned int isig = 0; isig < fEmuRecMCSignals.size(); isig++) { + if (!(mcDecision & (static_cast(1) << isig))) { + continue; + } + int indexMC = iTrack * (fNCutsMuon * fEmuRecMCSignals.size()) + iMuon * fEmuRecMCSignals.size() + isig; + auto itHistMC = histNamesMC.find(indexMC); + if (itHistMC == histNamesMC.end()) { + continue; + } + const auto& mcNames = itHistMC->second; + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(mcNames[0].Data(), VarManager::fgValues); + } else if (sign1 > 0) { + fHistMan->FillHistClass(mcNames[1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(mcNames[2].Data(), VarManager::fgValues); + } + if (!fConfigQA || mcNames.size() < 11) { + continue; + } + // QA fills (PM only, mirroring the dilepton MC layout: indices 3..10) + if (sign1 * sign2 < 0) { + if (isCorrectPair) { + fHistMan->FillHistClass(mcNames[3].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(mcNames[4].Data(), VarManager::fgValues); + } + if (isAmbiInBunch) { + fHistMan->FillHistClass(mcNames[5].Data(), VarManager::fgValues); + if (isCorrectPair) { + fHistMan->FillHistClass(mcNames[6].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(mcNames[7].Data(), VarManager::fgValues); + } + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(mcNames[8].Data(), VarManager::fgValues); + if (isCorrectPair) { + fHistMan->FillHistClass(mcNames[9].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(mcNames[10].Data(), VarManager::fgValues); + } + } + } + } + } + } + } + } + } + + template + void runEmuMixedPairing(TAssoc1 const& assocs1, TAssoc2 const& assocs2, TTracks1 const& /*tracks1*/, TTracks2 const& /*tracks2*/) + { + const auto& histNames = fTrackMuonHistNames; + int nPairCuts = (fPairCuts.size() > 0) ? static_cast(fPairCuts.size()) : 1; + int sign1 = 0; + int sign2 = 0; + + constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); + constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); + + for (auto& a1 : assocs1) { + if (!(a1.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & fTrackFilterMask)) { + continue; + } + for (auto& a2 : assocs2) { + if (!(a2.isMuonSelected_raw() & fMuonFilterMask)) { + continue; + } + auto t1 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedmuon_as(); + sign1 = t1.sign(); + sign2 = t2.sign(); + + VarManager::FillPairME(t1, t2); + if constexpr (eventHasQvector) { + VarManager::FillPairVn(t1, t2); + } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } + + for (int iTrack = 0; iTrack < fNCutsBarrel; ++iTrack) { + if (!(a1.isBarrelSelected_raw() & (static_cast(1) << iTrack))) { + continue; + } + for (int iMuon = 0; iMuon < fNCutsMuon; ++iMuon) { + if (!(a2.isMuonSelected_raw() & (static_cast(1) << iMuon))) { + continue; + } + // base ME entry + auto itHistBase = histNames.find(iTrack * fNCutsMuon + iMuon); + if (itHistBase != histNames.end() && itHistBase->second.size() >= 6) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(itHistBase->second[3].Data(), VarManager::fgValues); + } else if (sign1 > 0) { + fHistMan->FillHistClass(itHistBase->second[4].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(itHistBase->second[5].Data(), VarManager::fgValues); + } + } + for (int iPairCut = 0; iPairCut < nPairCuts; ++iPairCut) { + if (!fPairCuts.empty()) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!cut.IsSelected(VarManager::fgValues)) { + continue; + } + } + if (fPairCuts.empty()) { + continue; + } + int index = fNCutsBarrel * fNCutsMuon + iTrack * (fNCutsMuon * nPairCuts) + iMuon * nPairCuts + iPairCut; + auto itHist = histNames.find(index); + if (itHist == histNames.end() || itHist->second.size() < 6) { + continue; + } + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(itHist->second[3].Data(), VarManager::fgValues); + } else if (sign1 > 0) { + fHistMan->FillHistClass(itHist->second[4].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(itHist->second[5].Data(), VarManager::fgValues); + } + } + } + } + } + } + } + + template + void runEmuSameSideMixing(TEvents& events, Preslice& preslice1, TTrackAssocs const& assocs1, TTracks const& tracks1, + Preslice& preslice2, TMuonAssocs const& assocs2, TMuons const& tracks2) + { + events.bindExternalIndices(&assocs1); + events.bindExternalIndices(&assocs2); + int mixingDepth = fConfigMixingDepth.value; + for (auto& [event1, event2] : selfCombinations(hashBin, mixingDepth, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1, VarManager::fgValues); + + auto groupedAssocs1 = assocs1.sliceBy(preslice1, event1.globalIndex()); + groupedAssocs1.bindExternalIndices(&events); + if (groupedAssocs1.size() == 0) { + continue; + } + auto groupedAssocs2 = assocs2.sliceBy(preslice2, event2.globalIndex()); + groupedAssocs2.bindExternalIndices(&events); + if (groupedAssocs2.size() == 0) { + continue; + } + runEmuMixedPairing(groupedAssocs1, groupedAssocs2, tracks1, tracks2); + } + } + void processAllSkimmed(MyEventsVtxCovSelected const& events, soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons, @@ -2352,11 +2809,6 @@ struct AnalysisSameEventPairing { { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons, mcEvents, mcTracks); - // Feature replaced by processMCGen - /*if (fConfigMC.runMCGenPair) { - runMCGen(mcEvents, mcTracks); - }*/ - // runSameEventPairing(event, tracks, muons); } void processBarrelOnlySkimmed(MyEventsVtxCovSelected const& events, @@ -2605,6 +3057,21 @@ struct AnalysisSameEventPairing { } } + void processElectronMuonSkimmed(MyEventsVtxCovSelected const& events, + soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons, + ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + { + runEmuSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, muonAssocsPerCollision, muonAssocs, muons, mcEvents, mcTracks); + } + + void processMixingElectronMuonSkimmed(soa::Filtered& events, + soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) + { + runEmuSameSideMixing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, muonAssocsPerCollision, muonAssocs, muons); + } + void processDummy(MyEvents&) { // do nothing @@ -2614,6 +3081,8 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmed, "Run barrel only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithCollSkimmed, "Run barrel only pairing, with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmed, "Run muon only pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processElectronMuonSkimmed, "Run electron-muon pairing, with skimmed tracks/muons", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processMixingElectronMuonSkimmed, "Run electron-muon mixing pairing, with skimmed tracks/muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMCGen, "Loop over MC particle stack and fill generator level histograms", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMCGenWithGrouping, "Loop over MC particle stack (grouped MCTracks) and fill generator level histograms", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", true); From 24a0afaf451a3a9cf830309e5c6b3278d40aa692 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Mon, 18 May 2026 11:20:52 +0200 Subject: [PATCH 204/449] [PWGCF] Add dedicated PbPb processing function (#16283) --- PWGCF/Femto/Core/collisionBuilder.h | 11 ++-- PWGCF/Femto/Core/mcBuilder.h | 12 +++- PWGCF/Femto/Core/modes.h | 1 + PWGCF/Femto/TableProducer/femtoProducer.cxx | 67 ++++++++++++++++++++- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 5093ed99269..19fb00b8abe 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -585,11 +585,12 @@ class CollisionBuilder } // PbPb specific columns - if constexpr (modes::isFlagSet(system, modes::System::kPbPb)) { - if (mProduceQns) { - collisionProducts.producedQns(utils::qn(col)); - } - } + // TODO: enable later update + // if constexpr (modes::isFlagSet(system, modes::System::kPbPb)) { + // if (mProduceQns) { + // collisionProducts.producedQns(utils::qn(col)); + // } + // } mCollisionAlreadyFilled = true; } diff --git a/PWGCF/Femto/Core/mcBuilder.h b/PWGCF/Femto/Core/mcBuilder.h index d799265dd88..812de9b7fca 100644 --- a/PWGCF/Femto/Core/mcBuilder.h +++ b/PWGCF/Femto/Core/mcBuilder.h @@ -230,9 +230,15 @@ class McBuilder template void fillMcCollision(T1 const& mcCol, T2& mcProducts) { - mcProducts.producedMcCollisions( - mcCol.multMCNParticlesEta08(), - mcCol.centFT0M()); + float centrality = -1; + if constexpr (modes::isFlagSet(system, modes::System::kPP)) { + centrality = mcCol.centFT0M(); + } + if constexpr (modes::isFlagSet(system, modes::System::kPbPb)) { + centrality = mcCol.centFT0C(); + } + + mcProducts.producedMcCollisions(mcCol.multMCNParticlesEta08(), centrality); mCollisionMap.emplace(mcCol.globalIndex(), mcProducts.producedMcCollisions.lastIndex()); } diff --git a/PWGCF/Femto/Core/modes.h b/PWGCF/Femto/Core/modes.h index c694e1916a6..5e1d18ce162 100644 --- a/PWGCF/Femto/Core/modes.h +++ b/PWGCF/Femto/Core/modes.h @@ -69,6 +69,7 @@ enum class System : uint32_t { kPP_Run3_MC = kPP | kRun3 | kMC, kPP_Run2 = kPP | kRun2, kPbPb_Run3 = kPbPb | kRun3, + kPbPb_Run3_MC = kPbPb | kRun3 | kMC, kPbPb_Run2 = kPbPb | kRun2, }; diff --git a/PWGCF/Femto/TableProducer/femtoProducer.cxx b/PWGCF/Femto/TableProducer/femtoProducer.cxx index ce58dbbd4a7..3f1bef7f42f 100644 --- a/PWGCF/Femto/TableProducer/femtoProducer.cxx +++ b/PWGCF/Femto/TableProducer/femtoProducer.cxx @@ -54,7 +54,12 @@ namespace consumeddata { using Run3PpCollisions = o2::soa::Join; using Run3PpMcRecoCollisions = o2::soa::Join; -using Run3PpMcGenCollisions = o2::soa::Join; +using Run3PpMcGenCollisions = o2::soa::Join; + +using Run3PbPbCollisions = o2::soa::Join; + +using Run3PbPbMcRecoCollisions = o2::soa::Join; +using Run3PbPbMcGenCollisions = o2::soa::Join; using Run3FullPidTracks = soa::Join(col, bcs, tracks)) { + return; + } + auto tracksWithItsPid = o2::soa::Attach(tracks); + processTracks(col, tracksWithItsPid); + } + PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPb, "Process tracks in PbPB collisions", false); + // process tracks and v0s void processTracksV0sRun3pp(consumeddata::Run3PpCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, @@ -304,6 +322,21 @@ struct FemtoProducer { }; PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3pp, "Process tracks and v0s", false); + void processTracksV0sRun3PbPb(consumeddata::Run3PbPbCollisions::iterator const& col, + o2::aod::BCsWithTimestamps const& bcs, + consumeddata::Run3FullPidTracks const& tracks, + consumeddata::Run3Vzeros const& v0s) + { + if (!processCollisions(col, bcs, tracks)) { + return; + } + auto tracksWithItsPid = o2::soa::Attach(tracks); + processTracks(col, tracksWithItsPid); + processV0s(col, tracks, v0s); + }; + PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3PbPb, "Process tracks and v0s in PbPB collisions", false); + // process tracks and kinks void processTracksKinksRun3pp(consumeddata::Run3PpCollisions::iterator const& col, o2::aod::BCsWithTimestamps const& bcs, @@ -374,6 +407,21 @@ struct FemtoProducer { } PROCESS_SWITCH(FemtoProducer, processTracksRun3ppMc, "Provide reconstructed and generated Tracks", false); + void processTracksRun3PbPbMc(consumeddata::Run3PbPbMcRecoCollisions::iterator const& col, + consumeddata::Run3PbPbMcGenCollisions const& mcCols, + o2::aod::BCsWithTimestamps const& bcs, + consumeddata::Run3McRecoTracks const& tracks, + consumeddata::Run3McGenParticles const& mcParticles) + { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { + return; + } + auto tracksWithItsPid = o2::soa::Attach(tracks); + processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); + } + PROCESS_SWITCH(FemtoProducer, processTracksRun3PbPbMc, "Provide reconstructed and generated Tracks in PbPb collisions", false); + // process monte carlo tracks and v0s void processTracksV0sRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, @@ -392,6 +440,23 @@ struct FemtoProducer { } PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3ppMc, "Provide reconstructed and generated tracks and v0s", false); + void processTracksV0sRun3PbPbMc(consumeddata::Run3PbPbMcRecoCollisions::iterator const& col, + consumeddata::Run3PbPbMcGenCollisions const& mcCols, + o2::aod::BCsWithTimestamps const& bcs, + consumeddata::Run3McRecoTracks const& tracks, + consumeddata::Run3RecoVzeros const& v0s, + consumeddata::Run3McGenParticles const& mcParticles) + { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { + return; + } + auto tracksWithItsPid = o2::soa::Attach(tracks); + processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); + processMcV0s(col, mcCols, tracks, v0s, mcParticles); + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3PbPbMc, "Provide reconstructed and generated tracks and v0s in PbPb collisions", false); + // process monte carlo tracks and kinks void processTracksKinksRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, From 3a7d1bd9e7dda929a449796b80c5ef36762fb8f1 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Mon, 18 May 2026 11:29:21 +0200 Subject: [PATCH 205/449] [PWGDQ] use configurable vector for ML input features (#16271) --- PWGDQ/Tasks/qaMatching.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 9455bbc86c7..bf0e7beb53a 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -362,12 +362,12 @@ struct QaMatching { std::array*, MlModelsNum> modelNames{ &cfgMlModelName1, &cfgMlModelName2, &cfgMlModelName3, &cfgMlModelName4, &cfgMlModelName5}; - Configurable cfgMlInputFeatures1{"cfgMlInputFeatures1", "chi2MCHMFT", "Names of ML model input features"}; - Configurable cfgMlInputFeatures2{"cfgMlInputFeatures2", std::string{""}, "Names of ML model input features"}; - Configurable cfgMlInputFeatures3{"cfgMlInputFeatures3", std::string{""}, "Names of ML model input features"}; - Configurable cfgMlInputFeatures4{"cfgMlInputFeatures4", std::string{""}, "Names of ML model input features"}; - Configurable cfgMlInputFeatures5{"cfgMlInputFeatures5", std::string{""}, "Names of ML model input features"}; - std::array*, MlModelsNum> inputFeatures{ + Configurable> cfgMlInputFeatures1{"cfgMlInputFeatures1", std::vector{"chi2MCHMFT"}, "Names of ML model input features"}; + Configurable> cfgMlInputFeatures2{"cfgMlInputFeatures2", std::vector{}, "Names of ML model input features"}; + Configurable> cfgMlInputFeatures3{"cfgMlInputFeatures3", std::vector{}, "Names of ML model input features"}; + Configurable> cfgMlInputFeatures4{"cfgMlInputFeatures4", std::vector{}, "Names of ML model input features"}; + Configurable> cfgMlInputFeatures5{"cfgMlInputFeatures5", std::vector{}, "Names of ML model input features"}; + std::array>*, MlModelsNum> inputFeatures{ &cfgMlInputFeatures1, &cfgMlInputFeatures2, &cfgMlInputFeatures3, &cfgMlInputFeatures4, &cfgMlInputFeatures5}; Configurable cfgMlModelMatchingScoreCut1{"cfgMlModelMatchingScoreCut1", 0.f, "Minimum score value for selecting good matches"}; @@ -1158,12 +1158,12 @@ struct QaMatching { auto matchingPlaneZ = configMlOptions.matchingPlaneZs[modelId]->value; auto extrapMethod = configMlOptions.matchingExtrapMethods[modelId]->value; - if (label == "" || modelPath == "" || inputFeatures == "" || modelName == "") + if (label == "" || modelPath == "" || inputFeatures.empty() || modelName == "") break; matchingMlResponses[label].configure(binsPtMl, mycutsMl, cutDirMl, 1); matchingMlResponses[label].setModelPathsCCDB(std::vector{modelName}, fCCDBApi, std::vector{modelPath}, configCcdb.cfgCcdbNoLaterThan.value); - matchingMlResponses[label].cacheInputFeaturesIndices(std::vector{inputFeatures}); + matchingMlResponses[label].cacheInputFeaturesIndices(inputFeatures); matchingMlResponses[label].init(); matchingScoreCuts[label] = scoreMin; From e073e18be51709bc27d3651223026662f92eb304 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Mon, 18 May 2026 11:29:23 +0200 Subject: [PATCH 206/449] [ALICE3] Only fill enabled histograms in otf-tof (#16282) Co-authored-by: ALICE Action Bot --- ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx | 24 ++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index b327b098a06..4617ca73657 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -707,7 +707,9 @@ struct OnTheFlyTofPid { } else { float x = 0.f; o2track.getXatLabR(simConfig.innerTOFRadius, x, mMagneticField); - histos.fill(HIST("iTOF/h2HitMap"), o2track.getZAt(x, mMagneticField), simConfig.innerTOFRadius * o2track.getPhiAt(x, mMagneticField)); + if (plotsConfig.doQAplots) { + histos.fill(HIST("iTOF/h2HitMap"), o2track.getZAt(x, mMagneticField), simConfig.innerTOFRadius * o2track.getPhiAt(x, mMagneticField)); + } } const bool activeOuterTOF = isInOuterTOFActiveArea(o2track); @@ -716,7 +718,9 @@ struct OnTheFlyTofPid { } else { float x = 0.f; o2track.getXatLabR(simConfig.outerTOFRadius, x, mMagneticField); - histos.fill(HIST("oTOF/h2HitMap"), o2track.getZAt(x, mMagneticField), simConfig.outerTOFRadius * o2track.getPhiAt(x, mMagneticField)); + if (plotsConfig.doQAplots) { + histos.fill(HIST("oTOF/h2HitMap"), o2track.getZAt(x, mMagneticField), simConfig.outerTOFRadius * o2track.getPhiAt(x, mMagneticField)); + } } // get mass to calculate velocity @@ -938,15 +942,15 @@ struct OnTheFlyTofPid { } } } - } - const float deltaTrackLengthInnerTOF = std::abs(trackLengthInnerTOF - trackLengthRecoInnerTOF); - if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) { - histos.fill(HIST("iTOF/h2dDeltaTrackLengthInnerVsPt"), noSmearingPt, deltaTrackLengthInnerTOF); - } - const float deltaTrackLengthOuterTOF = std::abs(trackLengthOuterTOF - trackLengthRecoOuterTOF); - if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) { - histos.fill(HIST("oTOF/h2dDeltaTrackLengthOuterVsPt"), noSmearingPt, deltaTrackLengthOuterTOF); + const float deltaTrackLengthInnerTOF = std::abs(trackLengthInnerTOF - trackLengthRecoInnerTOF); + if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) { + histos.fill(HIST("iTOF/h2dDeltaTrackLengthInnerVsPt"), noSmearingPt, deltaTrackLengthInnerTOF); + } + const float deltaTrackLengthOuterTOF = std::abs(trackLengthOuterTOF - trackLengthRecoOuterTOF); + if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) { + histos.fill(HIST("oTOF/h2dDeltaTrackLengthOuterVsPt"), noSmearingPt, deltaTrackLengthOuterTOF); + } } // Sigmas have been fully calculated. Please populate the NSigma helper table (once per track) From 9f94395aef4f33fdaf1a6580dbb04ef4cb84b6ca Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Mon, 18 May 2026 11:34:50 +0200 Subject: [PATCH 207/449] [PWGCF] Update in MFT track selection and added extra colums for global tracks (#16279) --- .../DataModel/LongRangeDerived.h | 260 +++++++-- .../TableProducer/longrangeMaker.cxx | 511 ++++++++++++------ .../Tasks/longrangecorrDerived.cxx | 342 ++++++------ 3 files changed, 717 insertions(+), 396 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index 69b4f8c1b5d..de216b6727a 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -18,8 +18,12 @@ #ifndef PWGCF_TWOPARTICLECORRELATIONS_DATAMODEL_LONGRANGEDERIVED_H_ #define PWGCF_TWOPARTICLECORRELATIONS_DATAMODEL_LONGRANGEDERIVED_H_ +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" + #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include #include #include @@ -138,19 +142,121 @@ using LRZdc = LRZdcs::iterator; namespace lrcorrtrktable { + +template +inline typename binningType::binned_t packInTable(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return binningType::underflowBin; + } else if (valueToBin >= binningType::binned_max) { + return binningType::overflowBin; + } else { + return static_cast((valueToBin - binningType::binned_min) / binningType::bin_width); + } +} + +template +inline float unPack(const typename binningType::binned_t& b) +{ + return binningType::bin_width * b + binningType::binned_min; +} + +template +inline typename binningType::binned_t packSymmetric(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return (binningType::underflowBin); + } else if (valueToBin >= binningType::binned_max) { + return (binningType::overflowBin); + } else if (valueToBin >= 0) { + return (static_cast((valueToBin * binningType::inv_bin_width) + 0.5f)); + } else { + return (static_cast((valueToBin * binningType::inv_bin_width) - 0.5f)); + } +} + +template +inline float unPackSymmetric(const typename binningType::binned_t& b) +{ + return binningType::bin_width * static_cast(b); +} + +namespace binning +{ + +template lim, typename binVariable = int8_t> +struct binningParent { + public: + typedef binVariable binned_t; + + // Reserve two bins: one for overflow and one for underflow + static constexpr int nbins = (1 << (8 * sizeof(binned_t))) - 2; + static constexpr binned_t overflowBin = nbins; + static constexpr binned_t underflowBin = -1; + static constexpr float binned_min = lim.first; + static constexpr float binned_max = lim.second; + static constexpr float binned_center = 0.5 * (binned_min + binned_max); + static constexpr float bin_width = (binned_max - binned_min) / static_cast(nbins); + static constexpr float inv_bin_width = 1. / bin_width; + static_assert(binned_min < binned_max, "Invalid binning range"); + static void print() + { + LOG(info) << "Binning: " << binned_min << " - " << binned_max << " with " << nbins << " bins, width = " + << bin_width << ". Overflow bin " << static_cast(overflowBin) << " Underflow bin " << static_cast(underflowBin); + } +}; + +using trkdca_v0 = binningParent(-2.0f, 2.0f), int8_t>; +using trkphi_v0 = binningParent(0.0f, o2::constants::math::TwoPI), uint16_t>; +using trkamp_v0 = binningParent(0.0f, 5000.0f), uint16_t>; +using trkpt_v0 = binningParent(0.0f, 10.0f), uint8_t>; +using trketa_v0 = binningParent(-5.0f, 5.0f), int16_t>; +using trkchi2_v0 = binningParent(0.0f, 10.0f), int8_t>; + +using trkdca = trkdca_v0; +using trkchi2 = trkchi2_v0; +using trkpt = trkpt_v0; +using trketa = trketa_v0; +using trkphi = trkphi_v0; +using trkamp = trkamp_v0; + +} // namespace binning + DECLARE_SOA_INDEX_COLUMN(LRCollision, lrCollision); DECLARE_SOA_INDEX_COLUMN(UpcLRCollision, upcLRCollision); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(Eta, eta, float); -DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(ChannelID, channelID, int); -DECLARE_SOA_COLUMN(Amplitude, amplitude, float); -DECLARE_SOA_COLUMN(GainAmplitude, gainAmplitude, float); +DECLARE_SOA_COLUMN(ChannelID, channelID, uint8_t); +DECLARE_SOA_COLUMN(AmplitudeStore, amplitudeStore, binning::trkamp::binned_t); DECLARE_SOA_COLUMN(InvMass, invMass, float); DECLARE_SOA_COLUMN(IdPos, idPos, int64_t); DECLARE_SOA_COLUMN(IdNeg, idNeg, int64_t); DECLARE_SOA_COLUMN(TrackType, trackType, uint8_t); DECLARE_SOA_COLUMN(V0Type, v0Type, uint8_t); +DECLARE_SOA_COLUMN(AmbDegree, ambDegree, uint8_t); +DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); +DECLARE_SOA_COLUMN(TPCChi2NClStore, tpcChi2NClStore, binning::trkchi2::binned_t); //! Stored binned chi2 +DECLARE_SOA_COLUMN(DCAzStore, dcazStore, binning::trkdca::binned_t); //! Stored binned dcaz +DECLARE_SOA_COLUMN(BestDCAxyStore, bestdcaxyStore, binning::trkdca::binned_t); //! Stored binned best dcaxy +DECLARE_SOA_COLUMN(BestDCAzStore, bestdcazStore, binning::trkdca::binned_t); //! Stored binned best dcaz +DECLARE_SOA_COLUMN(PtStore, ptStore, binning::trkpt::binned_t); //! Stored binned pt +DECLARE_SOA_COLUMN(EtaStore, etaStore, binning::trketa::binned_t); //! Stored binned eta +DECLARE_SOA_COLUMN(PhiStore, phiStore, binning::trkphi::binned_t); //! Stored binned phi +DECLARE_SOA_DYNAMIC_COLUMN(TPCChi2NCl, tpcChi2NCl, + [](binning::trkchi2::binned_t chi2_binned) -> float { return unPack(chi2_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAz, dcaZ, + [](binning::trkdca::binned_t dcaz_binned) -> float { return unPackSymmetric(dcaz_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, + [](binning::trkpt::binned_t pt_binned) -> float { return unPack(pt_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, + [](binning::trketa::binned_t eta_binned) -> float { return unPackSymmetric(eta_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, + [](binning::trkphi::binned_t phi_binned) -> float { return unPackSymmetric(phi_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(BestDCAXY, bestDCAXY, + [](binning::trkdca::binned_t bestdcaxy_binned) -> float { return unPackSymmetric(bestdcaxy_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(BestDCAZ, bestDCAZ, + [](binning::trkdca::binned_t bestdcaz_binned) -> float { return unPackSymmetric(bestdcaz_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Amplitude, amplitude, + [](binning::trkamp::binned_t amp_binned) -> float { return unPack(amp_binned); }); enum TrackPid { kSpCharge, kSpPion, @@ -168,30 +274,43 @@ enum V0TrackPid { DECLARE_SOA_TABLE(LRMidTracks, "AOD", "LRMIDTRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, - lrcorrtrktable::TrackType); + lrcorrtrktable::TPCNClsFound, + lrcorrtrktable::TPCNClsCrossedRows, + lrcorrtrktable::TPCChi2NClStore, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::DCAzStore, + lrcorrtrktable::TrackType, + lrcorrtrktable::TPCChi2NCl, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, + lrcorrtrktable::DCAz); using LRMidTrack = LRMidTracks::iterator; DECLARE_SOA_TABLE(LRFt0aTracks, "AOD", "LRFT0ATRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::Amplitude, - lrcorrtrktable::GainAmplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmplitudeStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRFt0aTrack = LRFt0aTracks::iterator; DECLARE_SOA_TABLE(LRFt0cTracks, "AOD", "LRFT0CTRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::Amplitude, - lrcorrtrktable::GainAmplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmplitudeStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRFt0cTrack = LRFt0cTracks::iterator; DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", @@ -199,56 +318,73 @@ DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", lrcorrtrktable::LRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, lrcorrtrktable::InvMass, - lrcorrtrktable::V0Type); + lrcorrtrktable::V0Type, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRV0Track = LRV0Tracks::iterator; DECLARE_SOA_TABLE(LRMftTracks, "AOD", "LRMFTTRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmbDegree, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + fwdtrack::NClusters, + lrcorrtrktable::BestDCAxyStore, + lrcorrtrktable::BestDCAzStore, + lrcorrtrktable::BestDCAXY, + lrcorrtrktable::BestDCAZ, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRMftTrack = LRMftTracks::iterator; -DECLARE_SOA_TABLE(LRMftBestTracks, "AOD", "LRMFTBESTTRACK", - o2::soa::Index<>, - lrcorrtrktable::LRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); -using LRMftBestTrack = LRMftBestTracks::iterator; - DECLARE_SOA_TABLE(UpcLRMidTracks, "AOD", "UPCLRMIDTRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, - lrcorrtrktable::TrackType); + lrcorrtrktable::TPCNClsFound, + lrcorrtrktable::TPCNClsCrossedRows, + lrcorrtrktable::TPCChi2NClStore, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::DCAzStore, + lrcorrtrktable::TrackType, + lrcorrtrktable::TPCChi2NCl, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, + lrcorrtrktable::DCAz); using UpcLRMidTrack = UpcLRMidTracks::iterator; DECLARE_SOA_TABLE(UpcLRFt0aTracks, "AOD", "UPCLRFT0ATRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::Amplitude, - lrcorrtrktable::GainAmplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmplitudeStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRFt0aTrack = UpcLRFt0aTracks::iterator; DECLARE_SOA_TABLE(UpcLRFt0cTracks, "AOD", "UPCLRFT0CTRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::Amplitude, - lrcorrtrktable::GainAmplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmplitudeStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRFt0cTrack = UpcLRFt0cTracks::iterator; DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", @@ -256,28 +392,32 @@ DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, lrcorrtrktable::InvMass, - lrcorrtrktable::V0Type); + lrcorrtrktable::V0Type, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRV0Track = UpcLRV0Tracks::iterator; DECLARE_SOA_TABLE(UpcLRMftTracks, "AOD", "UPCLRMFTTRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::AmbDegree, + lrcorrtrktable::PtStore, + lrcorrtrktable::EtaStore, + lrcorrtrktable::PhiStore, + fwdtrack::NClusters, + lrcorrtrktable::BestDCAxyStore, + lrcorrtrktable::BestDCAzStore, + lrcorrtrktable::BestDCAXY, + lrcorrtrktable::BestDCAZ, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRMftTrack = UpcLRMftTracks::iterator; - -DECLARE_SOA_TABLE(UpcLRMftBestTracks, "AOD", "UPCLRMFTBESTTRACK", - o2::soa::Index<>, - lrcorrtrktable::UpcLRCollisionId, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); -using UpcLRMftBestTrack = UpcLRMftBestTracks::iterator; } // namespace o2::aod #endif // PWGCF_TWOPARTICLECORRELATIONS_DATAMODEL_LONGRANGEDERIVED_H_ diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index eccf6d8fb4d..79a9465064c 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -84,6 +84,7 @@ auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; auto static constexpr TotFt0Channels = 208; AxisSpec axisEvent{15, 0.5, 15.5, "#Event", "EventAxis"}; +AxisSpec axisTrackSel{10, 0.5, 10.5, "#Track", "TrackAxis"}; auto static constexpr KminCharge = 3.0f; static constexpr std::string_view species[] = {"Pi", "Ka", "Pr"}; static constexpr std::array speciesIds{kPiPlus, kKPlus, kProton}; @@ -108,8 +109,8 @@ struct LongrangeMaker { Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; Configurable isApplyGoodITSLayersAll{"isApplyGoodITSLayersAll", false, "Enable GoodITSLayersAll cut"}; Configurable isApplyExtraCorrCut{"isApplyExtraCorrCut", false, "Enable extra NPVtracks vs FTOC correlation cut"}; - Configurable npvTracksCut{"npvTracksCut", 1.0f, "Apply extra NPVtracks cut"}; - Configurable ft0cCut{"ft0cCut", 1.0f, "Apply extra FT0C cut"}; + Configurable isApplyBestCollIndex{"isApplyBestCollIndex", true, "bestCollIndex"}; + Configurable isrejectFlangeEvent{"isrejectFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, "Enable NoCollInTimeRangeStandard cut"}; Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, "Enable NoCollInRofStandard cut"}; Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, "Enable NoHighMultCollInPrevRof cut"}; @@ -119,39 +120,45 @@ struct LongrangeMaker { Configurable isApplyOccuSelection{"isApplyOccuSelection", false, "Enable occupancy selection"}; Configurable cfgOccuCut{"cfgOccuCut", 1000, "Occupancy selection"}; Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "vertex Z selection"}; - Configurable isApplyBestCollIndex{"isApplyBestCollIndex", true, "bestCollIndex"}; - Configurable isrejectFlangeEvent{"isrejectFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; + Configurable npvTracksCut{"npvTracksCut", 1.0f, "Apply extra NPVtracks cut"}; + Configurable ft0cCut{"ft0cCut", 1.0f, "Apply extra FT0C cut"}; } cfgevtsel; struct : ConfigurableGroup { + Configurable cfgItsPattern{"cfgItsPattern", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "Eta range to consider"}; Configurable cfgPtCutMin{"cfgPtCutMin", 0.2f, "minimum accepted track pT"}; Configurable cfgPtCutMax{"cfgPtCutMax", 10.0f, "maximum accepted track pT"}; Configurable cfgPtCutMult{"cfgPtCutMult", 3.0f, "maximum track pT for multiplicity classification"}; Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "cut on minimum number of TPC crossed rows"}; Configurable minTPCNClsFound{"minTPCNClsFound", 50.f, "cut on minimum value of TPC found clusters"}; - Configurable maxDcaZ{"maxDcaZ", 2.f, "cut on maximum abs value of DCA z"}; - Configurable maxDcaXY{"maxDcaXY", 1.f, "cut on maximum abs value of DCA xy"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "cut on minNCrossedRowsOverFindableClustersTPC"}; Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "cut on maximum value of TPC chi2 per cluster"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "cut on maximum value of ITS chi2 per cluster"}; + Configurable maxDcaZ{"maxDcaZ", 2.0f, "cut on maximum abs value of DCA z"}; + Configurable maxDcaXY{"maxDcaXY", 1.0f, "cut on maximum abs value of DCA xy"}; } cfgtrksel; struct : ConfigurableGroup { - Configurable cfigMftEtaMax{"cfigMftEtaMax", -2.5f, "Maximum MFT eta cut"}; - Configurable cfigMftEtaMin{"cfigMftEtaMin", -3.6f, "Minimum MFT eta cut"}; - Configurable cfigMftDcaxy{"cfigMftDcaxy", 2.0f, "cut on DCA xy for MFT tracks"}; - Configurable cfigMftDcaz{"cfigMftDcaz", 2.0f, "cut on DCA z for MFT tracks"}; - Configurable cfigMftCluster{"cfigMftCluster", 5, "cut on MFT Cluster"}; + Configurable cfgUseChi2Cut{"cfgUseChi2Cut", false, "Use condition on MFT track: chi2/Nclusters"}; + Configurable cfgRequireCA{"cfgRequireCA", false, "Use Cellular Automaton track-finding algorithm"}; Configurable useMftPtCut{"useMftPtCut", true, "Choose to apply MFT track pT cut"}; + Configurable cfgMftCluster{"cfgMftCluster", 5, "cut on MFT Cluster"}; + Configurable cfgMftEtaMax{"cfgMftEtaMax", -2.4f, "Maximum MFT eta cut"}; + Configurable cfgMftEtaMin{"cfgMftEtaMin", -3.6f, "Minimum MFT eta cut"}; + Configurable cfgMftDcaxy{"cfgMftDcaxy", 2.0f, "cut on DCA xy for MFT tracks"}; + Configurable cfgMftDcaz{"cfgMftDcaz", 2.0f, "cut on DCA z for MFT tracks"}; Configurable cfgMftPtCutMin{"cfgMftPtCutMin", 0.f, "minimum accepted MFT track pT"}; Configurable cfgMftPtCutMax{"cfgMftPtCutMax", 10.f, "maximum accepted MFT track pT"}; + Configurable cfgMaxChi2NCl{"cfgMaxChi2NCl", 1.f, "Cut on MFT track: chi2/Nclusters"}; } cfgmfttrksel; struct : ConfigurableGroup { - Configurable cfigFt0aEtaMax{"cfigFt0aEtaMax", 4.9f, "Maximum FT0A eta cut"}; - Configurable cfigFt0aEtaMin{"cfigFt0aEtaMin", 3.5f, "Minimum FT0A eta cut"}; - Configurable cfigFt0cEtaMax{"cfigFt0cEtaMax", -2.1f, "Maximum FT0C eta cut"}; - Configurable cfigFt0cEtaMin{"cfigFt0cEtaMin", -3.3f, "Minimum FT0C eta cut"}; - Configurable cfigVerbosity{"cfigVerbosity", 0, "print statement"}; + Configurable cfgFt0aEtaMax{"cfgFt0aEtaMax", 4.9f, "Maximum FT0A eta cut"}; + Configurable cfgFt0aEtaMin{"cfgFt0aEtaMin", 3.5f, "Minimum FT0A eta cut"}; + Configurable cfgFt0cEtaMax{"cfgFt0cEtaMax", -2.1f, "Maximum FT0C eta cut"}; + Configurable cfgFt0cEtaMin{"cfgFt0cEtaMin", -3.3f, "Minimum FT0C eta cut"}; + Configurable cfgVerbosity{"cfgVerbosity", 0, "print statement"}; Configurable useGainCalib{"useGainCalib", true, "use gain calibration"}; Configurable confGainPath{"confGainPath", "Analysis/EventPlane/GainEq/FT0", "Path to gain calibration"}; } cfgfittrksel; @@ -183,6 +190,16 @@ struct LongrangeMaker { Configurable maxLambdaLifeTime{"maxLambdaLifeTime", 30.0f, "Maximum Lambda lifetime (in cm)"}; } cfgv0trksel; + struct : ConfigurableGroup { + ConfigurableAxis axisVtx = {"axisVtx", {20, -10, 10}, "Vertex axis"}; + ConfigurableAxis axisMult = {"axisMult", {100, 0, 100}, "Multiplicity axis"}; + ConfigurableAxis axisEta = {"axisEta", {20, -1, 1}, "eta axis"}; + ConfigurableAxis axisPt = {"axisPt", {10, 0, 10}, "pT axis"}; + ConfigurableAxis axisSpecies = {"axisSpecies", {4, 0.5, 4.5}, "Species axis"}; + ConfigurableAxis axisAmplitude{"axisAmplitude", {5000, 0, 10000}, "FT0 amplitude"}; + ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; + } cfgAxis; + Configurable> itsNsigmaPidCut{"itsNsigmaPidCut", std::vector{3, 2.5, 2, -3, -2.5, -2}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; Configurable> tpcNsigmaPidCut{"tpcNsigmaPidCut", std::vector{1.5, 1.5, 1.5, -1.5, -1.5, -1.5}, "TPC n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; Configurable> tofNsigmaPidCut{"tofNsigmaPidCut", std::vector{1.5, 1.5, 1.5, -1.5, -1.5, -1.5}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; @@ -190,12 +207,6 @@ struct LongrangeMaker { Configurable isUseItsPid{"isUseItsPid", false, "Use ITS PID for particle identification"}; Configurable isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; - ConfigurableAxis vtxHistBin{"vtxHistBin", {20, -10, 10}, ""}; - ConfigurableAxis multHistBin{"multHistBin", {100, 0, 100}, ""}; - ConfigurableAxis etaHistBin{"etaHistBin", {20, -1, 1}, ""}; - ConfigurableAxis ptHistBin{"ptHistBin", {10, 0, 10}, ""}; - ConfigurableAxis speciesHistBin{"speciesHistBin", {4, 0.5, 4.5}, ""}; - Service ccdb; Service pdg; o2::ccdb::CcdbApi ccdbApi; @@ -246,15 +257,38 @@ struct LongrangeMaker { x->SetBinLabel(13, "reject flange event"); histos.add("hSelectionResult", "hSelectionResult", kTH1I, {{5, -0.5, 4.5}}); - AxisSpec axisVtx = {vtxHistBin, "Vertex", "VtxAxis"}; - AxisSpec axisMult = {multHistBin, "Mult", "MultAxis"}; - AxisSpec axisEta = {etaHistBin, "Eta", "EtaAxis"}; - AxisSpec axisPt = {ptHistBin, "Pt", "PtAxis"}; - AxisSpec axisSpecies = {speciesHistBin, "Species", "SpeciesAxis"}; + histos.add("hMftTrkSel", "hMftTrkSel", kTH1D, {axisTrackSel}, false); + auto hMftTrkStat = histos.get(HIST("hMftTrkSel")); + auto* xMftTrk = hMftTrkStat->GetXaxis(); + xMftTrk->SetBinLabel(1, "All"); + xMftTrk->SetBinLabel(2, "Cluster selection"); + xMftTrk->SetBinLabel(3, "Chi2/NCluster selection"); + xMftTrk->SetBinLabel(4, "eta selection"); + xMftTrk->SetBinLabel(5, "pT selection"); + xMftTrk->SetBinLabel(6, "CA track selection"); + + histos.add("hMftBestTrkSel", "hMftBestTrkSel", kTH1D, {axisTrackSel}, false); + auto hMftBestTrkStat = histos.get(HIST("hMftBestTrkSel")); + auto* xMftBestTrk = hMftBestTrkStat->GetXaxis(); + xMftBestTrk->SetBinLabel(1, "All"); + xMftBestTrk->SetBinLabel(2, "BestSelCollID selection"); + xMftBestTrk->SetBinLabel(3, "Orphan track selection"); + xMftBestTrk->SetBinLabel(4, "DCAxy selection"); + xMftBestTrk->SetBinLabel(5, "DCAz selection"); + + histos.add("FT0A_Amp", "FT0A_Amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("FT0A_Amp_gaincorrected", "FT0A_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("FT0A_Channel_vs_Amp", "FT0A_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + histos.add("FT0A_Channel_vs_Amp_gaincorrected", "FT0A_Channel_vs_Amp_gaincorrected", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + + histos.add("FT0C_Amp", "FT0C_Amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("FT0C_Amp_gaincorrected", "FT0C_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("FT0C_Channel_vs_Amp", "FT0C_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + histos.add("FT0C_Channel_vs_Amp_gaincorrected", "FT0C_Channel_vs_Amp_gaincorrected", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); if (doprocessTPCtrackEff || doprocessMFTtrackEff) { - histos.add("hGenMCdndpt", "hGenMCdndpt", kTHnSparseD, {axisVtx, axisMult, axisEta, axisPt, axisSpecies}, false); - histos.add("hRecMCdndpt", "hRecMCdndpt", kTHnSparseD, {axisVtx, axisMult, axisEta, axisPt, axisSpecies}, false); + histos.add("hGenMCdndpt", "hGenMCdndpt", kTHnSparseD, {cfgAxis.axisVtx, cfgAxis.axisMult, cfgAxis.axisEta, cfgAxis.axisPt, cfgAxis.axisSpecies}, false); + histos.add("hRecMCdndpt", "hRecMCdndpt", kTHnSparseD, {cfgAxis.axisVtx, cfgAxis.axisMult, cfgAxis.axisEta, cfgAxis.axisPt, cfgAxis.axisSpecies}, false); auto hGenSpecies = histos.get(HIST("hGenMCdndpt")); auto hRecSpecies = histos.get(HIST("hRecMCdndpt")); auto* axisGen = hGenSpecies->GetAxis(4); @@ -267,14 +301,16 @@ struct LongrangeMaker { axisRec->SetBinLabel(4, "Other"); } - myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + myTrackFilter = getGlobalTrackSelectionRun3ITSMatch(cfgtrksel.cfgItsPattern, TrackSelection::GlobalTrackRun3DCAxyCut::Default); myTrackFilter.SetPtRange(cfgtrksel.cfgPtCutMin, cfgtrksel.cfgPtCutMax); myTrackFilter.SetEtaRange(-cfgtrksel.cfgEtaCut, cfgtrksel.cfgEtaCut); myTrackFilter.SetMinNCrossedRowsTPC(cfgtrksel.minNCrossedRowsTPC); + myTrackFilter.SetMinNCrossedRowsOverFindableClustersTPC(cfgtrksel.minNCrossedRowsOverFindableClustersTPC); myTrackFilter.SetMinNClustersTPC(cfgtrksel.minTPCNClsFound); + myTrackFilter.SetMaxChi2PerClusterTPC(cfgtrksel.maxChi2PerClusterTPC); + myTrackFilter.SetMaxChi2PerClusterITS(cfgtrksel.maxChi2PerClusterITS); myTrackFilter.SetMaxDcaZ(cfgtrksel.maxDcaZ); myTrackFilter.SetMaxDcaXYPtDep([scale = cfgtrksel.maxDcaXY.value](float pt) { return scale * (0.0105f + 0.0350f / std::pow(pt, 1.1f)); }); - myTrackFilter.SetMaxChi2PerClusterTPC(cfgtrksel.maxChi2PerClusterTPC); myTrackFilter.print(); tofNsigmaCut = tofNsigmaPidCut; @@ -296,7 +332,6 @@ struct LongrangeMaker { Produces lrft0atracks; Produces lrft0ctracks; Produces lrmfttracks; - Produces lrmftbesttracks; Produces lrv0tracks; Produces upclrcollision; @@ -307,21 +342,20 @@ struct LongrangeMaker { Produces upclrft0atracks; Produces upclrft0ctracks; Produces upclrmfttracks; - Produces upclrmftbesttracks; Produces upclrv0tracks; Filter fTracksEta = nabs(aod::track::eta) < cfgtrksel.cfgEtaCut; Filter fTracksPt = (aod::track::pt > cfgtrksel.cfgPtCutMin) && (aod::track::pt < cfgtrksel.cfgPtCutMax); - using CollTable = soa::Join; + using CollTable = soa::Join; using TrksTable = soa::Filtered>; using MftTrkTable = aod::MFTTracks; using BCs = soa::Join; std::vector ft0gainvalues{}; void processData(CollTable::iterator const& col, TrksTable const& tracks, - aod::FT0s const&, MftTrkTable const& mfttracks, - soa::SmallGroups const& besttracks, + aod::FT0s const&, MftTrkTable const&, + soa::SmallGroups const& reassoMftTracks, aod::V0Datas const& V0s, aod::BCsWithTimestamps const&) { if (!isEventSelected(col)) { @@ -330,6 +364,7 @@ struct LongrangeMaker { auto multiplicity = countNTracks(tracks); auto centrality = selColCent(col); auto bc = col.bc_as(); + // retrieve FT0 gain info from CCDB ft0gainvalues.clear(); ft0gainvalues = {}; if (cfgfittrksel.useGainCalib) { @@ -355,25 +390,58 @@ struct LongrangeMaker { if (!myTrackFilter.IsSelected(track)) continue; auto pid = getTrackPID(track); - lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); + lrmidtracks(lrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + aod::lrcorrtrktable::kSpCharge); + if (pid != aod::lrcorrtrktable::kSpCharge) { - lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), pid); + lrmidtracks(lrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + pid); } } // ft0 loop if (col.has_foundFT0()) { const auto& ft0 = col.foundFT0(); + if (cfgevtsel.isrejectFlangeEvent) { + constexpr int IsFlangeEventId = 7; + std::bitset<8> ft0TriggerMask = ft0.triggerMask(); + if (ft0TriggerMask[IsFlangeEventId]) { + return; + } + } + histos.fill(HIST("EventHist"), 13); for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { auto chanelid = ft0.channelA()[iCh]; float ampl = ft0.amplitudeA()[iCh]; auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); auto gainampl = ampl / ft0gainvalues[chanelid]; - if (cfgfittrksel.cfigVerbosity > 0) { + if (cfgfittrksel.cfgVerbosity > 0) { LOGF(info, "FT0A info: Channel = %d | indexchannel = %d | %f | %f", chanelid, iCh, ft0gainvalues[chanelid], ft0gainvalues[iCh]); } - lrft0atracks(lrcollision.lastIndex(), chanelid, ampl, gainampl, eta, phi); + lrft0atracks(lrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(gainampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); + histos.fill(HIST("FT0A_Amp"), ampl); + histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); + histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); + histos.fill(HIST("FT0A_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; @@ -381,34 +449,39 @@ struct LongrangeMaker { auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); auto gainampl = ampl / ft0gainvalues[chanelid]; - if (cfgfittrksel.cfigVerbosity > 0) { + if (cfgfittrksel.cfgVerbosity > 0) { LOGF(info, "FT0C info: Channel = %d | indexchannel = %d | %f | %f", chanelid, iCh, ft0gainvalues[chanelid], ft0gainvalues[iCh]); } - lrft0ctracks(lrcollision.lastIndex(), chanelid, ampl, gainampl, eta, phi); + lrft0ctracks(lrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(gainampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); + histos.fill(HIST("FT0C_Amp"), ampl); + histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); + histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); + histos.fill(HIST("FT0C_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); } } - // mft loop - for (const auto& track : mfttracks) { - if (!isMftTrackSelected(track)) + // mft tracks + for (const auto& reassoMftTrack : reassoMftTracks) { + if (!isMftBestTrackSelected(reassoMftTrack)) + continue; + auto itrack = reassoMftTrack.template mfttrack_as(); + if (!isMftTrackSelected(itrack)) { continue; - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - lrmfttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); - } - - if (besttracks.size() > 0) { - for (const auto& besttrack : besttracks) { - if (!isMftBestTrackSelected(besttrack)) - continue; - auto track = besttrack.mfttrack(); - if (!isMftTrackSelected(track)) { - continue; - } - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - lrmftbesttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); } + auto phi = itrack.phi(); + o2::math_utils::bringTo02Pi(phi); + lrmfttracks(lrcollision.lastIndex(), + reassoMftTrack.ambDegree(), + aod::lrcorrtrktable::packInTable(itrack.pt()), + aod::lrcorrtrktable::packSymmetric(itrack.eta()), + aod::lrcorrtrktable::packSymmetric(phi), + itrack.nClusters(), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); } // v0 loop @@ -422,8 +495,14 @@ struct LongrangeMaker { // K0short if (isSelectK0s(col, v0)) { // candidate is K0s - lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); + lrv0tracks(lrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.mK0Short(), + aod::lrcorrtrktable::kSpK0short); } // Lambda and Anti-Lambda @@ -433,13 +512,25 @@ struct LongrangeMaker { // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) if (lambdaTag) { // candidate is Lambda massV0 = v0.mLambda(); - lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); + lrv0tracks(lrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + massV0, + aod::lrcorrtrktable::kSpLambda); } if (antilambdaTag) { // candidate is Anti-lambda massV0 = v0.mAntiLambda(); - lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); + lrv0tracks(lrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + massV0, + aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing } } // process function @@ -447,8 +538,8 @@ struct LongrangeMaker { void processUpc(CollTable::iterator const& col, BCs const& bcs, TrksTable const& tracks, aod::Zdcs const&, aod::FV0As const& fv0as, aod::FT0s const& ft0s, - aod::FDDs const& fdds, MftTrkTable const& mfttracks, - soa::SmallGroups const& besttracks, + aod::FDDs const& fdds, MftTrkTable const&, + soa::SmallGroups const& reassoMftTracks, aod::V0Datas const& V0s) { if (!isEventSelected(col)) { @@ -492,9 +583,26 @@ struct LongrangeMaker { if (!myTrackFilter.IsSelected(track)) continue; auto pid = getTrackPID(track); - upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); + upclrmidtracks(upclrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + aod::lrcorrtrktable::kSpCharge); + if (pid != aod::lrcorrtrktable::kSpCharge) { - upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), pid); + upclrmidtracks(upclrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + pid); } } @@ -506,38 +614,42 @@ struct LongrangeMaker { float ampl = ft0.amplitudeA()[iCh]; auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); - upclrft0atracks(upclrcollision.lastIndex(), chanelid, ampl, ampl, eta, phi); + upclrft0atracks(upclrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(ampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; float ampl = ft0.amplitudeC()[iCh]; auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); - upclrft0ctracks(upclrcollision.lastIndex(), chanelid, ampl, ampl, eta, phi); + upclrft0ctracks(upclrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(ampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); } } - // mft loop - for (const auto& track : mfttracks) { - if (!isMftTrackSelected(track)) + for (const auto& reassoMftTrack : reassoMftTracks) { + if (!isMftBestTrackSelected(reassoMftTrack)) + continue; + auto itrack = reassoMftTrack.template mfttrack_as(); + if (!isMftTrackSelected(itrack)) { continue; - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - upclrmfttracks(upclrcollision.lastIndex(), track.pt(), track.eta(), phi); - } - - if (besttracks.size() > 0) { - for (const auto& besttrack : besttracks) { - if (!isMftBestTrackSelected(besttrack)) - continue; - auto track = besttrack.mfttrack(); - if (!isMftTrackSelected(track)) { - continue; - } - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - upclrmftbesttracks(upclrcollision.lastIndex(), track.pt(), track.eta(), phi); } + auto phi = itrack.phi(); + o2::math_utils::bringTo02Pi(phi); + upclrmfttracks(upclrcollision.lastIndex(), + reassoMftTrack.ambDegree(), + aod::lrcorrtrktable::packInTable(itrack.pt()), + aod::lrcorrtrktable::packSymmetric(itrack.eta()), + aod::lrcorrtrktable::packSymmetric(phi), + itrack.nClusters(), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); } // v0 loop @@ -551,8 +663,14 @@ struct LongrangeMaker { // K0short if (isSelectK0s(col, v0)) { // candidate is K0s - upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); + upclrv0tracks(upclrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.mK0Short(), + aod::lrcorrtrktable::kSpK0short); } // Lambda and Anti-Lambda @@ -562,13 +680,25 @@ struct LongrangeMaker { // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) if (lambdaTag) { // candidate is Lambda massV0 = v0.mLambda(); - upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); + upclrv0tracks(upclrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + massV0, + aod::lrcorrtrktable::kSpLambda); } if (antilambdaTag) { // candidate is Anti-lambda massV0 = v0.mAntiLambda(); - upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); + upclrv0tracks(upclrcollision.lastIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + aod::lrcorrtrktable::packInTable(v0.pt()), + aod::lrcorrtrktable::packSymmetric(v0.eta()), + aod::lrcorrtrktable::packSymmetric(v0.phi()), + massV0, + aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing } } // SG events @@ -579,11 +709,10 @@ struct LongrangeMaker { using TrksMCRecTable = soa::Filtered>; using MftTrkMCRecTable = soa::Join; Preslice perColMidtrack = aod::track::collisionId; - Preslice perColMfttrack = o2::aod::fwdtrack::collisionId; - PresliceUnsorted perColMftbesttrack = aod::fwdtrack::bestCollisionId; + PresliceUnsorted perColMftTrack = aod::fwdtrack::bestCollisionId; void processMCRec(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, TrksMCRecTable const& RecTracks, - aod::FT0s const&, MftTrkMCRecTable const& mfttracks, aod::BestCollisionsFwd3d const& besttracks, + aod::FT0s const&, MftTrkMCRecTable const&, aod::BestCollisionsFwd3d const& reassoMftTracks, aod::McParticles const& mcparticles, aod::BCsWithTimestamps const&) { auto multiplicity = 0; @@ -636,9 +765,26 @@ struct LongrangeMaker { if (RecCol.mcCollisionId() != mcpart.mcCollisionId()) continue; auto pid = getTrackPID(track); - lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); + lrmidtracks(lrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + aod::lrcorrtrktable::kSpCharge); + if (pid != aod::lrcorrtrktable::kSpCharge) { - lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), pid); + lrmidtracks(lrcollision.lastIndex(), + track.tpcNClsFound(), + track.tpcNClsCrossedRows(), + aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), + aod::lrcorrtrktable::packInTable(track.pt()), + aod::lrcorrtrktable::packSymmetric(track.eta()), + aod::lrcorrtrktable::packSymmetric(track.phi()), + aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + pid); } } @@ -651,7 +797,15 @@ struct LongrangeMaker { auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); auto gainampl = ampl / ft0gainvalues[chanelid]; - lrft0atracks(lrcollision.lastIndex(), chanelid, ampl, gainampl, eta, phi); + lrft0atracks(lrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(gainampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); + histos.fill(HIST("FT0A_Amp"), ampl); + histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); + histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); + histos.fill(HIST("FT0A_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; @@ -659,38 +813,36 @@ struct LongrangeMaker { auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); auto gainampl = ampl / ft0gainvalues[chanelid]; - lrft0ctracks(lrcollision.lastIndex(), chanelid, ampl, gainampl, eta, phi); + lrft0ctracks(lrcollision.lastIndex(), + chanelid, + aod::lrcorrtrktable::packInTable(gainampl), + aod::lrcorrtrktable::packSymmetric(eta), + aod::lrcorrtrktable::packSymmetric(phi)); + histos.fill(HIST("FT0C_Amp"), ampl); + histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); + histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); + histos.fill(HIST("FT0C_Channel_vs_Amp_gaincorrected"), chanelid, gainampl); } } - // mft loop - auto recMftTracksPart = mfttracks.sliceBy(perColMfttrack, RecCol.globalIndex()); - for (const auto& track : recMftTracksPart) { - if (!isMftTrackSelected(track)) + auto recMftTracksPart = reassoMftTracks.sliceBy(perColMftTrack, RecCol.globalIndex()); + for (const auto& reassoMftTrack : recMftTracksPart) { + if (!isMftBestTrackSelected(reassoMftTrack)) continue; - if (!track.has_mcParticle()) + auto itrack = reassoMftTrack.template mfttrack_as(); + if (!isMftTrackSelected(itrack)) { continue; - auto mcpart = track.mcParticle(); - if (RecCol.mcCollisionId() != mcpart.mcCollisionId()) - continue; - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - lrmfttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); - } - - auto recMftbestTracksPart = besttracks.sliceBy(perColMftbesttrack, RecCol.globalIndex()); - if (recMftbestTracksPart.size() > 0) { - for (const auto& besttrack : recMftbestTracksPart) { - if (!isMftBestTrackSelected(besttrack)) - continue; - auto track = besttrack.mfttrack_as(); - if (!isMftTrackSelected(track)) { - continue; - } - auto phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - lrmftbesttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); } + auto phi = itrack.phi(); + o2::math_utils::bringTo02Pi(phi); + lrmfttracks(lrcollision.lastIndex(), + reassoMftTrack.ambDegree(), + aod::lrcorrtrktable::packInTable(itrack.pt()), + aod::lrcorrtrktable::packSymmetric(itrack.eta()), + aod::lrcorrtrktable::packSymmetric(phi), + itrack.nClusters(), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), + aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); } for (const auto& particle : mcparticles) { @@ -701,12 +853,12 @@ struct LongrangeMaker { if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks - if (cfgfittrksel.cfigFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0aEtaMax) + if (cfgfittrksel.cfgFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0aEtaMax) lrft0amctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); - if (cfgfittrksel.cfigFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0cEtaMax) + if (cfgfittrksel.cfgFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (cfgmfttrksel.cfigMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfigMftEtaMax) + if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } @@ -730,12 +882,12 @@ struct LongrangeMaker { if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks - if (cfgfittrksel.cfigFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0aEtaMax) + if (cfgfittrksel.cfgFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0aEtaMax) lrft0amctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); - if (cfgfittrksel.cfigFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfigFt0cEtaMax) + if (cfgfittrksel.cfgFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (cfgmfttrksel.cfigMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfigMftEtaMax) + if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } @@ -797,8 +949,8 @@ struct LongrangeMaker { } } void processMFTtrackEff(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, - TrksMCRecTable const& RecTracks, MftTrkMCRecTable const& mfttracks, - aod::McParticles const& mcparticles) + TrksMCRecTable const& RecTracks, MftTrkMCRecTable const&, + aod::BestCollisionsFwd3d const& reassoMftTracks, aod::McParticles const& mcparticles) { if (std::abs(mcCollision.posZ()) >= cfgevtsel.cfgVtxCut) { return; @@ -821,7 +973,7 @@ struct LongrangeMaker { atLeastOne = true; } for (const auto& particle : mcparticles) { - if (!isGenPartSelected(particle) || particle.eta() > cfgmfttrksel.cfigMftEtaMax || particle.eta() < cfgmfttrksel.cfigMftEtaMin || particle.pt() < cfgmfttrksel.cfgMftPtCutMin || particle.pt() > cfgmfttrksel.cfgMftPtCutMax) + if (!isGenPartSelected(particle) || particle.eta() > cfgmfttrksel.cfgMftEtaMax || particle.eta() < cfgmfttrksel.cfgMftEtaMin || particle.pt() < cfgmfttrksel.cfgMftPtCutMin || particle.pt() > cfgmfttrksel.cfgMftPtCutMax) continue; if (atLeastOne) histos.fill(HIST("hGenMCdndpt"), mcCollision.posZ(), multiplicity, particle.eta(), particle.pt(), 1.0); @@ -833,10 +985,15 @@ struct LongrangeMaker { continue; if (cfgevtsel.isApplyBestCollIndex && RecCol.globalIndex() != mcCollision.bestCollisionIndex()) continue; - auto recTracksPart = mfttracks.sliceBy(perColMfttrack, RecCol.globalIndex()); - for (const auto& track : recTracksPart) { - if (!isMftTrackSelected(track)) + + auto recTracksPart = reassoMftTracks.sliceBy(perColMftTrack, RecCol.globalIndex()); + for (const auto& reassoMftTrack : recTracksPart) { + if (!isMftBestTrackSelected(reassoMftTrack)) continue; + auto track = reassoMftTrack.mfttrack_as(); + if (!isMftTrackSelected(track)) { + continue; + } if (!track.has_mcParticle()) continue; auto particle = track.mcParticle(); @@ -915,16 +1072,6 @@ struct LongrangeMaker { return false; } histos.fill(HIST("EventHist"), 12); - if (cfgevtsel.isrejectFlangeEvent) { - if constexpr (requires { col.ft0TriggerMask(); }) { - constexpr int IsFlangeEventId = 7; - std::bitset<8> ft0TriggerMask = col.ft0TriggerMask(); - if (ft0TriggerMask[IsFlangeEventId]) { - return false; - } - } - } - histos.fill(HIST("EventHist"), 13); return true; } @@ -1027,36 +1174,78 @@ struct LongrangeMaker { return -std::log(std::tan(0.5 * theta)); } - template + template bool isMftTrackSelected(CheckMftTrack const& track) { - if (track.nClusters() < cfgmfttrksel.cfigMftCluster) { + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 1); + } + if (track.nClusters() < cfgmfttrksel.cfgMftCluster) { return false; } - if (track.eta() > cfgmfttrksel.cfigMftEtaMax || track.eta() < cfgmfttrksel.cfigMftEtaMin) { + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 2); + } + if (cfgmfttrksel.cfgUseChi2Cut) { + float nclMft = std::max(2.0f * track.nClusters() - 5.0f, 1.0f); + float mftChi2NCl = track.chi2() / nclMft; + if (mftChi2NCl > cfgmfttrksel.cfgMaxChi2NCl) + return false; + } + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 3); + } + if (track.eta() > cfgmfttrksel.cfgMftEtaMax || track.eta() < cfgmfttrksel.cfgMftEtaMin) { return false; } + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 4); + } if (cfgmfttrksel.useMftPtCut && (track.pt() < cfgmfttrksel.cfgMftPtCutMin || track.pt() > cfgmfttrksel.cfgMftPtCutMax)) { return false; } + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 5); + } + if (cfgmfttrksel.cfgRequireCA && !track.isCA()) { + return false; + } + if constexpr (fillHis) { + histos.fill(HIST("hMftTrkSel"), 6); + } return true; } - template - bool isMftBestTrackSelected(CheckMftBestTrack const& besttrack) + template + bool isMftBestTrackSelected(CheckMftTrack const& mfttrack) { - if (besttrack.bestCollisionId() < CintZero) { + if constexpr (fillHis) { + histos.fill(HIST("hMftBestTrkSel"), 1); + } + if (mfttrack.bestCollisionId() < CintZero) { return false; } - if (besttrack.ambDegree() == CintZero) { + if constexpr (fillHis) { + histos.fill(HIST("hMftBestTrkSel"), 2); + } + if (mfttrack.ambDegree() == CintZero) { return false; } - if (std::abs(besttrack.bestDCAXY()) > cfgmfttrksel.cfigMftDcaxy) { + if constexpr (fillHis) { + histos.fill(HIST("hMftBestTrkSel"), 3); + } + if (std::abs(mfttrack.bestDCAXY()) >= cfgmfttrksel.cfgMftDcaxy) { return false; } - if (std::abs(besttrack.bestDCAZ()) >= cfgmfttrksel.cfigMftDcaz) { + if constexpr (fillHis) { + histos.fill(HIST("hMftBestTrkSel"), 4); + } + if (std::abs(mfttrack.bestDCAZ()) >= cfgmfttrksel.cfgMftDcaz) { return false; } + if constexpr (fillHis) { + histos.fill(HIST("hMftBestTrkSel"), 5); + } return true; } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 705795bf863..f387acbbd2b 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -54,13 +54,58 @@ struct LongrangecorrDerived { SliceCache cache; SGSelector sgSelector; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Configurable cfgNmixedevent{"cfgNmixedevent", 5, "how many events are mixed"}; - Configurable cfgPidMask{"cfgPidMask", 0, "Selection bitmask for the TPC particle"}; - Configurable cfgV0Mask{"cfgV0Mask", 0, "Selection bitmask for the V0 particle"}; - Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; - Configurable isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; - Configurable isUseDataLikeMult{"isUseDataLikeMult", 0, "Data like mult/cent classification"}; - Configurable useGainCorr{"useGainCorr", true, "use gain calibration"}; + + struct : ConfigurableGroup { + Configurable cfgNmixedevent{"cfgNmixedevent", 5, "how many events are mixed"}; + Configurable cfgPidMask{"cfgPidMask", 0, "Selection bitmask for the TPC particle"}; + Configurable cfgV0Mask{"cfgV0Mask", 0, "Selection bitmask for the V0 particle"}; + Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; + Configurable isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; + Configurable isUseDataLikeMult{"isUseDataLikeMult", 0, "Data like mult/cent classification"}; + + Configurable cfgTpcMinNclsFound{"cfgTpcMinNclsFound", 50.0f, ""}; + Configurable cfgTpcMinNCrossedRows{"cfgTpcMinNCrossedRows", 70.0f, ""}; + Configurable cfgTpcMaxChi2PerCluster{"cfgTpcMaxChi2PerCluster", 4.0f, ""}; + Configurable cfgTpcMaxDcaZ{"cfgTpcMaxDcaZ", 1.0f, ""}; + + Configurable cfgMftCluster{"cfgMftCluster", 5, "cut on MFT Cluster"}; + Configurable cfgMftDcaxy{"cfgMftDcaxy", 2.0f, "cut on DCA xy for MFT tracks"}; + Configurable cfgMftDcaz{"cfgMftDcaz", 2.0f, "cut on DCA z for MFT tracks"}; + Configurable cfgRejectAmbTrk{"cfgRejectAmbTrk", false, "Condition to reject Ambiguous tracks"}; + Configurable cfgRejectNonAmbTrk{"cfgRejectNonAmbTrk", false, "Condition to reject Non-Ambiguous tracks"}; + } cfgSel; + + struct : ConfigurableGroup { + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 15, 25, 50, 60, 1000}, "multiplicity axis"}; + ConfigurableAxis axisPhi{"axisPhi", {96, 0, TwoPI}, "#phi axis"}; + ConfigurableAxis axisEtaTrig{"axisEtaTrig", {40, -1., 1.}, "#eta trig axis"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt assoc axis for histograms"}; + ConfigurableAxis axisVtxZ{"axisVtxZ", {40, -20, 20}, "vertex axis"}; + ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {96, 3.5, 4.9}, "#eta assoc axis"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -6, -2}, "delta eta axis for histograms"}; + ConfigurableAxis axisInvMass{"axisInvMass", {VARIABLE_WIDTH, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0}, "invariant mass axis"}; + ConfigurableAxis axisInvMassQA{"axisInvMassQA", {20, 0.45, 0.55}, "invariant mass axis for QA"}; + ConfigurableAxis axisAmplitude{"axisAmplitude", {5000, 0, 10000}, "FT0 amplitude"}; + ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; + ConfigurableAxis axisMultME{"axisMultME", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 1000}, "Mixing bins - multiplicity"}; + ConfigurableAxis axisVtxZME{"axisVtxZME", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; + + ConfigurableAxis axisTPCNClsFound{"axisTPCNClsFound", {200, -0.5, 199.5}, "TPC Cluster axis"}; + ConfigurableAxis axisTPCNClsCrossedRows{"axisTPCNClsCrossedRows", {200, -0.5, 199.5}, "TPC NCrossedRow axis"}; + ConfigurableAxis axisTPCChi2NCl{"axisTPCChi2NCl", {20, 0.0, 20.0}, "TPC Chi2/NCl axis"}; + ConfigurableAxis axisTPCdcaZ{"axisTPCdcaZ", {200, -10.0, 10.0}, "TPC dcaZ axis"}; + + ConfigurableAxis axisMFTAmbDegree{"axisMFTAmbDegree", {50, -0.5, 49.5}, "Track Ambiguity axis"}; + ConfigurableAxis axisMFTNClusters{"axisMFTNClusters", {200, -0.5, 199.5}, "MFT Cluster axis"}; + ConfigurableAxis axisMFTbestDCAXY{"axisMFTbestDCAXY", {200, -10.0, 10.0}, "MFT dcaXY axis"}; + ConfigurableAxis axisMFTbestDCAZ{"axisMFTbestDCAZ", {200, -10.0, 10.0}, "MFT dcaZ axis"}; + + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {1, 0.5, 8.0}, "pt axis for efficiency histograms"}; + } cfgAxis; Configurable cfgFv0Cut{"cfgFv0Cut", 50.0f, "FV0A threshold"}; Configurable cfgFt0aCut{"cfgFt0aCut", 100.0f, "FT0A threshold"}; @@ -68,26 +113,6 @@ struct LongrangecorrDerived { Configurable cfgZdcCut{"cfgZdcCut", 0.1f, "ZDC threshold"}; Configurable cfgGapSideCut{"cfgGapSideCut", 0, "Gap-side A=0, C=1, AC = 2, No Gap = -1, All events = 3"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 15, 25, 50, 60, 1000}, "multiplicity axis"}; - ConfigurableAxis axisPhi{"axisPhi", {96, 0, TwoPI}, "#phi axis"}; - ConfigurableAxis axisEtaTrig{"axisEtaTrig", {40, -1., 1.}, "#eta trig axis"}; - ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; - ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt assoc axis for histograms"}; - ConfigurableAxis axisVtxZ{"axisVtxZ", {40, -20, 20}, "vertex axis"}; - ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {96, 3.5, 4.9}, "#eta assoc axis"}; - ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; - ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -6, -2}, "delta eta axis for histograms"}; - ConfigurableAxis axisInvMass{"axisInvMass", {VARIABLE_WIDTH, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0}, "invariant mass axis"}; - ConfigurableAxis axisInvMassQA{"axisInvMassQA", {20, 0.45, 0.55}, "invariant mass axis for QA"}; - ConfigurableAxis axisAmplitude{"axisAmplitude", {5000, 0, 10000}, "FT0 amplitude"}; - ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; - ConfigurableAxis axisMultME{"axisMultME", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 1000}, "Mixing bins - multiplicity"}; - ConfigurableAxis axisVtxZME{"axisVtxZME", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; - - ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; - ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; - ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; - OutputObj same{"sameEvent"}; OutputObj mixed{"mixedEvent"}; @@ -96,7 +121,6 @@ struct LongrangecorrDerived { using MftTrksTable = aod::LRMftTracks; using Ft0aTrksTable = aod::LRFt0aTracks; using Ft0cTrksTable = aod::LRFt0cTracks; - using MftbestTrksTable = aod::LRMftBestTracks; using V0TrksTable = aod::LRV0Tracks; using McCollsTable = aod::LRMcCollisions; @@ -110,19 +134,16 @@ struct LongrangecorrDerived { using MftTrksUpcTable = aod::UpcLRMftTracks; using Ft0aTrksUpcTable = aod::UpcLRFt0aTracks; using Ft0cTrksUpcTable = aod::UpcLRFt0cTracks; - using MftbestTrksUpcTable = aod::UpcLRMftBestTracks; using V0TrksUpcTable = aod::UpcLRV0Tracks; Preslice perColTpc = aod::lrcorrtrktable::lrCollisionId; Preslice perColMft = aod::lrcorrtrktable::lrCollisionId; - Preslice perColMftbest = aod::lrcorrtrktable::lrCollisionId; Preslice perColFt0a = aod::lrcorrtrktable::lrCollisionId; Preslice perColFt0c = aod::lrcorrtrktable::lrCollisionId; Preslice perColV0 = aod::lrcorrtrktable::lrCollisionId; Preslice perUpcColTpc = aod::lrcorrtrktable::upcLRCollisionId; Preslice perUpcColMft = aod::lrcorrtrktable::upcLRCollisionId; - Preslice perUpcColMftbest = aod::lrcorrtrktable::upcLRCollisionId; Preslice perUpcColFt0a = aod::lrcorrtrktable::upcLRCollisionId; Preslice perUpcColFt0c = aod::lrcorrtrktable::upcLRCollisionId; Preslice perUpcColV0 = aod::lrcorrtrktable::upcLRCollisionId; @@ -134,50 +155,86 @@ struct LongrangecorrDerived { void init(InitContext const&) { - std::vector corrAxis = {{axisVtxZ, "z-vtx (cm)"}, - {axisMultiplicity, "multiplicity"}, - {axisPtTrigger, "p_{T} (GeV/c)"}, - {axisPtAssoc, "p_{T} (GeV/c)"}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEta, "#Delta#eta"}}; - std::vector effAxis = {{axisVertexEfficiency, "z-vtx (cm)"}, - {axisPtEfficiency, "p_{T} (GeV/c)"}, - {axisEtaEfficiency, "#eta"}}; - std::vector userAxis = {{axisInvMass, "m (GeV/c^2)"}}; + std::vector corrAxis = {{cfgAxis.axisVtxZ, "z-vtx (cm)"}, + {cfgAxis.axisMultiplicity, "multiplicity"}, + {cfgAxis.axisPtTrigger, "p_{T} (GeV/c)"}, + {cfgAxis.axisPtAssoc, "p_{T} (GeV/c)"}, + {cfgAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, + {cfgAxis.axisDeltaEta, "#Delta#eta"}}; + std::vector effAxis = {{cfgAxis.axisVertexEfficiency, "z-vtx (cm)"}, + {cfgAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, + {cfgAxis.axisEtaEfficiency, "#eta"}}; + std::vector userAxis = {{cfgAxis.axisInvMass, "m (GeV/c^2)"}}; same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); - histos.add("hMultiplicity", "hMultiplicity", kTH1D, {axisMultiplicity}); - histos.add("hCentrality", "hCentrality", kTH1D, {axisMultiplicity}); - histos.add("hVertexZ", "hVertexZ", kTH1D, {axisVtxZ}); + histos.add("hMultiplicity", "hMultiplicity", kTH1D, {cfgAxis.axisMultiplicity}); + histos.add("hCentrality", "hCentrality", kTH1D, {cfgAxis.axisMultiplicity}); + histos.add("hVertexZ", "hVertexZ", kTH1D, {cfgAxis.axisVtxZ}); histos.add("hGapSide", "hGapSide", kTH1I, {{5, -0.5, 4.5}}); histos.add("hTrueGapSide", "hTrueGapSide", kTH1I, {{6, -1.5, 4.5}}); histos.add("hTrueGapSide_AfterSel", "hTrueGapSide_AfterSel", kTH1I, {{6, -1.5, 4.5}}); - histos.add("Trig_eta", "Trig_eta", kTH1D, {axisEtaTrig}); - histos.add("Trig_phi", "Trig_phi", kTH1D, {axisPhi}); - histos.add("Trig_etavsphi", "Trig_etavsphi", kTH2D, {axisPhi, axisEtaTrig}); - histos.add("Trig_pt", "Trig_pt", kTH1D, {axisPtTrigger}); - histos.add("Trig_invMass", "Trig_invMass", kTH1D, {axisInvMassQA}); - histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {axisVtxZ, axisMultiplicity, axisPtTrigger, axisInvMass}); - histos.add("Trig_amp", "Trig_amp", kTH1D, {axisAmplitude}); - histos.add("Trig_amp_gaincorrected", "Trig_amp_gaincorrected", kTH1D, {axisAmplitude}); - histos.add("Channel_vs_Trig_amp", "Channel_vs_Trig_amp", kTH2D, {axisChannel, axisAmplitude}); - histos.add("Channel_vs_Trig_amp_gaincorrected", "Channel_vs_Trig_amp_gaincorrected", kTH2D, {axisChannel, axisAmplitude}); - - histos.add("Assoc_eta", "Assoc_eta", kTH1D, {axisEtaAssoc}); - histos.add("Assoc_phi", "Assoc_phi", kTH1D, {axisPhi}); - histos.add("Assoc_etavsphi", "Assoc_etavsphi", kTH2D, {axisPhi, axisEtaAssoc}); - histos.add("Assoc_pt", "Assoc_pt", kTH1D, {axisPtAssoc}); - histos.add("Assoc_amp", "Assoc_amp", kTH1D, {axisAmplitude}); - histos.add("Assoc_amp_gaincorrected", "Assoc_amp_gaincorrected", kTH1D, {axisAmplitude}); - histos.add("Channel_vs_Assoc_amp", "Channel_vs_Assoc_amp", kTH2D, {axisChannel, axisAmplitude}); - histos.add("Channel_vs_Assoc_amp_gaincorrected", "Channel_vs_Assoc_amp_gaincorrected", kTH2D, {axisChannel, axisAmplitude}); - - histos.add("deltaEta_deltaPhi_same", "", kTH2D, {axisDeltaPhi, axisDeltaEta}); - histos.add("deltaEta_deltaPhi_mixed", "", kTH2D, {axisDeltaPhi, axisDeltaEta}); + histos.add("Trig_eta", "Trig_eta", kTH1D, {cfgAxis.axisEtaTrig}); + histos.add("Trig_phi", "Trig_phi", kTH1D, {cfgAxis.axisPhi}); + histos.add("Trig_etavsphi", "Trig_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaTrig}); + histos.add("Trig_pt", "Trig_pt", kTH1D, {cfgAxis.axisPtTrigger}); + histos.add("Trig_invMass", "Trig_invMass", kTH1D, {cfgAxis.axisInvMassQA}); + histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {cfgAxis.axisVtxZ, cfgAxis.axisMultiplicity, cfgAxis.axisPtTrigger, cfgAxis.axisInvMass}); + histos.add("Trig_amp", "Trig_amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("Channel_vs_Trig_amp", "Channel_vs_Trig_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + + histos.add("Assoc_eta", "Assoc_eta", kTH1D, {cfgAxis.axisEtaAssoc}); + histos.add("Assoc_phi", "Assoc_phi", kTH1D, {cfgAxis.axisPhi}); + histos.add("Assoc_etavsphi", "Assoc_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaAssoc}); + histos.add("Assoc_pt", "Assoc_pt", kTH1D, {cfgAxis.axisPtAssoc}); + histos.add("Assoc_amp", "Assoc_amp", kTH1D, {cfgAxis.axisAmplitude}); + histos.add("Channel_vs_Assoc_amp", "Channel_vs_Assoc_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); + + histos.add("deltaEta_deltaPhi_same", "deltaEta_deltaPhi_same", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); + histos.add("deltaEta_deltaPhi_mixed", "deltaEta_deltaPhi_mixed", kTH2D, {cfgAxis.axisDeltaPhi, cfgAxis.axisDeltaEta}); + + histos.add("TPCNClsFound", "TPCNClsFound", kTH1D, {cfgAxis.axisTPCNClsFound}); + histos.add("TPCNClsCrossedRows", "TPCNClsCrossedRows", kTH1D, {cfgAxis.axisTPCNClsCrossedRows}); + histos.add("TPCChi2NCl", "TPCChi2NCl", kTH1D, {cfgAxis.axisTPCChi2NCl}); + histos.add("TPCdcaZ", "TPCdcaZ", kTH1D, {cfgAxis.axisTPCdcaZ}); + + histos.add("MFTAmbDegree", "MFTAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + histos.add("MFTNClusters", "MFTNClusters", kTH1D, {cfgAxis.axisMFTNClusters}); + histos.add("MFTbestDCAXY", "MFTbestDCAXY", kTH1D, {cfgAxis.axisMFTbestDCAXY}); + histos.add("MFTbestDCAZ", "MFTbestDCAZ", kTH1D, {cfgAxis.axisMFTbestDCAZ}); + } + + template + bool isTrackSelected(TTrack const& track) + { + if constexpr (requires { track.tpcNClsFound(); }) { + if (track.tpcNClsFound() < cfgSel.cfgTpcMinNclsFound) + return false; + if (track.tpcNClsCrossedRows() < cfgSel.cfgTpcMinNCrossedRows) + return false; + if (track.tpcChi2NCl() > cfgSel.cfgTpcMaxChi2PerCluster) + return false; + if (std::abs(track.dcaZ()) > cfgSel.cfgTpcMaxDcaZ) + return false; + return true; + } else if constexpr (requires { track.nClusters(); }) { + if (track.nClusters() < cfgSel.cfgMftCluster) + return false; + if (std::abs(track.bestDCAXY()) >= cfgSel.cfgMftDcaxy) + return false; + if (std::abs(track.bestDCAZ()) >= cfgSel.cfgMftDcaz) + return false; + if (cfgSel.cfgRejectAmbTrk && track.ambDegree() > 1) + return false; + if (cfgSel.cfgRejectNonAmbTrk && track.ambDegree() == 1) + return false; + return true; + } else { + return true; + } } template @@ -199,14 +256,24 @@ struct LongrangecorrDerived { if constexpr (requires { track.channelID(); }) { histos.fill(HIST("Trig_amp"), track.amplitude()); histos.fill(HIST("Channel_vs_Trig_amp"), track.channelID(), track.amplitude()); - histos.fill(HIST("Trig_amp_gaincorrected"), track.gainAmplitude()); - histos.fill(HIST("Channel_vs_Trig_amp_gaincorrected"), track.channelID(), track.gainAmplitude()); } else { histos.fill(HIST("Trig_pt"), track.pt()); } if constexpr (requires { track.invMass(); }) { histos.fill(HIST("Trig_invMass"), track.invMass()); } + if constexpr (requires { track.tpcNClsFound(); }) { + histos.fill(HIST("TPCNClsFound"), track.tpcNClsFound()); + histos.fill(HIST("TPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + histos.fill(HIST("TPCChi2NCl"), track.tpcChi2NCl()); + histos.fill(HIST("TPCdcaZ"), track.dcaZ()); + } + if constexpr (requires { track.nClusters(); }) { + histos.fill(HIST("MFTNClusters"), track.nClusters()); + histos.fill(HIST("MFTbestDCAXY"), track.bestDCAXY()); + histos.fill(HIST("MFTbestDCAZ"), track.bestDCAZ()); + histos.fill(HIST("MFTAmbDegree"), track.ambDegree()); + } } template @@ -218,11 +285,15 @@ struct LongrangecorrDerived { if constexpr (requires { track.channelID(); }) { histos.fill(HIST("Assoc_amp"), track.amplitude()); histos.fill(HIST("Channel_vs_Assoc_amp"), track.channelID(), track.amplitude()); - histos.fill(HIST("Assoc_amp_gaincorrected"), track.gainAmplitude()); - histos.fill(HIST("Channel_vs_Assoc_amp_gaincorrected"), track.channelID(), track.gainAmplitude()); } else { histos.fill(HIST("Assoc_pt"), track.pt()); } + if constexpr (requires { track.nClusters(); }) { + histos.fill(HIST("MFTNClusters"), track.nClusters()); + histos.fill(HIST("MFTbestDCAXY"), track.bestDCAXY()); + histos.fill(HIST("MFTbestDCAZ"), track.bestDCAZ()); + histos.fill(HIST("MFTAmbDegree"), track.ambDegree()); + } } template @@ -249,25 +320,26 @@ struct LongrangecorrDerived { for (auto const& triggerTrack : triggers) { auto trigAmpl = 1.0f; if constexpr (requires { triggerTrack.channelID(); }) { - if (useGainCorr) - trigAmpl = triggerTrack.gainAmplitude(); - else - trigAmpl = triggerTrack.amplitude(); + trigAmpl = triggerTrack.amplitude(); } else { trigAmpl = 1.0; } + + if (!isTrackSelected(triggerTrack)) + continue; + if constexpr (requires { triggerTrack.trackType(); }) { - if (cfgPidMask != 0 && (cfgPidMask & (1u << static_cast(triggerTrack.trackType()))) == 0u) + if (cfgSel.cfgPidMask != 0 && (cfgSel.cfgPidMask & (1u << static_cast(triggerTrack.trackType()))) == 0u) continue; } else if constexpr (requires { triggerTrack.v0Type(); }) { - if (cfgV0Mask != 0 && (cfgV0Mask & (1u << static_cast(triggerTrack.v0Type()))) == 0u) + if (cfgSel.cfgV0Mask != 0 && (cfgSel.cfgV0Mask & (1u << static_cast(triggerTrack.v0Type()))) == 0u) continue; } if (!mixing) { fillTrigTrackQA(triggerTrack); if constexpr (requires { triggerTrack.channelID(); }) { histos.fill(HIST("Trig_hist"), vz, multiplicity, 1.0, 1.0, eventWeight * trigAmpl); - } else if constexpr (requires { triggerTrack.v0Type(); }) { + } else if constexpr (requires { triggerTrack.invMass(); }) { histos.fill(HIST("Trig_hist"), vz, multiplicity, triggerTrack.pt(), triggerTrack.invMass(), eventWeight * trigAmpl); } else { histos.fill(HIST("Trig_hist"), vz, multiplicity, triggerTrack.pt(), 1.0, eventWeight * trigAmpl); @@ -275,14 +347,15 @@ struct LongrangecorrDerived { } for (auto const& assoTrack : assocs) { auto assoAmpl = 1.0f; - if constexpr (requires { assoTrack.v0Type(); }) { - if (useGainCorr) - assoAmpl = assoTrack.gainAmplitude(); - else - assoAmpl = assoTrack.amplitude(); + if constexpr (requires { assoTrack.channelID(); }) { + assoAmpl = assoTrack.amplitude(); } else { assoAmpl = 1.0f; } + + if (!isTrackSelected(assoTrack)) + continue; + float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - assoTrack.phi(), -PIHalf); float deltaEta = triggerTrack.eta() - assoTrack.eta(); if (!mixing) { @@ -305,13 +378,13 @@ struct LongrangecorrDerived { template void processSame(TCollision const& col, TTriggers const& triggers, TAssocs const& assocs) { - if (std::abs(col.posZ()) >= cfgVtxCut) { + if (std::abs(col.posZ()) >= cfgSel.cfgVtxCut) { return; } fillCollQA(col); auto multiplicity = 1.0f; if constexpr (requires { col.centrality(); }) { - if (isUseCentEst) + if (cfgSel.isUseCentEst) multiplicity = col.centrality(); else multiplicity = col.multiplicity(); @@ -334,7 +407,7 @@ struct LongrangecorrDerived { } auto multiplicity = 1.0f; if constexpr (requires { col.centrality(); }) { - if (isUseCentEst) + if (cfgSel.isUseCentEst) multiplicity = col.centrality(); else multiplicity = col.multiplicity(); @@ -344,11 +417,11 @@ struct LongrangecorrDerived { return multiplicity; }; using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; - MixedBinning binningOnVtxAndMult{{getMultiplicity}, {axisVtxZME, axisMultME}, true}; + MixedBinning binningOnVtxAndMult{{getMultiplicity}, {cfgAxis.axisVtxZME, cfgAxis.axisMultME}, true}; auto tracksTuple = std::make_tuple(std::forward(tracks)...); using TupleAtrack = std::tuple_element<0, decltype(tracksTuple)>::type; using TupleBtrack = std::tuple_element - 1, decltype(tracksTuple)>::type; - Pair pairs{binningOnVtxAndMult, cfgNmixedevent, -1, cols, tracksTuple, &cache}; + Pair pairs{binningOnVtxAndMult, cfgSel.cfgNmixedevent, -1, cols, tracksTuple, &cache}; for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [col1, tracks1, col2, tracks2] = *it; if constexpr (requires { col1.gapSide(); } || requires { col2.gapSide(); }) { @@ -365,14 +438,14 @@ struct LongrangecorrDerived { template void processMcSame(McCollsTable::iterator const& mccollision, soa::SmallGroups const& collisions, TTriggers const& triggers, TAssocs const& assocs) { - if (std::abs(mccollision.posZ()) >= cfgVtxCut) { + if (std::abs(mccollision.posZ()) >= cfgSel.cfgVtxCut) { return; } fillCollQA(mccollision); auto multiplicity = mccollision.multiplicity(); - if (isUseDataLikeMult > 0) { + if (cfgSel.isUseDataLikeMult > 0) { for (const auto& collision : collisions) { - if (isUseCentEst) + if (cfgSel.isUseCentEst) multiplicity = collision.centrality(); else multiplicity = collision.multiplicity(); @@ -384,7 +457,7 @@ struct LongrangecorrDerived { template void processMcMixed(McCollsTable const& mccollisions, aod::LRCollisionsWithLabel const& collisions, TrackTypes&&... tracks) { - bool useMCMultiplicity = (isUseDataLikeMult == 0); + bool useMCMultiplicity = (cfgSel.isUseDataLikeMult == 0); auto getMultiplicity = [&collisions, &useMCMultiplicity, this](auto& col) { if (useMCMultiplicity) @@ -392,18 +465,18 @@ struct LongrangecorrDerived { auto groupedCollisions = collisions.sliceByCached(aod::lrcorrcolltable::lrMcCollisionId, col.globalIndex(), this->cache); if (groupedCollisions.size() == 0) return -1.0f; - if (isUseCentEst) + if (cfgSel.isUseCentEst) return groupedCollisions.begin().centrality(); else return groupedCollisions.begin().multiplicity(); }; using MixedBinning = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getMultiplicity)>; - MixedBinning binningOnVtxAndMult{{getMultiplicity}, {axisVtxZME, axisMultME}, true}; + MixedBinning binningOnVtxAndMult{{getMultiplicity}, {cfgAxis.axisVtxZME, cfgAxis.axisMultME}, true}; auto tracksTuple = std::make_tuple(std::forward(tracks)...); using TupleAtrack = std::tuple_element<0, decltype(tracksTuple)>::type; using TupleBtrack = std::tuple_element - 1, decltype(tracksTuple)>::type; - Pair pairs{binningOnVtxAndMult, cfgNmixedevent, -1, mccollisions, tracksTuple, &cache}; + Pair pairs{binningOnVtxAndMult, cfgSel.cfgNmixedevent, -1, mccollisions, tracksTuple, &cache}; for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [col1, tracks1, col2, tracks2] = *it; float eventweight = 1.0f / it.currentWindowNeighbours(); @@ -442,21 +515,6 @@ struct LongrangecorrDerived { processSame(col, tracks, mfts); } - void processTpcmftbestSE(CollsTable::iterator const& col, TrksTable const& tracks, MftbestTrksTable const& mfts) - { - processSame(col, tracks, mfts); - } - - void processMftbestft0aSE(CollsTable::iterator const& col, MftbestTrksTable const& mfts, Ft0aTrksTable const& ft0as) - { - processSame(col, mfts, ft0as); - } - - void processV0mftbestSE(CollsTable::iterator const& col, V0TrksTable const& tracks, MftbestTrksTable const& mfts) - { - processSame(col, tracks, mfts); - } - void processFt0aft0cSE(CollsTable::iterator const& col, Ft0aTrksTable const& ft0as, Ft0cTrksTable const& ft0cs) { processSame(col, ft0as, ft0cs); @@ -492,21 +550,6 @@ struct LongrangecorrDerived { processMixed(cols, tracks, mfts); } - void processTpcmftbestME(CollsTable const& cols, TrksTable const& tracks, MftbestTrksTable const& mfts) - { - processMixed(cols, tracks, mfts); - } - - void processMftbestft0aME(CollsTable const& cols, MftbestTrksTable const& mfts, Ft0aTrksTable const& ft0as) - { - processMixed(cols, mfts, ft0as); - } - - void processV0mftbestME(CollsTable const& cols, V0TrksTable const& tracks, MftbestTrksTable const& mfts) - { - processMixed(cols, tracks, mfts); - } - void processFt0aft0cME(CollsTable const& cols, Ft0aTrksTable const& ft0as, Ft0cTrksTable const& ft0cs) { processMixed(cols, ft0as, ft0cs); @@ -560,30 +603,6 @@ struct LongrangecorrDerived { processSame(col, tracks, mfts); } - void processUpcTpcmftbestSE(UpcCollsTable::iterator const& col, TrksUpcTable const& tracks, MftbestTrksUpcTable const& mfts) - { - if (!isUpcEventSelected(col)) { - return; - } - processSame(col, tracks, mfts); - } - - void processUpcMftbestft0aSE(UpcCollsTable::iterator const& col, MftbestTrksUpcTable const& mfts, Ft0aTrksUpcTable const& ft0as) - { - if (!isUpcEventSelected(col)) { - return; - } - processSame(col, mfts, ft0as); - } - - void processUpcV0mftbestSE(UpcCollsTable::iterator const& col, V0TrksUpcTable const& tracks, MftbestTrksUpcTable const& mfts) - { - if (!isUpcEventSelected(col)) { - return; - } - processSame(col, tracks, mfts); - } - void processUpcTpcft0aME(UpcCollsTable const& cols, TrksUpcTable const& tracks, Ft0aTrksUpcTable const& ft0as) { processMixed(cols, tracks, ft0as); @@ -614,21 +633,6 @@ struct LongrangecorrDerived { processMixed(cols, tracks, mfts); } - void processUpcTpcmftbestME(UpcCollsTable const& cols, TrksUpcTable const& tracks, MftbestTrksUpcTable const& mfts) - { - processMixed(cols, tracks, mfts); - } - - void processUpcMftbestft0aME(UpcCollsTable const& cols, MftbestTrksUpcTable const& mfts, Ft0aTrksUpcTable const& ft0as) - { - processMixed(cols, mfts, ft0as); - } - - void processUpcV0mftbestME(UpcCollsTable const& cols, V0TrksUpcTable const& tracks, MftbestTrksUpcTable const& mfts) - { - processMixed(cols, tracks, mfts); - } - void processMcTpcft0aSE(McCollsTable::iterator const& mccollision, soa::SmallGroups const& collisions, McTrksTable const& tracks, McFt0aTrksTable const& ft0as) { processMcSame(mccollision, collisions, tracks, ft0as); @@ -691,12 +695,6 @@ struct LongrangecorrDerived { PROCESS_SWITCH(LongrangecorrDerived, processV0ft0aME, "mixed event V0 vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processV0mftSE, "same event V0 vs MFT", false); PROCESS_SWITCH(LongrangecorrDerived, processV0mftME, "mixed event V0 vs MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processTpcmftbestSE, "same event TPC vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processTpcmftbestME, "mixed event TPC vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processMftbestft0aSE, "same event best MFT vs FT0A", false); - PROCESS_SWITCH(LongrangecorrDerived, processMftbestft0aME, "mixed event best MFT vs FT0A", false); - PROCESS_SWITCH(LongrangecorrDerived, processV0mftbestSE, "same event V0 vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processV0mftbestME, "mixed event V0 vs best MFT", false); PROCESS_SWITCH(LongrangecorrDerived, processFt0aft0cSE, "same event FT0A vs FT0C", false); PROCESS_SWITCH(LongrangecorrDerived, processFt0aft0cME, "mixed event FT0A vs FT0C", false); PROCESS_SWITCH(LongrangecorrDerived, processUpcTpcft0aSE, "same UPC event TPC vs FT0A", false); @@ -711,12 +709,6 @@ struct LongrangecorrDerived { PROCESS_SWITCH(LongrangecorrDerived, processUpcV0ft0aME, "mixed UPC event V0 vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processUpcV0mftSE, "same UPC event V0 vs MFT", false); PROCESS_SWITCH(LongrangecorrDerived, processUpcV0mftME, "mixed UPC event V0 vs MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcTpcmftbestSE, "same UPC event TPC vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcTpcmftbestME, "mixed UPC event TPC vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcMftbestft0aSE, "same UPC event best MFT vs FT0A", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcMftbestft0aME, "mixed UPC event best MFT vs FT0A", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcV0mftbestSE, "same UPC event V0 vs best MFT", false); - PROCESS_SWITCH(LongrangecorrDerived, processUpcV0mftbestME, "mixed UPC event V0 vs best MFT", false); PROCESS_SWITCH(LongrangecorrDerived, processMcTpcft0aSE, "same MC event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processMcTpcft0aME, "mixed MC event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processMcTpcft0cSE, "same MC event TPC vs FT0C", false); From d6a77490e2c93dde8931f402b228a328452994bc Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Mon, 18 May 2026 11:56:46 +0200 Subject: [PATCH 208/449] [PWGHF] update the default settings and correct the `getCandMassAndSign` in `taskPtFlucCharmHadrons.cxx` (#16230) --- PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx | 42 +++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx index f705e0ea31d..4b1b6362692 100644 --- a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx @@ -90,9 +90,9 @@ struct HfTaskPtFlucCharmHadrons { Configurable etaTrkMax{"etaTrkMax", 0.8f, "Track eta max"}; Configurable ptTrkMin{"ptTrkMin", 0.2f, "Track pT min for (charged hadrons)"}; - Configurable ptTrkMax{"ptTrkMax", 2.0f, "Track pT max for (charged hadrons)"}; - Configurable ptTrkMinD{"ptTrkMinD", 0.2f, "Track pT min for D"}; - Configurable ptTrkMaxD{"ptTrkMaxD", 2.0f, "Track pT max for D"}; + Configurable ptTrkMax{"ptTrkMax", 5.0f, "Track pT max for (charged hadrons)"}; + Configurable ptCandMin{"ptCandMin", 0.2f, "Min pT for D candidates"}; + Configurable ptCandMax{"ptCandMax", 12.0f, "Max pT for D candidates"}; Configurable minNTrk{"minNTrk", 5, "Min charged tracks in each subevent to compute "}; // Use ML in denominator AND numerator consistently @@ -128,16 +128,16 @@ struct HfTaskPtFlucCharmHadrons { ConfigurableAxis axisInvMass{"axisInvMass", {100, 1.78, 2.05}, "Inv mass axis"}; ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0}, "Candidate pT axis"}; ConfigurableAxis axisCent{"axisCent", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Centrality axis"}; - ConfigurableAxis axisSign{"axisSign", {VARIABLE_WIDTH, -1.0, 1.0}, "Sign axis"}; - ConfigurableAxis axisMlOne{"axisMlOne", {1000, 0., 1.}, ""}; - ConfigurableAxis axisMlTwo{"axisMlTwo", {100, 0., 1.}, ""}; - ConfigurableAxis axisCandEta{"axisCandEta", {20, -1., 1.}, ""}; - ConfigurableAxis axisMPtTrkA{"axisMPtTrkA", {50, 0., 5.}, ""}; - ConfigurableAxis axisMPtTrkB{"axisMPtTrkB", {50, 0., 5.}, ""}; - ConfigurableAxis axisPtCandProduct{"axisPtCandProduct", {50, 0., 50.}, ""}; - ConfigurableAxis axisPtTrkProduct{"axisPtTrkProduct", {50, 0., 25.}, ""}; - ConfigurableAxis axisNTrkA{"axisNTrkA", {2000, 0., 2000.}, ""}; - ConfigurableAxis axisNTrkB{"axisNTrkB", {2000, 0., 2000.}, ""}; + ConfigurableAxis axisSign{"axisSign", {VARIABLE_WIDTH, -1.0, 4.0}, "Sign axis"}; + ConfigurableAxis axisMlOne{"axisMlOne", {1000, 0., 1.}, "ML score 1 axis"}; + ConfigurableAxis axisMlTwo{"axisMlTwo", {100, 0., 1.}, "ML score 2 axis"}; + ConfigurableAxis axisCandEta{"axisCandEta", {16, -0.8, 0.8}, "Candidate eta axis"}; + ConfigurableAxis axisMPtTrkA{"axisMPtTrkA", {150, 0., 1.5}, "Mean pT of tracks in subevent A"}; + ConfigurableAxis axisMPtTrkB{"axisMPtTrkB", {150, 0., 1.5}, "Mean pT of tracks in subevent B"}; + ConfigurableAxis axisPtCandProduct{"axisPtCandProduct", {150, 0., 15}, "Candidate pT * mean pT of tracks (A and B) product"}; + ConfigurableAxis axisPtTrkProduct{"axisPtTrkProduct", {200, 0., 2.}, "Mean pT of tracks in A * Mean pT of tracks in B"}; + ConfigurableAxis axisNTrkA{"axisNTrkA", {2000, 0., 2000.}, "N_{tracks} in subevent A"}; + ConfigurableAxis axisNTrkB{"axisNTrkB", {2000, 0., 2000.}, "N_{tracks} in subevent B"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -222,13 +222,13 @@ struct HfTaskPtFlucCharmHadrons { } /// Get candidate mass - template - std::pair getCandMassAndSign(const CandT& cand, DecayChannel channel, Trk const& /*tracks*/) + template + std::pair getCandMassAndSign(const CandT& cand) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { return {HfHelper::invMassDplusToPiKPi(cand), cand.template prong0_as().sign()}; } - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { if (channel == DecayChannel::D0ToPiK) { return {HfHelper::invMassD0ToPiK(cand), cand.isSelD0bar() ? CandD0Type::ReflectedD0bar : CandD0Type::PureD0}; } @@ -431,7 +431,7 @@ struct HfTaskPtFlucCharmHadrons { } // get candidate mass and sign - auto [invMass, sign] = getCandMassAndSign(cand, Channel, tracks); + auto [invMass, sign] = getCandMassAndSign(cand); // fill charm-bulk correlation thnsparse registry.fill(HIST("hCharmBulkCorrelations"), invMass, cent, pt, sign, ml1, ml2, eta, meanPtA, meanPtB, candPtProduct); @@ -451,7 +451,7 @@ struct HfTaskPtFlucCharmHadrons { continue; } float pt = cand.pt(); - if (pt < ptTrkMinD.value || pt >= ptTrkMaxD.value) { + if (pt < ptCandMin.value || pt >= ptCandMax.value) { continue; } @@ -477,10 +477,10 @@ struct HfTaskPtFlucCharmHadrons { } // compute mass - auto [massCand, signCand] = getCandMassAndSign(candidate, Channel, tracks); + auto [massCand, signCand] = getCandMassAndSign(candidate); const double ptCand = candidate.pt(); - if (ptCand < ptTrkMinD.value || ptCand >= ptTrkMaxD.value) { + if (ptCand < ptCandMin.value || ptCand >= ptCandMax.value) { continue; } From a3cee132d229bcd110579f86500eee1941cdf502 Mon Sep 17 00:00:00 2001 From: akyadav1963 <84583181+akyadav1963@users.noreply.github.com> Date: Mon, 18 May 2026 16:01:16 +0530 Subject: [PATCH 209/449] [PWGLF] Changed ptmultCorr track selections to align with piKpRAA track selections (#16260) --- .../GlobalEventProperties/ptmultCorr.cxx | 116 ++++++++++++++++-- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx index e41a4055458..5cab01248e8 100644 --- a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx @@ -22,7 +22,9 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" +#include #include +#include #include #include #include @@ -36,12 +38,24 @@ #include #include +#include +#include +#include #include +#include +#include +#include #include +#include +#include #include +#include #include +#include #include +#include +#include #include using namespace o2; @@ -110,10 +124,6 @@ static constexpr TrackSelectionFlags::flagtype TrackSelectionTpc = TrackSelectionFlags::kTPCNCls | TrackSelectionFlags::kTPCCrossedRowsOverNCls | TrackSelectionFlags::kTPCChi2NDF; -static constexpr TrackSelectionFlags::flagtype TrackSelectionDca = - TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; -static constexpr TrackSelectionFlags::flagtype TrackSelectionDcaxyOnly = - TrackSelectionFlags::kDCAxy; AxisSpec axisEvent{15, 0.5, 15.5, "#Event", "EventAxis"}; AxisSpec axisVtxZ{40, -20, 20, "Vertex Z", "VzAxis"}; @@ -133,20 +143,46 @@ struct PtmultCorr { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Service pdg; + Service ccdb; Preslice perCollision = aod::track::collisionId; - Configurable etaRange{"etaRange", 1.0f, "Eta range to consider"}; + Configurable etaRange{"etaRange", 0.8f, "Eta range to consider"}; Configurable vtxRange{"vtxRange", 10.0f, "Vertex Z range to consider"}; Configurable occuRange{"occuRange", 500.0f, "Occupancy range to consider"}; - Configurable dcaZ{"dcaZ", 0.2f, "Custom DCA Z cut (ignored if negative)"}; - Configurable cfgPtCutMin{"cfgPtCutMin", 0.15f, "minimum accepted track pT"}; + Configurable cfgPtCutMin{"cfgPtCutMin", 0.1f, "minimum accepted track pT"}; + Configurable cfgPtCutMax{"cfgPtCutMax", 1e9f, "maximum accepted track pT"}; Configurable extraphicut1{"extraphicut1", 3.07666f, "Extra Phi cut 1"}; Configurable extraphicut2{"extraphicut2", 3.12661f, "Extra Phi cut 2"}; Configurable extraphicut3{"extraphicut3", 0.03f, "Extra Phi cut 3"}; Configurable extraphicut4{"extraphicut4", 6.253f, "Extra Phi cut 4"}; + + // Track quality cuts (matching piKpRAA analysis) + Configurable cfgMinNClusITS{"cfgMinNClusITS", 7, "Minimum ITS clusters"}; + Configurable cfgMinNCrossedRows{"cfgMinNCrossedRows", 70, "Minimum TPC crossed rows"}; + Configurable cfgMinNcls{"cfgMinNcls", 130, "Minimum TPC clusters (applied only if cfgApplyNclSel is true)"}; + Configurable cfgApplyNclSel{"cfgApplyNclSel", true, "Enable minimum TPC cluster selection"}; + Configurable cfgUseNclsPID{"cfgUseNclsPID", false, "Use NclsPID instead of NclsFound for the Ncls cut"}; + Configurable cfgMinChi2ClsTPC{"cfgMinChi2ClsTPC", 0.5f, "Minimum TPC chi2/cls"}; + Configurable cfgMaxChi2ClsTPC{"cfgMaxChi2ClsTPC", 4.0f, "Maximum TPC chi2/cls"}; + Configurable cfgMaxChi2ClsITS{"cfgMaxChi2ClsITS", 36.0f, "Maximum ITS chi2/cls"}; + Configurable cfgNSigmaDCAxy{"cfgNSigmaDCAxy", 1.0f, "nSigma scaling for DCAxy cut"}; + Configurable cfgNSigmaDCAz{"cfgNSigmaDCAz", 1.0f, "nSigma scaling for DCAz cut"}; + + // CCDB paths for pT-dependent DCA cuts + Configurable pathDCAxy{"pathDCAxy", "", "CCDB path for DCAxy parametrisation (leave empty to skip)"}; + Configurable pathDCAz{"pathDCAz", "", "CCDB path for DCAz parametrisation (leave empty to skip)"}; + Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable CCDB timestamp"}; + ConfigurableAxis ptHistBin{"ptHistBin", {200, 0., 20.}, ""}; ConfigurableAxis centralityBinning{"centralityBinning", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, ""}; ConfigurableAxis binsImpactPar{"binsImpactPar", {VARIABLE_WIDTH, 0.0, 3.00065, 4.28798, 6.14552, 7.6196, 8.90942, 10.0897, 11.2002, 12.2709, 13.3167, 14.4173, 23.2518}, "Binning of the impact parameter axis"}; + // DCA cache (loaded from CCDB) + struct ConfigDCA { + TH1F* hDCAxy = nullptr; + TH1F* hDCAz = nullptr; + bool loaded = false; + } cfgDCA; + Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; Configurable isApplyExtraPhiCut{"isApplyExtraPhiCut", false, "Enable extra phi cut"}; @@ -159,6 +195,19 @@ struct PtmultCorr { void init(InitContext const&) { + // Load DCA parametrisations from CCDB (matching piKpRAA) + if (!pathDCAxy.value.empty()) { + cfgDCA.hDCAxy = ccdb->getForTimeStamp(pathDCAxy, ccdbNoLaterThan); + if (cfgDCA.hDCAxy == nullptr) + LOGF(fatal, "Could not load DCAxy histogram from %s", pathDCAxy.value.c_str()); + } + if (!pathDCAz.value.empty()) { + cfgDCA.hDCAz = ccdb->getForTimeStamp(pathDCAz, ccdbNoLaterThan); + if (cfgDCA.hDCAz == nullptr) + LOGF(fatal, "Could not load DCAz histogram from %s", pathDCAz.value.c_str()); + } + if (cfgDCA.hDCAxy && cfgDCA.hDCAz) + cfgDCA.loaded = true; AxisSpec centAxis = {centralityBinning, "Centrality", "CentralityAxis"}; AxisSpec axisPt = {ptHistBin, "pT", "pTAxis"}; AxisSpec impactParAxis = {binsImpactPar, "Impact Parameter"}; @@ -290,9 +339,59 @@ struct PtmultCorr { template bool isTrackSelected(CheckTrack const& track) { + // --- eta (applied to all track types) --- if (std::abs(track.eta()) >= etaRange) { return false; } + + // --- pT (applied to all track types) --- + if (track.pt() < cfgPtCutMin || track.pt() > cfgPtCutMax) { + return false; + } + + if (track.hasTPC()) { + // ---- Global (ITS+TPC) tracks: + + // ITS inner-barrel hit: must fire layer 0 or layer 1 + if (!(track.itsClusterMap() & 0x01) && !(track.itsClusterMap() & 0x02)) { + return false; + } + if (track.itsNCls() < cfgMinNClusITS) { + return false; + } + if (track.tpcNClsCrossedRows() < cfgMinNCrossedRows) { + return false; + } + // optional minimum TPC clusters (found or PID, matching piKpRAA applyNclSel) + if (cfgApplyNclSel) { + const int16_t ncl = cfgUseNclsPID ? track.tpcNClsPID() : track.tpcNClsFound(); + if (ncl < cfgMinNcls) { + return false; + } + } + if (track.tpcChi2NCl() < cfgMinChi2ClsTPC || track.tpcChi2NCl() > cfgMaxChi2ClsTPC) { + return false; + } + if (track.itsChi2NCl() > cfgMaxChi2ClsITS) { + return false; + } + // pT-dependent DCA cuts from CCDB + if (cfgDCA.loaded) { + const float pt = track.pt(); + const double dcaXYcut = cfgNSigmaDCAxy * (cfgDCA.hDCAxy->GetBinContent(1) + + cfgDCA.hDCAxy->GetBinContent(2) / + std::pow(std::abs(pt), cfgDCA.hDCAxy->GetBinContent(3))); + const double dcaZcut = cfgNSigmaDCAz * (cfgDCA.hDCAz->GetBinContent(1) + + cfgDCA.hDCAz->GetBinContent(2) / + std::pow(std::abs(pt), cfgDCA.hDCAz->GetBinContent(3))); + if (std::abs(track.dcaZ()) > dcaZcut || std::abs(track.dcaXY()) > dcaXYcut) { + return false; + } + } + } + // ITS-only tracks: quality already ensured by the framework-level fTrackSelectionITS filter + + // --- optional phi cut (applied to all track types) --- histos.fill(HIST("PhiVsEtaHistNoCut"), track.phi(), track.eta()); if (isApplyExtraPhiCut && ((track.phi() > extraphicut1 && track.phi() < extraphicut2) || track.phi() <= extraphicut3 || track.phi() >= extraphicut4)) { return false; @@ -330,8 +429,7 @@ struct PtmultCorr { ncheckbit(aod::track::trackCutFlag, TrackSelectionIts); Filter fTrackSelectionTPC = ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), ncheckbit(aod::track::trackCutFlag, TrackSelectionTpc), true); - Filter fTrackSelectionDCA = ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDcaxyOnly), - ncheckbit(aod::track::trackCutFlag, TrackSelectionDca)); + // DCA is now applied manually inside isTrackSelected() using pT-dependent CCDB parametrisation Filter fTracksPt = aod::track::pt > cfgPtCutMin; void processDataPbPb(ColDataTablePbPb::iterator const& cols, FilTrackDataTable const& tracks) From 509a9adc4d2c1def0fe0de94705fb558ebbac760 Mon Sep 17 00:00:00 2001 From: Rocco Liotino Date: Mon, 18 May 2026 12:53:06 +0200 Subject: [PATCH 210/449] [DPG] major_update_producer (#16257) --- DPG/Tasks/AOTTrack/PID/HMPID/CMakeLists.txt | 2 +- .../AOTTrack/PID/HMPID/hmpidTableProducer.cxx | 352 +++++++++++++++--- 2 files changed, 309 insertions(+), 45 deletions(-) diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/CMakeLists.txt b/DPG/Tasks/AOTTrack/PID/HMPID/CMakeLists.txt index 96bb9ab18c4..d33a73eb12f 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/CMakeLists.txt +++ b/DPG/Tasks/AOTTrack/PID/HMPID/CMakeLists.txt @@ -17,7 +17,7 @@ o2physics_add_dpl_workflow(hmpid-qa o2physics_add_dpl_workflow(hmpid-table-producer SOURCES hmpidTableProducer.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::HMPIDBase COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hmpid-deuteron diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx index 1b6cea53ef5..58438690781 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx @@ -19,17 +19,21 @@ #include "Common/DataModel/TrackSelectionTables.h" #include -#include +#include +#include +#include +#include #include -#include #include -#include #include -#include -#include -#include #include +#include + +#include + +#include +#include #include #include #include @@ -40,50 +44,238 @@ using namespace o2::framework::expressions; using namespace o2::constants::physics; struct HmpidTableProducer { + + Produces hmpidAnalysis; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; const AxisSpec axisEvtCounter{1, 0, +1, ""}; - // CCDB configurable Service ccdb; struct : ConfigurableGroup { Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "URL of the CCDB repository"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the material LUT"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the aligned geometry"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of GRPMagField"}; } ccdbConfig; - Produces hmpidAnalysis; - - // configurable for quality requirements + // ----------------------------------------------------------------------- + // Quality configurables + // ----------------------------------------------------------------------- Configurable requireITS{"requireITS", true, "Require ITS track"}; Configurable requireTPC{"requireTPC", true, "Require TPC track"}; Configurable requireTOF{"requireTOF", true, "Require TOF track"}; using CollisionCandidates = o2::soa::Join; - using TrackCandidates = soa::Join; + using TrackCandidates = soa::Join; void init(o2::framework::InitContext&) { - // Configure CCDB ccdb->setURL(ccdbConfig.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - histos.add("eventCounter", "eventCounter", kTH1F, {axisEvtCounter}); - histos.add("goodEventCounter", "goodEventCounter", kTH1F, {axisEvtCounter}); - histos.add("eventsHmpid", "eventsWithHmpid", kTH1F, {axisEvtCounter}); + // event counters + histos.add("eventCounter", "All events", kTH1F, {axisEvtCounter}); + histos.add("goodEventCounter", "Events passing sel8", kTH1F, {axisEvtCounter}); + histos.add("eventsHmpid", "Events with HMPID track", kTH1F, {axisEvtCounter}); + + // chamber extraction quality checks - M1 propagation, M2 clusSize encoding, M3 hybrid configuration + const AxisSpec axisCh{10, -1.5, 8.5, "Chamber"}; + histos.add("hChamberM1", "Chamber M1 (propagation)", kTH1F, {axisCh}); + histos.add("hChamberM2", "Chamber M2 (clusSize encoding)", kTH1F, {axisCh}); + histos.add("hChamberM3", "Chamber M3 (hybrid, in table)", kTH1F, {axisCh}); + + histos.add("hChamberM1vsM2", "M1 vs M2; M2; M1", kTH2F, {axisCh, axisCh}); + histos.add("hChamberM3vsM2", "M3 vs M2; M2; M3", kTH2F, {axisCh, axisCh}); + + histos.add("hClusSize", "Raw hmpidClusSize", kTH1F, {{500, -1.1e6, 1e6, "clusSize"}}); + histos.add("hClusSizeCorrupt", "Corrupt entries (<=0)", kTH1F, {{200, -1.1e6, 1., "clusSize"}}); + + histos.add("hChamberAssignment", + "Chamber assignment outcome; category; counts", + kTH1F, {{4, -0.5, 3.5, ""}}); } - // function to manage ccdb + // ----------------------------------------------------------------------- + // CCDB initialisation per run + // ----------------------------------------------------------------------- int mCCDBRunNumber = 0; + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { if (mCCDBRunNumber == bc.runNumber()) { return; } mCCDBRunNumber = bc.runNumber(); + + auto grpMag = ccdb->getForTimeStamp( + ccdbConfig.grpmagPath, bc.timestamp()); + if (!grpMag) { + LOGF(fatal, "initCCDB: GRPMagField not found at %s", + ccdbConfig.grpmagPath.value.c_str()); + return; + } + o2::base::Propagator::initFieldFromGRP(grpMag); + + auto lut = o2::base::MatLayerCylSet::rectifyPtrFromFile( + ccdb->get(ccdbConfig.lutPath)); + o2::base::Propagator::Instance()->setMatLUT(lut); + + // Geometry needed by o2::hmpid::Param for mars2Lors + if (!gGeoManager) { + ccdb->get(ccdbConfig.geoPath); + } + + LOGF(info, "initCCDB: run %d initialised (mag + LUT + geo)", bc.runNumber()); + } + + void propagateHelix( + double len, + double bz, + int charge, + std::array& x, + std::array& p) + { + // Extrapolate track along simple helix in magnetic field + + constexpr double KB2C = 0.299792458e-3; + + double px = p[0]; + double py = p[1]; + double pz = p[2]; + + double pmod = std::hypot(px, py, pz); + double pt = std::hypot(px, py); + + if (pt < o2::constants::math::Almost0 || std::abs(bz) < o2::constants::math::Almost0) // straight-line tracks + { + x[0] += px / pmod * len; + x[1] += py / pmod * len; + x[2] += pz / pmod * len; + + return; + } + + double a = -KB2C * bz * charge; + double rho = a / pmod; + + double sinr = std::sin(rho * len); + double cosr = std::cos(rho * len); + + x[0] += px * sinr / a - py * (1. - cosr) / a; + x[1] += py * sinr / a + px * (1. - cosr) / a; + x[2] += pz * len / pmod; + + double px0 = px; + + p[0] = px0 * cosr - py * sinr; + p[1] = py * cosr + px0 * sinr; + p[2] = pz; + } + + bool intersectHelixPlane( + double bz, + int charge, + const std::array& x0, + const std::array& p0, + const std::array& planePoint, + const std::array& planeNormal, + std::array& xOut, + std::array& pOut) + { + // Intersect a helix with a plane defined by normals and points, using an iterative approach. + + double s = + (planePoint[0] - x0[0]) * planeNormal[0] + + (planePoint[1] - x0[1]) * planeNormal[1] + + (planePoint[2] - x0[2]) * planeNormal[2]; + + double dist = 99999., distPrev = dist; + + const double kConvThr = 0.00001; + const int kMaxIter = 100; + + std::array x, p; + + for (int iter = 0; iter < kMaxIter; ++iter) { + + x = x0; + p = p0; + propagateHelix(s, bz, charge, x, p); + + dist = + (x[0] - planePoint[0]) * planeNormal[0] + + (x[1] - planePoint[1]) * planeNormal[1] + + (x[2] - planePoint[2]) * planeNormal[2]; + + if (std::abs(dist) >= std::abs(distPrev)) + return false; + + distPrev = dist; + s -= dist; + + if (std::abs(dist) < kConvThr) { + xOut = x; + pOut = p; + return true; + } + } + + return false; + } + + int getHmpidChamber( + std::array x, + std::array p, + double bz, + int charge) + { + auto* param = o2::hmpid::Param::instance(); + + for (int ch = o2::hmpid::Param::kMinCh; ch <= o2::hmpid::Param::kMaxCh; ++ch) { + + // Chamber module geometry: points and normals for radiators and PCs + std::array pRad{}, pPc{}; + std::array nRad{}, nPc{}; + + param->point(ch, pRad.data(), o2::hmpid::Param::kRad); + param->norm(ch, nRad.data()); + param->point(ch, pPc.data(), o2::hmpid::Param::kPc); + param->norm(ch, nPc.data()); + + // Intersection track - radiator plane + std::array xRad, pAtRad; + + if (!intersectHelixPlane(bz, charge, x, p, pRad, nRad, xRad, pAtRad)) + continue; + + // Intersection track - PC plane + std::array xPc, pAtPc; + + if (!intersectHelixPlane(bz, charge, xRad, pAtRad, pPc, nPc, xPc, pAtPc)) + continue; + + double theta, phi; + param->mars2LorsVec(ch, pAtRad.data(), theta, phi); + + double xL, yL; + param->mars2Lors(ch, xPc.data(), xL, yL); + + // Use isInside to check Chamber intersected + if (param->isInside(xL, yL, param->distCut())) + return ch; + } + + // No chamber intersected + return -1; } void processEvent(CollisionCandidates::iterator const& col, @@ -93,11 +285,9 @@ struct HmpidTableProducer { if (col.sel8()) { histos.fill(HIST("goodEventCounter"), 0.5); } - - // initialize CCDB for current BC initCCDB(col.bc_as()); } - PROCESS_SWITCH(HmpidTableProducer, processEvent, "Process event level - collisions", true); + PROCESS_SWITCH(HmpidTableProducer, processEvent, "Process event level", true); void processHmpid( aod::HMPIDs const& hmpids, @@ -105,60 +295,134 @@ struct HmpidTableProducer { CollisionCandidates const&, aod::BCsWithTimestamps const&) { - // --- Static set to track unique collisions with HMPID tracks --- static std::unordered_set collisionsWithHmpid; for (auto const& t : hmpids) { - // Access the global track associated to the HMPID track const auto& globalTrack = t.track_as(); if (!globalTrack.has_collision()) continue; - // Access the associated collision const auto& col = globalTrack.collision_as(); initCCDB(col.bc_as()); uint32_t collId = col.globalIndex(); - // --- Track quality selection --- + // Track quality selection if ((requireITS && !globalTrack.hasITS()) || (requireTPC && !globalTrack.hasTPC()) || (requireTOF && !globalTrack.hasTOF())) { continue; } - // Count collisions with at least one valid HMPID track if (collisionsWithHmpid.insert(collId).second) { histos.fill(HIST("eventsHmpid"), 0.5); } - float centrality = col.centFV0A(); + // clusSize diagnostics + histos.fill(HIST("hClusSize"), t.hmpidClusSize()); + bool isCorrupt = (t.hmpidClusSize() <= 0); + if (isCorrupt) { + histos.fill(HIST("hClusSizeCorrupt"), t.hmpidClusSize()); + } + + // --- M2: clusSize encoding --- + int chamberM2 = t.hmpidClusSize() / 1000000; + histos.fill(HIST("hChamberM2"), chamberM2); + + // --- M1: propagation + // obtain global coordinates + double sinA = std::sin(globalTrack.alpha()); + double cosA = std::cos(globalTrack.alpha()); + + std::array x = { + globalTrack.x() * cosA - globalTrack.y() * sinA, + globalTrack.x() * sinA + globalTrack.y() * cosA, + static_cast(globalTrack.z())}; + + std::array p = { + static_cast(globalTrack.px()), + static_cast(globalTrack.py()), + static_cast(globalTrack.pz())}; + + // int charge = (globalTrack.signed1Pt() > 0) ? +1 : -1; + int16_t charge = globalTrack.sign(); + + auto prop = o2::base::Propagator::Instance(); + double bz = static_cast(prop->getNominalBz()); // positive sign + + int chamberM1 = getHmpidChamber(x, p, bz, charge); + + histos.fill(HIST("hChamberM1"), chamberM1); + + if (!isCorrupt) { + histos.fill(HIST("hChamberM1vsM2"), chamberM2, chamberM1); + } + + // --- M3: hybrid --- + int chamberM3 = -1; + if (!isCorrupt) { + chamberM3 = chamberM2; + } else { + chamberM3 = chamberM1; + } + + // Legend: + // bin 0 = clusSize > 0, chamber found (M2 ok) + // bin 1 = clusSize > 0, chamber not found (non dovrebbe mai accadere) + // bin 2 = clusSize <= 0, M1 recovery (corrupt, M1 ok) + // bin 3 = clusSize <= 0, M1 fails (corrupt, skipped) + + if (!isCorrupt && chamberM3 >= 0) { + histos.fill(HIST("hChamberAssignment"), 0.); + } else if (!isCorrupt && chamberM3 < 0) { + histos.fill(HIST("hChamberAssignment"), 1.); + } else if (isCorrupt && chamberM3 >= 0) { + histos.fill(HIST("hChamberAssignment"), 2.); + } else { + histos.fill(HIST("hChamberAssignment"), 3.); + } - // check cluster size sign - if (t.hmpidClusSize() <= 0) + histos.fill(HIST("hChamberM3"), chamberM3); + histos.fill(HIST("hChamberM3vsM2"), chamberM2, chamberM3); + + // Skip track if chamber undetermined + if (chamberM3 < 0) { continue; + } + // Fill photon charges float hmpidPhotsCharge2[o2::aod::kDimPhotonsCharge]; - for (int i = 0; i < o2::aod::kDimPhotonsCharge; i++) { hmpidPhotsCharge2[i] = t.hmpidPhotsCharge()[i]; } - /////FILL HMPID CUSTOM TABLE - hmpidAnalysis(t.hmpidSignal(), t.hmpidMom(), - globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), - t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, - t.hmpidClusSize() / 1000000, hmpidPhotsCharge2, globalTrack.eta(), globalTrack.phi(), - globalTrack.px(), globalTrack.py(), globalTrack.pz(), globalTrack.itsNCls(), - globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), - globalTrack.dcaXY(), globalTrack.dcaZ(), globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), - globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), - globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), centrality); - } // end loop on hmpid table entries - } + // Fill output table + hmpidAnalysis( + t.hmpidSignal(), t.hmpidMom(), + globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), + t.hmpidXMip(), t.hmpidYMip(), + t.hmpidNPhotons(), t.hmpidQMip(), + (t.hmpidClusSize() % 1000000) / 1000, + chamberM3, + hmpidPhotsCharge2, + globalTrack.eta(), globalTrack.phi(), + globalTrack.px(), globalTrack.py(), globalTrack.pz(), + globalTrack.itsNCls(), globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), + globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), + globalTrack.dcaXY(), globalTrack.dcaZ(), + globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), + globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), + globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), + globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), + col.centFV0A()); - PROCESS_SWITCH(HmpidTableProducer, processHmpid, "Process hmpid entries - tracks", true); + } // end HMPID loop + } + PROCESS_SWITCH(HmpidTableProducer, processHmpid, "Process HMPID entries", true); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { return WorkflowSpec{adaptAnalysisTask(cfg)}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{adaptAnalysisTask(cfg)}; +} From a084847798293f3cb62b25f6b222997e4f148c7c Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Mon, 18 May 2026 13:24:32 +0200 Subject: [PATCH 211/449] [PWGLF] Jet reconstruction with V0s + MC models process function + Event loss, splitting (#16284) --- .../Strangeness/strangenessInJetsIons.cxx | 655 +++++++++++++++++- 1 file changed, 636 insertions(+), 19 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index 477b1138515..a89040cc729 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -69,6 +69,8 @@ #include #include #include +#include +#include #include using namespace std; @@ -131,6 +133,7 @@ struct StrangenessInJetsIons { Configurable triggerName{"triggerName", "fOmega", "Software trigger name"}; Configurable centrEstimator{"centrEstimator", 1, "Select centrality estimator. Options: 0 = FT0C, 1 = FT0M. CCDB objects available only for FT0M."}; Configurable calculateFeeddownMatrix{"calculateFeeddownMatrix", true, "Fill feeddown matrix for Lambda if MC"}; + Configurable useV0inJetRec{"useV0inJetRec", true, "Include V0s in jet reconstruction"}; // Event selection Configurable requireNoSameBunchPileup{"requireNoSameBunchPileup", true, "Require kNoSameBunchPileup selection"}; @@ -335,7 +338,10 @@ struct StrangenessInJetsIons { } // Histograms for mc generated - if (doprocessMCgenerated) { + if (doprocessMCgenerated || doprocessMCmodels) { + if (doprocessMCgenerated && doprocessMCmodels) { + LOG(fatal) << "processMCgenerated and processMCmodels cannot be selected at the same time. Exit." << endl; + } // Event counter registryMC.add("number_of_events_mc_gen", "number of gen events in mc", HistType::kTH1D, {{10, 0, 10, "Event Cuts"}}); @@ -347,9 +353,11 @@ struct StrangenessInJetsIons { // Add histogram to store multiplicity of the event registryMC.add("number_of_events_vsmultiplicity_gen", "number of events vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + registryMC.add("number_of_events_vsmultiplicity_gen_w_reco", "number of events vs multiplicity (gen with reco)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); // For MB registryMC.add("number_of_events_vsmultiplicity_gen_MB", "number of events vs multiplicity (MB)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + registryMC.add("number_of_events_vsmultiplicity_gen_w_reco_MB", "number of events vs multiplicity (MB gen with reco)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); // Jet counters registryMC.add("n_jets_vs_mult_pT_mc_gen", "n_jets_vs_mult_pT_mc_gen", HistType::kTH2F, {multAxis, ptJetAxis}); @@ -559,6 +567,12 @@ struct StrangenessInJetsIons { return deltaPhi; } + // Compute energy + double GetEnergy(double px, double py, double pz, double mass) + { + return std::sqrt(px * px + py * py + pz * pz + mass * mass); + } + // Check if particle is a physical primary or a decay product of a heavy-flavor hadron bool isPhysicalPrimaryOrFromHF(aod::McParticle const& particle, aod::McParticles const& mcParticles) { @@ -1188,9 +1202,9 @@ struct StrangenessInJetsIons { return std::abs(yParticle) < rapidityCut; } - void FillFullEventHistoMCGEN(aod::McParticle const& particle, - const double& genMultiplicity, - bool hasReco = false) + void FillMBEventHistoMCGEN(aod::McParticle const& particle, + const double& genMultiplicity, + bool hasReco = false) { if (particle.isPhysicalPrimary() && passedRapidityCut(particle.y(), configV0.rapidityMax)) { switch (particle.pdgCode()) { @@ -1276,12 +1290,12 @@ struct StrangenessInJetsIons { // Fill Minimum Bias histograms template - void FillFullEventHistoMCREC(MCRecoCollision collision, - aod::McParticles const& mcParticles, - V0PerColl const& v0sPerColl, - CascPerColl const& cascPerColl, - TracksPerColl const& tracksPerColl, - const double& multiplicity) + void FillMBEventHistoMCREC(MCRecoCollision collision, + aod::McParticles const& mcParticles, + V0PerColl const& v0sPerColl, + CascPerColl const& cascPerColl, + TracksPerColl const& tracksPerColl, + const double& multiplicity) { // V0 particles if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -1525,11 +1539,292 @@ struct StrangenessInJetsIons { } } + /** + * @brief Identifies the index of the common mother for two MC particles. + * + * @tparam T Type of the MC particle objects + * @param posParticle MC particle associated with the positive daughter + * @param negParticle MC particle associated with the negative daughter + * @return int The index of the common mother, or -1 if no common mother exists. + */ + template + int GetCommonMotherId(aod::McParticles const& mcParticles, + const T& posParticle, const T& negParticle) + { + int motherIdPos = posParticle.mothersIds()[0]; + int motherIdNeg = negParticle.mothersIds()[0]; + + const auto& motherPos = mcParticles.iteratorAt(motherIdPos); + const auto& motherNeg = mcParticles.iteratorAt(motherIdNeg); + if (motherPos != motherNeg) { + return -1; // Return -1 if they originate from different parents + } + + return motherIdPos; // Return mother ID + } + + /** + * Returns true if the track is a daughter of the V0 candidate + * Adapted from: PWGJE/Core/JetV0Utilities.h + * + * @param track track that is being checked + * @param candidate V0 candidate that is being checked + */ + template + bool isV0DaughterTrack(T& track, U& candidate) + { + if (candidate.posTrackId() == track.globalIndex() || candidate.negTrackId() == track.globalIndex()) { + return true; + } else { + return false; + } + } + + /** + * @brief Add V0s as input for the jet finder algorithm in DATA + * + * @tparam Track + * @tparam V0PerColl The container type holding the sliced V0 candidates for the current collision. + * + * @param[in,out] fjInput Vector of FastJet PseudoJets where valid V0s will be appended. + * @param[in] fjTracks Vector containing tracks already selected for jet finder input. + * @param[in] v0sPerColl V0 candidates belonging to this specific collision. + * @param[in] vtxPos TVector3 object representing the vertex position. + */ + template + void AddV0sForJetReconstructionData(std::vector& fjInput, + const std::vector& fjTracks, + V0PerColl const& v0sPerColl, + const TVector3& vtxPos) + { + // Vector of labels: if true remove the element from fjInput + std::vector isTrackReplaced(fjTracks.size(), false); + std::vector v0PseudoJets; // V0s to use as input for jet finder + + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.template posTrack_as(); + const auto& neg = v0.template negTrack_as(); + + bool isK0S = false, isLambda = false, isAntiLambda = false; + // K0s + if (passedK0ShortSelection(v0, pos, neg, vtxPos)) { + // LOG(info) << "[AddV0sForJetReconstructionData] Add K0S as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassK0Short); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isK0S = true; + } + // Lambda + if (passedLambdaSelection(v0, pos, neg, vtxPos)) { + // LOG(info) << "[AddV0sForJetReconstructionData] Add Lambda as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassLambda0); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isLambda = true; + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg, vtxPos)) { + // LOG(info) << "[AddV0sForJetReconstructionData] Add AntiLambda as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassLambda0Bar); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isAntiLambda = true; + } + + // Exclude daughter tracks in case a V0 is found + bool isV0 = isK0S || isLambda || isAntiLambda; + if (!isV0) + continue; + for (int i = 0; i < int(fjTracks.size()); ++i) { + if (isV0DaughterTrack(fjTracks[i], v0)) { + // LOG(info) << "[AddV0sForJetReconstructionData] V0 daughter track found in fjTracks."; + isTrackReplaced[i] = true; + } + } + } + + std::vector cleanFjInput; + cleanFjInput.reserve(fjInput.size()); + for (int i = 0; i < int(fjInput.size()); ++i) { + if (!isTrackReplaced[i]) + cleanFjInput.push_back(fjInput[i]); + } + for (const auto& v0pj : v0PseudoJets) { + cleanFjInput.push_back(v0pj); + } + // LOG(info) << "[AddV0sForJetReconstructionData] Size fjInput: " << fjInput.size(); + fjInput = std::move(cleanFjInput); + // LOG(info) << "[AddV0sForJetReconstructionData] Size fjInput dopo move: " << fjInput.size(); + } + + /** + * @brief Add V0s as input for the jet finder algorithm in MC reco (detector level) + * + * @tparam Track + * @tparam V0PerColl The container type holding the sliced V0 candidates for the current collision. + * + * @param[in,out] fjInput Vector of FastJet PseudoJets where valid V0s will be appended. + * @param[in] fjTracks Vector containing tracks already selected for jet finder input. + * @param[in] v0sPerColl Sliced V0 candidates belonging to this specific collision. + * @param[in] mcParticles Global MC particles table used to look up mother particle truth information. + * @param[in] vtxPos TVector3 object representing the vertex position. + */ + template + void AddV0sForJetReconstructionMCD(std::vector& fjInput, + const std::vector& fjTracks, + V0PerColl const& v0sPerColl, + aod::McParticles const& mcParticles, + const TVector3& vtxPos) + { + // Vector of labels: if true remove the element from fjInput + std::vector isTrackReplaced(fjTracks.size(), false); + std::vector v0PseudoJets; // V0s to use as input for jet finder + + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.template posTrack_as(); + const auto& neg = v0.template negTrack_as(); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) { + continue; + } + const auto& posParticle = pos.template mcParticle_as(); + const auto& negParticle = neg.template mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) { + continue; + } + + // Select particles originating from the same parent + int motherId = GetCommonMotherId(mcParticles, posParticle, negParticle); + if (motherId < 0) + continue; // if motherId is -1, it means no common mother was found + const auto& mother = mcParticles.iteratorAt(motherId); + const bool isPhysPrim = mother.isPhysicalPrimary(); + int pdgParent = mother.pdgCode(); + + /// NOTE: V0s are required to be primary particles; + bool isK0S = false, isLambda = false, isAntiLambda = false; + // K0s + if (passedK0ShortSelection(v0, pos, neg, vtxPos) && pdgParent == kK0Short && isPhysPrim) { + // LOG(info) << "[AddV0sForJetReconstructionMCD] Add K0S as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassK0Short); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isK0S = true; + } + // Lambda + if (passedLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0 && isPhysPrim) { + // LOG(info) << "[AddV0sForJetReconstructionMCD] Add Lambda as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassLambda0); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isLambda = true; + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0Bar && isPhysPrim) { + // LOG(info) << "[AddV0sForJetReconstructionMCD] Add AntiLambda as input for jet finder."; + double energy = GetEnergy(v0.px(), v0.py(), v0.pz(), o2::constants::physics::MassLambda0Bar); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + v0PseudoJets.emplace_back(fourMomentum); + isAntiLambda = true; + } + + // Exclude daughter tracks in case a V0 is found + bool isV0 = isK0S || isLambda || isAntiLambda; + if (!isV0) + continue; + for (int i = 0; i < int(fjTracks.size()); ++i) { + if (isV0DaughterTrack(fjTracks[i], v0)) { + // LOG(info) << "[AddV0sForJetReconstructionMCD] V0 daughter track found in fjTracks."; + isTrackReplaced[i] = true; + } + } + } + + std::vector cleanFjInput; + cleanFjInput.reserve(fjInput.size()); + for (int i = 0; i < int(fjInput.size()); ++i) { + if (!isTrackReplaced[i]) + cleanFjInput.push_back(fjInput[i]); + } + for (const auto& v0pj : v0PseudoJets) { + cleanFjInput.push_back(v0pj); + } + // LOG(info) << "[AddV0sForJetReconstructionMCD] Size fjInput: " << fjInput.size(); + fjInput = std::move(cleanFjInput); + // LOG(info) << "[AddV0sForJetReconstructionMCD] Size fjInput dopo move: " << fjInput.size(); + } + + /** + * @brief Add V0s as input for the jet finder algorithm at Particle Level (MC Generated) + * + * @tparam McParticleType + * @tparam ParticleColl The container type holding the sliced MC particles. + * + * @param[in,out] fjInput Vector of FastJet PseudoJets where V0s will be appended. + * @param[in] fjParticleObj Vector containing the MC particles already selected for jet finder input. + * @param[in] mcParticlesPerColl MC particles belonging to this specific collision. + * @param[in] mcParticles Full McParticles. + */ + template + void AddV0sForJetReconstructionMCP(std::vector& fjInput, + const std::vector& fjParticleObj, + ParticleColl const& mcParticlesPerColl, + aod::McParticles const& mcParticles) + { + std::vector isTrackReplaced(fjParticleObj.size(), false); + std::vector v0PseudoJets; + + // Add V0s to the input list for the jet finder and eventually remove their daughter particles + for (const auto& p : mcParticlesPerColl) { + int pdgAbs = std::abs(p.pdgCode()); + /// NOTE: p.isPhysicalPrimary() is required + if (p.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0)) { + double mass = (pdgAbs == kK0Short) ? o2::constants::physics::MassK0Short : o2::constants::physics::MassLambda0; + double energy = std::sqrt(p.p() * p.p() + mass * mass); + + fastjet::PseudoJet pj(p.px(), p.py(), p.pz(), energy); + pj.set_user_index(p.pdgCode()); + v0PseudoJets.push_back(pj); + // LOG(info) << "[AddV0sForJetReconstructionMCP] Add V0 as input for jet finder."; + + // Remove V0 daughter particles if already in the input list for the jet finder + for (int i = 0; i < int(fjParticleObj.size()); ++i) { + const auto& mcPart = fjParticleObj[i]; + if (!mcPart.has_mothers()) + continue; + auto mother = mcParticles.iteratorAt(mcPart.mothersIds()[0]); + int motherPdg = std::abs(mother.pdgCode()); + if (motherPdg == kK0Short || motherPdg == kLambda0) { + isTrackReplaced[i] = true; + // LOG(info) << "[AddV0sForJetReconstructionMCP] V0 daughter particle found in fjParticleObj."; + } + } + } + } + + std::vector cleanFjInput; + cleanFjInput.reserve(fjInput.size()); + for (int i = 0; i < int(fjInput.size()); ++i) { + if (!isTrackReplaced[i]) + cleanFjInput.push_back(fjInput[i]); + } + for (const auto& v0pj : v0PseudoJets) { + cleanFjInput.push_back(v0pj); + } + // LOG(info) << "[AddV0sForJetReconstructionMCP] Size fjInput: " << fjInput.size(); + fjInput = std::move(cleanFjInput); + // LOG(info) << "[AddV0sForJetReconstructionMCP] Size fjInput dopo move: " << fjInput.size(); + } + // Process data void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, DaughterTracks const& tracks, aod::BCsWithTimestamps const&) { + // Vertex position vector + TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); + // Fill event counter before event selection registryData.fill(HIST("number_of_events_data"), 0.5); @@ -1586,6 +1881,7 @@ struct StrangenessInJetsIons { // Loop over reconstructed tracks std::vector fjParticles; + std::vector> fjTracks; for (auto const& track : tracks) { // Require that tracks pass selection criteria @@ -1595,7 +1891,14 @@ struct StrangenessInJetsIons { // 4-momentum representation of a particle fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); fjParticles.emplace_back(fourMomentum); + fjTracks.push_back(track); + } + + // Include V0s as tracks for jet reconstruction + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionData(fjParticles, fjTracks, fullV0s, vtxPos); } + fjTracks.clear(); // Reject empty events if (fjParticles.size() < 1) @@ -1687,9 +1990,6 @@ struct StrangenessInJetsIons { const float deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); const float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Vertex position vector - TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); - // Fill Armenteros-Podolanski TH2 // registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); @@ -1914,11 +2214,14 @@ struct StrangenessInJetsIons { genMultiplicity = collision.centFT0M(); } registryMC.fill(HIST("number_of_events_vsmultiplicity_gen_MB"), genMultiplicity); + if (hasReco) + registryMC.fill(HIST("number_of_events_vsmultiplicity_gen_w_reco_MB"), genMultiplicity); // MC particles per collision auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); // Loop over all MC particles and select physical primaries within acceptance + std::vector> fjParticleObj; for (const auto& particle : mcParticlesPerColl) { // Store properties of strange hadrons int pdgAbs = std::abs(particle.pdgCode()); @@ -1931,7 +2234,7 @@ struct StrangenessInJetsIons { if (particle.eta() < configTracks.etaMin || particle.eta() > configTracks.etaMax || particle.pt() < minPtParticle) continue; - FillFullEventHistoMCGEN(particle, genMultiplicity, hasReco); + FillMBEventHistoMCGEN(particle, genMultiplicity, hasReco); // Select physical primary particles or HF decay products if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) @@ -1943,6 +2246,11 @@ struct StrangenessInJetsIons { fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); fourMomentum.set_user_index(particle.pdgCode()); fjParticles.emplace_back(fourMomentum); + fjParticleObj.push_back(particle); + } + + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionMCP(fjParticles, fjParticleObj, mcParticlesPerColl, mcParticles); } // Skip events with no particles @@ -1975,6 +2283,8 @@ struct StrangenessInJetsIons { countSelJet++; registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_gen"), genMultiplicity); + if (hasReco) + registryMC.fill(HIST("number_of_events_vsmultiplicity_gen_w_reco"), genMultiplicity); // Fill jet counter registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); @@ -2182,6 +2492,9 @@ struct StrangenessInJetsIons { const auto& mcCollision = collision.mcCollision_as>(); + // Vertex position vector + TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); + // Clear containers at the start of the event loop fjParticles.clear(); selectedJet.clear(); @@ -2230,10 +2543,11 @@ struct StrangenessInJetsIons { auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mcCollision.globalIndex()); - FillFullEventHistoMCREC(collision, mcParticles, v0sPerColl, - cascPerColl, tracksPerColl, multiplicity); + FillMBEventHistoMCREC(collision, mcParticles, v0sPerColl, + cascPerColl, tracksPerColl, multiplicity); // Loop over reconstructed tracks + std::vector> fjTracks; for (auto const& track : tracksPerColl) { if (!passedTrackSelectionForJetReconstruction(track)) continue; @@ -2241,7 +2555,14 @@ struct StrangenessInJetsIons { // 4-momentum representation of a particle fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); fjParticles.emplace_back(fourMomentum); + fjTracks.push_back(track); + } + + // Include V0s as tracks for jet reconstruction + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionMCD(fjParticles, fjTracks, v0sPerColl, mcParticles, vtxPos); } + fjTracks.clear(); // Reject empty events if (fjParticles.size() < 1) @@ -2397,6 +2718,17 @@ struct StrangenessInJetsIons { if (pdgParent == 0) continue; + // --- alternative method to avoid double for loop + // int motherId = GetCommonMotherId(mcParticles, posParticle, negParticle); + // if (motherId < 0) + // continue; // if motherId is -1, it means no common mother was found + // const auto& motherTest = mcParticles.iteratorAt(motherId); + // // const bool isPhysPrimTest = motherTest.isPhysicalPrimary(); + // int pdgParentTest = motherTest.pdgCode(); + // if (pdgParent != pdgParentTest) + // LOG(warning) << "pdgParent != pdgParentTest" << endl; + // --- + // Compute distance from jet and UE axes double deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); double deltaPhiJet = getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); @@ -2408,9 +2740,6 @@ struct StrangenessInJetsIons { double deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Vertex position vector - TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); - // Fill Armenteros-Podolanski TH2 // registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); @@ -2564,6 +2893,294 @@ struct StrangenessInJetsIons { } } PROCESS_SWITCH(StrangenessInJetsIons, processMCreconstructed, "process reconstructed events", false); + + void processMCmodels(soa::Join const& collisions, + aod::McParticles const& mcParticles) + { + // Define per-event particle containers + std::vector fjParticles; + std::vector strHadronMomentum; + std::vector pdg; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over MC collisions + for (const auto& collision : collisions) { + // Clear containers at the start of the event loop + fjParticles.clear(); + strHadronMomentum.clear(); + pdg.clear(); + + // Fill event counter before any selection + registryMC.fill(HIST("number_of_events_mc_gen"), 0.5); + + // Require vertex position within the allowed z range + // if (std::fabs(collision.posZ()) > zVtx) + // continue; + + // Fill event counter after selection on z-vertex + registryMC.fill(HIST("number_of_events_mc_gen"), 1.5); + + // Multiplicity of generated event + float genMultiplicity; + if (centrEstimator == 0) { + genMultiplicity = collision.centFT0C(); + } else { + genMultiplicity = collision.centFT0M(); + } + registryMC.fill(HIST("number_of_events_vsmultiplicity_gen_MB"), genMultiplicity); + + // MC particles per collision + auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); + + // Loop over all MC particles and select physical primaries within acceptance + std::vector> fjParticleObj; + for (const auto& particle : mcParticlesPerColl) { + // Store properties of strange hadrons + int pdgAbs = std::abs(particle.pdgCode()); + if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { // TODO: add protons, kaons, pions + pdg.emplace_back(particle.pdgCode()); + strHadronMomentum.emplace_back(particle.px(), particle.py(), particle.pz()); + } + + double minPtParticle = 0.1f; + if (particle.eta() < configTracks.etaMin || particle.eta() > configTracks.etaMax || particle.pt() < minPtParticle) + continue; + + // false --> do not fill histograms with reco events + FillMBEventHistoMCGEN(particle, genMultiplicity, false); + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + + // Build 4-momentum assuming charged pion mass + static constexpr float kMassPionChargedSquared = o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged; + const double energy = std::sqrt(particle.p() * particle.p() + kMassPionChargedSquared); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fourMomentum.set_user_index(particle.pdgCode()); + fjParticles.emplace_back(fourMomentum); + fjParticleObj.push_back(particle); + } + + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionMCP(fjParticles, fjParticleObj, mcParticlesPerColl, mcParticles); + } + + // Skip events with no particles + if (fjParticles.size() < 1) + continue; + registryMC.fill(HIST("number_of_events_mc_gen"), 2.5); + + // Cluster MC particles into jets using anti-kt algorithm + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + + // Estimate background energy density (rho) in perpendicular cone + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); + + // Loop over clustered jets + int countSelJet = 0; // number of selected jets + for (const auto& jet : jets) { + + // Jet must be fully contained in acceptance + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) + continue; + + // Subtract background energy from jet + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + + // Apply jet pT threshold + if (jetMinusBkg.pt() < minJetPt) + continue; + countSelJet++; + registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); + registryMC.fill(HIST("number_of_events_vsmultiplicity_gen"), genMultiplicity); + + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); + + // Set up two perpendicular cone axes for underlying event estimation + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + double coneRadius = std::sqrt(jet.area() / PI); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); + getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); + if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { + continue; + } + + // Loop over strange hadrons + int index = -1; + for (const auto& hadron : strHadronMomentum) { + // Particle index + index++; + + // Compute distance of particles from jet and UE axes + double deltaEtaJet = hadron.Eta() - jetAxis.Eta(); + double deltaPhiJet = getDeltaPhi(hadron.Phi(), jetAxis.Phi()); + double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + double deltaEtaUe1 = hadron.Eta() - ueAxis1.Eta(); + double deltaPhiUe1 = getDeltaPhi(hadron.Phi(), ueAxis1.Phi()); + double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + double deltaEtaUe2 = hadron.Eta() - ueAxis2.Eta(); + double deltaPhiUe2 = getDeltaPhi(hadron.Phi(), ueAxis2.Phi()); + double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Select particles inside jet + if (deltaRJet < coneRadius) { + switch (pdg[index]) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kXiMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiNeg_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kXiPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiPos_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kOmegaMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaNeg_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kOmegaPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaPos_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_generated_jet"), genMultiplicity, hadron.Pt()); + } + break; + default: + break; + } + } + + // Select particles inside UE cones + if (deltaRUe1 < coneRadius || deltaRUe2 < coneRadius) { + switch (pdg[index]) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kXiMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiNeg_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kXiPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiPos_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kOmegaMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaNeg_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kOmegaPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaPos_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_generated_ue"), genMultiplicity, hadron.Pt()); + } + break; + default: + break; + } + } + } + } + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_mc_gen"), genMultiplicity, countSelJet); + } + } + PROCESS_SWITCH(StrangenessInJetsIons, processMCmodels, "Process MC generated events (with models)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From b40884a5421f5e4f5d6ca200d9d870e70a8e72a0 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Mon, 18 May 2026 14:29:31 +0200 Subject: [PATCH 212/449] [ALICE3] Split otf particle from a3 track utilities (#16288) --- ALICE3/Core/Decayer.h | 1 + ALICE3/Core/OTFParticle.h | 165 +++++++++++++++++++ ALICE3/Core/TrackUtilities.h | 141 +--------------- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 1 + 4 files changed, 169 insertions(+), 139 deletions(-) create mode 100644 ALICE3/Core/OTFParticle.h diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 2280261dd21..7189223573c 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -19,6 +19,7 @@ #ifndef ALICE3_CORE_DECAYER_H_ #define ALICE3_CORE_DECAYER_H_ +#include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" #include diff --git a/ALICE3/Core/OTFParticle.h b/ALICE3/Core/OTFParticle.h new file mode 100644 index 00000000000..b6ca1f246c3 --- /dev/null +++ b/ALICE3/Core/OTFParticle.h @@ -0,0 +1,165 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file OTFParticle.h +/// \brief Basic class to hold information regarding a mc particle to be used in fast simulation +/// \author Jesper Karlsson Gumprecht +/// + +#ifndef ALICE3_CORE_OTFPARTICLE_H_ +#define ALICE3_CORE_OTFPARTICLE_H_ + +#include + +#include +#include +#include +#include + +namespace o2::upgrade +{ + +class OTFParticle +{ + public: + OTFParticle() = default; + + template + explicit OTFParticle(const TParticle& particle) + { + mPdgCode = particle.pdgCode(); + mGlobalIndex = particle.globalIndex(); + mCollisionId = particle.mcCollisionId(); + mPx = particle.px(); + mPy = particle.py(); + mPz = particle.pz(); + mE = particle.e(); + mVx = particle.vx(); + mVy = particle.vy(); + mVz = particle.vz(); + mVt = particle.vt(); + mIsFromMcParticles = true; + if (particle.has_mothers()) { + mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; + } + } + + // Setters + void setIsAlive(const bool isAlive) { mIsAlive = isAlive; } + void setIsPrimary(const bool isPrimary) { mIsPrimary = isPrimary; } + void setCollisionId(const int collisionId) { mCollisionId = collisionId; } + void setPDG(const int pdg) { mPdgCode = pdg; } + void setIndicesMother(const int start, const int stop) { mIndicesMother = {start, stop}; } + void setIndicesDaughter(const int start, const int stop) { mIndicesDaughter = {start, stop}; } + void setProductionTime(const float vt) { mVt = vt; } + void setVxVyVz(const float vx, const float vy, const float vz) + { + mVx = vx; + mVy = vy; + mVz = vz; + } + void setPxPyPzE(const float px, const float py, const float pz, const float e) + { + mPx = px; + mPy = py; + mPz = pz; + mE = e; + } + + // Getters + int pdgCode() const { return mPdgCode; } + int globalIndex() const { return mGlobalIndex; } + int collisionId() const { return mCollisionId; } + bool isAlive() const { return mIsAlive; } + bool isPrimary() const { return mIsPrimary; } + bool isFromMcParticles() const { return mIsFromMcParticles; } + float weight() const + { + static constexpr float Weight = 1.f; + return Weight; + } + uint8_t flags() const + { + static constexpr uint8_t Flags = 1; + return Flags; // todo + } + int statusCode() const + { + static constexpr int StatusCode = 1; + return StatusCode; // todo + } + float vx() const { return mVx; } + float vy() const { return mVy; } + float vz() const { return mVz; } + float vt() const { return mVt; } + float px() const { return mPx; } + float py() const { return mPy; } + float pz() const { return mPz; } + float e() const { return mE; } + float radius() const { return std::hypot(mVx, mVy); } + float r() const { return radius(); } + float pt() const { return std::hypot(mPx, mPy); } + float p() const { return std::hypot(mPx, mPy, mPz); } + float phi() const { return o2::constants::math::PI + std::atan2(-1.0f * py(), -1.0f * px()); } + float eta() const + { + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 + static constexpr float Tolerance = 1e-7f; + if ((p() - mPz) < Tolerance) { + return (mPz < 0.0f) ? -100.0f : 100.0f; + } else { + return 0.5f * std::log((p() + mPz) / (p() - mPz)); + } + } + float y() const + { + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 + static constexpr float Tolerance = 1e-7f; + if ((e() - mPz) < Tolerance) { + return (mPz < 0.0f) ? -100.0f : 100.0f; + } else { + return 0.5f * std::log((mE + mPz) / (mE - mPz)); + } + } + int getMotherIndexStart() const { return mIndicesMother[0]; } + int getMotherIndexStop() const { return mIndicesMother[1]; } + int getDaughterIndexStart() const { return mIndicesDaughter[0]; } + int getDaughterIndexStop() const { return mIndicesDaughter[1]; } + std::array getMothers() const { return mIndicesMother; } + std::array getDaughters() const { return mIndicesDaughter; } + std::span getMotherSpan() const { return hasMothers() ? std::span(mIndicesMother.data(), 2) : std::span(); } + + // Checks + bool hasDaughters() const { return (mIndicesDaughter[0] > 0); } + bool hasMothers() const { return (mIndicesMother[0] > 0); } + bool hasNaN() const + { + return std::isnan(mPx) || std::isnan(mPy) || std::isnan(mPz) || std::isnan(mE) || + std::isnan(mVx) || std::isnan(mVy) || std::isnan(mVz); + } + bool hasIndex() const + { + return (mGlobalIndex != -1); + } + + private: + int mPdgCode{}, mGlobalIndex{-1}; + int mCollisionId{}; + float mVx{}, mVy{}, mVz{}, mVt{}; + float mPx{}, mPy{}, mPz{}, mE{}; + bool mIsAlive{}, mIsFromMcParticles{false}; + bool mIsPrimary{}; + std::array mIndicesMother{-1, -1}, mIndicesDaughter{-1, -1}; +}; + +} // namespace o2::upgrade +#endif // ALICE3_CORE_OTFPARTICLE_H_ diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index 6e4905672bd..d61c72956cb 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -18,6 +18,8 @@ #ifndef ALICE3_CORE_TRACKUTILITIES_H_ #define ALICE3_CORE_TRACKUTILITIES_H_ +#include "ALICE3/Core/OTFParticle.h" + #include #include @@ -30,145 +32,6 @@ namespace o2::upgrade { -class OTFParticle -{ - public: - OTFParticle() = default; - - template - explicit OTFParticle(const TParticle& particle) - { - mPdgCode = particle.pdgCode(); - mGlobalIndex = particle.globalIndex(); - mCollisionId = particle.mcCollisionId(); - mPx = particle.px(); - mPy = particle.py(); - mPz = particle.pz(); - mE = particle.e(); - mVx = particle.vx(); - mVy = particle.vy(); - mVz = particle.vz(); - mIsFromMcParticles = true; - if (particle.has_mothers()) { - mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; - } - } - - // Setters - void setIsAlive(const bool isAlive) { mIsAlive = isAlive; } - void setIsPrimary(const bool isPrimary) { mIsPrimary = isPrimary; } - void setCollisionId(const int collisionId) { mCollisionId = collisionId; } - void setPDG(const int pdg) { mPdgCode = pdg; } - void setIndicesMother(const int start, const int stop) { mIndicesMother = {start, stop}; } - void setIndicesDaughter(const int start, const int stop) { mIndicesDaughter = {start, stop}; } - void setVxVyVz(const float vx, const float vy, const float vz) - { - mVx = vx; - mVy = vy; - mVz = vz; - } - void setPxPyPzE(const float px, const float py, const float pz, const float e) - { - mPx = px; - mPy = py; - mPz = pz; - mE = e; - } - - // Getters - int pdgCode() const { return mPdgCode; } - int globalIndex() const { return mGlobalIndex; } - int collisionId() const { return mCollisionId; } - bool isAlive() const { return mIsAlive; } - bool isPrimary() const { return mIsPrimary; } - bool isFromMcParticles() const { return mIsFromMcParticles; } - float weight() const - { - static constexpr float Weight = 1.f; - return Weight; - } - uint8_t flags() const - { - static constexpr uint8_t Flags = 1; - return Flags; - } - float vt() const - { - static constexpr float Vt = 1.f; - return Vt; - } - int statusCode() const - { - static constexpr int StatusCode = 1; - return StatusCode; - } - float vx() const { return mVx; } - float vy() const { return mVy; } - float vz() const { return mVz; } - float px() const { return mPx; } - float py() const { return mPy; } - float pz() const { return mPz; } - float e() const { return mE; } - float radius() const { return std::hypot(mVx, mVy); } - float r() const { return radius(); } - float pt() const { return std::hypot(mPx, mPy); } - float p() const { return std::hypot(mPx, mPy, mPz); } - float phi() const { return o2::constants::math::PI + std::atan2(-1.0f * py(), -1.0f * px()); } - float eta() const - { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 - static constexpr float Tolerance = 1e-7f; - if ((p() - mPz) < Tolerance) { - return (mPz < 0.0f) ? -100.0f : 100.0f; - } else { - return 0.5f * std::log((p() + mPz) / (p() - mPz)); - } - } - - float y() const - { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 - static constexpr float Tolerance = 1e-7f; - if ((e() - mPz) < Tolerance) { - return (mPz < 0.0f) ? -100.0f : 100.0f; - } else { - return 0.5f * std::log((mE + mPz) / (mE - mPz)); - } - } - - bool hasDaughters() const { return (mIndicesDaughter[0] > 0); } - bool hasMothers() const { return (mIndicesMother[0] > 0); } - int getMotherIndexStart() const { return mIndicesMother[0]; } - int getMotherIndexStop() const { return mIndicesMother[1]; } - int getDaughterIndexStart() const { return mIndicesDaughter[0]; } - int getDaughterIndexStop() const { return mIndicesDaughter[1]; } - std::array getMothers() const { return mIndicesMother; } - std::array getDaughters() const { return mIndicesDaughter; } - std::span getMotherSpan() const { return hasMothers() ? std::span(mIndicesMother.data(), 2) : std::span(); } - - bool hasNaN() const - { - return std::isnan(mPx) || std::isnan(mPy) || std::isnan(mPz) || std::isnan(mE) || - std::isnan(mVx) || std::isnan(mVy) || std::isnan(mVz); - } - - bool hasIndex() const - { - return (mGlobalIndex != -1); - } - - private: - int mPdgCode{}, mGlobalIndex{-1}; - int mCollisionId{}; - float mE{}; - float mVx{}, mVy{}, mVz{}; - float mPx{}, mPy{}, mPz{}; - bool mIsAlive{}, mIsFromMcParticles{false}; - bool mIsPrimary{}; - - std::array mIndicesMother{-1, -1}, mIndicesDaughter{-1, -1}; -}; - /// Function to convert a TLorentzVector into a perfect Track /// \param charge particle charge (integer) /// \param particle the particle to convert (TLorentzVector) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 1d1a301cd3f..38c51110feb 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -16,6 +16,7 @@ /// #include "ALICE3/Core/Decayer.h" +#include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFMCParticle.h" From 634c0737d59a93c5aa3a907d541b90dd3a8384d5 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Mon, 18 May 2026 17:50:09 +0200 Subject: [PATCH 213/449] [PWGLF] Replace cone radius calculation with rJet (#16292) --- PWGLF/Tasks/Strangeness/strangenessInJets.cxx | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index 1be5e3c83d6..245ce30e294 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -1455,7 +1455,7 @@ struct StrangenessInJets { // Set up two perpendicular cone axes for underlying event estimation const TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - const double coneRadius = std::sqrt(jet.area() / PI); + const double coneRadius = rJet; TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -1664,7 +1664,8 @@ struct StrangenessInJets { if (!motherPos.isPhysicalPrimary()) continue; - if (std::abs(motherPos.eta()) > 0.8) + const double maxPseudorap = 0.8; + if (std::abs(motherPos.eta()) > maxPseudorap) continue; // K0s @@ -1744,8 +1745,8 @@ struct StrangenessInJets { if (!mcParticle.isPhysicalPrimary()) { continue; } - - if (std::abs(mcParticle.eta()) > 0.8) { + const double maxPseudorap = 0.8; + if (std::abs(mcParticle.eta()) > maxPseudorap) { continue; } @@ -1786,9 +1787,10 @@ struct StrangenessInJets { } } - for (auto& particle : mcParticlesPerColl) { + const double maxPseudorap = 0.8; + for (auto const& particle : mcParticlesPerColl) { - if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= 0.8) { + if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= maxPseudorap) { switch (particle.pdgCode()) { case kK0Short: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { @@ -1889,8 +1891,8 @@ struct StrangenessInJets { continue; if (!motherPos.isPhysicalPrimary()) continue; - - if (std::abs(motherPos.eta()) > 0.8) + double maxPseudorap = 0.8; + if (std::abs(motherPos.eta()) > maxPseudorap) continue; // K0s @@ -1908,9 +1910,9 @@ struct StrangenessInJets { } } - for (auto& particle : mcParticlesPerColl) { - - if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= 0.8) { + for (auto const& particle : mcParticlesPerColl) { + double maxPseudorap = 0.8; + if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= maxPseudorap) { switch (particle.pdgCode()) { case kK0Short: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { @@ -1936,7 +1938,7 @@ struct StrangenessInJets { // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { - for (auto& particle : mcParticlesPerColl) { + for (auto const& particle : mcParticlesPerColl) { const ParticlePositionWithRespectToJet positionMC{particle.px(), particle.py(), particle.pz(), selectedJet[i], ue1[i], ue2[i]}; From e9533e8c2c14710d2eeb2b347a9358b36304a85a Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Mon, 18 May 2026 18:14:04 +0200 Subject: [PATCH 214/449] [PWGLF] Omegahm: data for deco (#16278) --- PWGLF/DataModel/LFNonPromptCascadeTables.h | 4 +- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 316 +++++++++++++------ 2 files changed, 218 insertions(+), 102 deletions(-) diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index d9d2c30ac97..0ea616d8853 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -121,6 +121,7 @@ DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); +DECLARE_SOA_COLUMN(MultNTracksNP, multNTracksNP, int); DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(NoSameBunchPileup, noSameBunchPileup, bool); @@ -454,13 +455,14 @@ DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", DECLARE_SOA_TABLE(NPMCChargedTable, "AOD", "NPMCChargedTABLE", NPCascadeTable::PtGen, NPCascadeTable::PtRec, - NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::MultNTracksNP, NPCascadeTable::MultGen); DECLARE_SOA_TABLE(NPCollisionTable, "AOD", "NPCollisionTABLE", NPCascadeTable::RunNumber, NPCascadeTable::GlobalBC, aod::collision::NumContrib, NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::MultNTracksNP, NPCascadeTable::CentFT0M, NPCascadeTable::MultFT0M); DECLARE_SOA_INDEX_COLUMN_FULL(NPCollision, npCollision, int32_t, NPCollisionTable, ""); diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 79c74df4307..cf85c93cc17 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -203,6 +203,7 @@ struct NonPromptCascadeTask { using CollisionCandidatesRun3MC = soa::Join; using TracksWithLabel = soa::Join; using TracksWithSel = soa::Join; + using TracksWithLabelSel = soa::Join; Preslice perCollision = aod::track::collisionId; Preslice perCollisionMC = aod::track::collisionId; @@ -818,185 +819,294 @@ struct NonPromptCascadeTask { // tracks: Join // mcCollisions: aod::McCollisions // mcParticles : aod::McParticles - void processdNdetaMC(CollisionCandidatesRun3MC const& colls, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles, - TracksWithLabel const& tracks) + TracksWithLabelSel const& tracks) { - //------------------------------------------------------------ - // Downscaling output table by BC as there is no pileup in MC - //------------------------------------------------------------ - int ds = 1; - //------------------------------------------------------------- - // MC mult for all MC coll - //-------------------------------------------------------------- - std::vector mcMult(mcCollisions.size(), 0); - for (auto const& mcp : mcParticles) { - int mcid = mcp.mcCollisionId(); - if (mcid < 0 || static_cast(mcid) >= mcMult.size()) - continue; + // ------------------------------------------------------------ + // Helper: accepted generated charged primary + // ------------------------------------------------------------ + auto isAcceptedMCParticle = [&](auto const& mcp) { + if (!mcp.isPhysicalPrimary()) { + return false; + } + if (std::abs(mcp.eta()) > cfgEtaCutdNdeta) { + return false; + } - // apply your primary/eta/charge definition here - if (!mcp.isPhysicalPrimary()) - continue; - if (std::abs(mcp.eta()) > cfgEtaCutdNdeta) - continue; int q = 0; if (auto pdg = pdgDB->GetParticle(mcp.pdgCode())) { q = static_cast(std::round(pdg->Charge() / 3.0)); } - if (q == 0) - continue; + return q != 0; + }; + // ------------------------------------------------------------ + // Helper: accepted reconstructed track + // Use same cuts as data. + // ------------------------------------------------------------ + auto isAcceptedRecoTrack = [&](auto const& trk) { + if (std::fabs(trk.eta()) >= cfgEtaCutdNdeta) { + return false; + } + if (trk.tpcNClsFound() < 80) { + return false; + } + if (trk.tpcNClsCrossedRows() < 100) { + return false; + } + if (!trk.isGlobalTrack()) { + return false; + } + return true; + }; + + // ------------------------------------------------------------ + // 1) MC charged multiplicity per MC collision + // mcid: mc collision row of mc particle + // ------------------------------------------------------------ + std::vector mcMult(mcCollisions.size(), 0); + // std::cout << "mcCollisions size:" << mcCollisions.size() << std::endl; + for (auto const& mcp : mcParticles) { + const int mcid = mcp.mcCollisionId(); + // std::cout << "mcid:" << mcid << std::endl; + if (mcid < 0 || static_cast(mcid) >= mcMult.size()) { + LOG(info) << "0 This should never happen ?"; + continue; + } + if (!isAcceptedMCParticle(mcp)) { + continue; + } ++mcMult[mcid]; } // ------------------------------------------------------------ - // Build mapping: (aod::Collisions row id used by tracks.collisionId()) - // -> dense index in 'colls' (0..colls.size()-1) - // We assume col.globalIndex() refers to the original aod::Collisions row. + // 2) Map aod::Collisions row id -> dense index in 'colls' // ------------------------------------------------------------ int maxCollRowId = -1; for (auto const& trk : tracks) { maxCollRowId = std::max(maxCollRowId, static_cast(trk.collisionId())); } + std::vector collRowIdToDense(maxCollRowId + 1, -1); - int dense = 0; + int denseIdx = 0; for (auto const& col : colls) { - const int collRowId = col.globalIndex(); // row id in aod::Collisions - if (collRowId >= 0 && static_cast(collRowId) < collRowIdToDense.size()) { - collRowIdToDense[collRowId] = dense; + const int collRowId = col.globalIndex(); + + if (collRowId >= 0 && collRowId <= maxCollRowId) { + collRowIdToDense[collRowId] = denseIdx; + } else { + LOG(info) << "1 This should never happen ?"; } - ++dense; + ++denseIdx; } // ------------------------------------------------------------ - // Reco multiplicity per *dense collision index in colls* + // 3) Reco multiplicity per reconstructed collision // ------------------------------------------------------------ std::vector recoMultDense(colls.size(), 0); + for (auto const& trk : tracks) { - if (std::abs(trk.eta()) > cfgEtaCutdNdeta) { + if (!isAcceptedRecoTrack(trk)) { continue; } + const int collRowId = trk.collisionId(); - if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { + // std::cout << collRowId << std::endl; + if (collRowId < 0 || collRowId > maxCollRowId) { + // std::cout << "2 This should never happen ?" << std::endl; continue; } const int dIdx = collRowIdToDense[collRowId]; - if (dIdx >= 0) { - ++recoMultDense[dIdx]; + if (dIdx < 0) { + // Tracks has collId which is not in the list created above + LOG(info) << "3 This should never happen ?"; + continue; } + ++recoMultDense[dIdx]; } // ------------------------------------------------------------ - // MC bookkeeping: index by ROW INDEX (0..size-1), not globalIndex() + // 4) Bookkeeping // ------------------------------------------------------------ std::vector isReco(mcParticles.size(), 0); - std::vector isRecoMult(mcParticles.size(), 0.f); - std::vector mcReconstructed(mcCollisions.size(), 0); - // Optional cache of MC multiplicity per MC collision - std::vector mcMultCache(mcCollisions.size(), -1.f); + // MC collision has a reconstructed collision in 'colls'. + // This must be independent of reco-track cuts. + std::vector mcCollisionHasRecoCollision(mcCollisions.size(), 0); + + for (auto const& col : colls) { + const int mcid = col.mcCollisionId(); + if (mcid >= 0 && static_cast(mcid) < mcCollisionHasRecoCollision.size()) { + mcCollisionHasRecoCollision[mcid] = 1; + } else { + LOG(info) << "4 This should never happen ?"; + } + } + + // Downscale output table per MC collision + std::vector writeMcCollision(mcCollisions.size(), 0); + int ds = 1; + for (auto const& mcColl : mcCollisions) { + const int mcid = mcColl.globalIndex(); + if (mcid < 0 || static_cast(mcid) >= writeMcCollision.size()) { + LOG(info) << "5 This should never happen ?"; + continue; + } + if ((ds % cfgDownscaleMB) == 0) { + writeMcCollision[mcid] = 1; + } + ++ds; + } + + std::vector writeRecoCollision(colls.size(), 0); + for (int iColl = 0; iColl < static_cast(colls.size()); ++iColl) { + if (((iColl + 1) % cfgDownscaleMB) == 0) { + writeRecoCollision[iColl] = 1; + } + } // ------------------------------------------------------------ - // Single pass over tracks: fill RM for tracks whose collision is in colls + // 5) Matched reconstructed tracks // ------------------------------------------------------------ for (auto const& trk : tracks) { - // Accept reco track - if (std::abs(trk.eta()) > cfgEtaCutdNdeta) { + if (!isAcceptedRecoTrack(trk)) { continue; } - // Map track's collision row id -> dense colls index const int collRowId = trk.collisionId(); - if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { + if (collRowId < 0 || collRowId > maxCollRowId) { continue; } + const int dIdx = collRowIdToDense[collRowId]; if (dIdx < 0) { - continue; // this track's collision is not in our 'colls' view + continue; } - // Get the collision row (dense index in colls view) auto col = colls.rawIteratorAt(dIdx); - // MC collision id (row index in aod::McCollisions) const int mcCollId = col.mcCollisionId(); + const float multReco = recoMultDense[dIdx]; + const float ptReco = trk.pt(); + if (mcCollId < 0 || static_cast(mcCollId) >= mcCollisions.size()) { + if (writeRecoCollision[dIdx]) { + // Fake: accepted reco track whose reconstructed collision has no valid MC collision label. + NPMCNTable(-1.f, ptReco, multReco, -1.f); + } continue; } - mcReconstructed[mcCollId] = 1; - // MC particle id (row index in aod::McParticles) const int mcPid = trk.mcParticleId(); if (mcPid < 0 || static_cast(mcPid) >= mcParticles.size()) { + if (writeMcCollision[mcCollId]) { + // Fake: accepted reco track with invalid or missing MC particle label. + NPMCNTable(-2.f, ptReco, multReco, -2.f); + } continue; } - // MC multiplicity for that MC collision (cache) - float mult = mcMultCache[mcCollId]; - if (mult < 0.f) { - std::vector tmp; - mult = mcMult[mcCollId]; - mcMultCache[mcCollId] = mult; - } - auto mcPar = mcParticles.rawIteratorAt(mcPid); - // Apply the same acceptance as in MC multiplicity definition - if (!mcPar.isPhysicalPrimary()) { - continue; - } - if (std::abs(mcPar.eta()) > cfgEtaCutdNdeta) { + const int mcParCollId = mcPar.mcCollisionId(); + if (mcParCollId != mcCollId) { + if (writeMcCollision[mcCollId]) { + // Fake: reco collision and particle label point to different MC collisions. + NPMCNTable(-3.f, ptReco, multReco, -3.f); + } continue; } - int q = 0; - if (auto pdgEntry = pdgDB->GetParticle(mcPar.pdgCode())) { - q = static_cast(std::round(pdgEntry->Charge() / 3.0)); - } - if (q == 0) { + if (!isAcceptedMCParticle(mcPar)) { + if (writeMcCollision[mcCollId]) { + // Feed-in: accepted reco track matched to truth outside fiducial phase space. + NPMCNTable(-4.f, ptReco, multReco, -4.f); + } continue; } - // Mark reconstructed MC particle (now that it truly passed & matched) isReco[mcPid] = 1; - isRecoMult[mcPid] = mult; - const float multReco = col.multNTracksGlobal(); // or recoMultDense[dIdx] - const float ptReco = trk.pt(); + const float multMC = mcMult[mcCollId]; const float ptMC = mcPar.pt(); - mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRM"), mult, multReco, ptMC, ptReco); - if (ds % cfgDownscaleMB == 0) { - NPMCNTable(ptMC, ptReco, mult, multReco); + mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRM"), + multMC, + multReco, + ptMC, + ptReco); + + if (writeMcCollision[mcCollId]) { + // Matched: accepted truth particle reconstructed inside the fiducial reco phase space. + NPMCNTable(ptMC, ptReco, multReco, multMC); } - ds++; } // ------------------------------------------------------------ - // MC particles with no reco track (iterate by row index) + // 6) MC particles with no accepted reco track, + // but from MC collisions that have a reconstructed collision // ------------------------------------------------------------ for (int pid = 0; pid < static_cast(mcParticles.size()); ++pid) { - if (!isReco[pid]) { - auto mcp = mcParticles.rawIteratorAt(pid); - mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoTrk"), isRecoMult[pid], mcp.pt()); - NPMCNTable(mcp.pt(), -1, isRecoMult[pid], -1); + if (isReco[pid]) { + continue; + } + + auto mcp = mcParticles.rawIteratorAt(pid); + + if (!isAcceptedMCParticle(mcp)) { + continue; + } + + const int mcid = mcp.mcCollisionId(); + if (mcid < 0 || static_cast(mcid) >= mcMult.size()) { + continue; + } + + if (!mcCollisionHasRecoCollision[mcid]) { + continue; + } + + const float multMC = mcMult[mcid]; + + mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoTrk"), + multMC, + mcp.pt()); + + if (writeMcCollision[mcid]) { + // Missed track: accepted truth particle in a reconstructed MC collision, but no accepted reco track. + NPMCNTable(mcp.pt(), -1.f, -1.f, multMC); } } // ------------------------------------------------------------ - // Unreconstructed MC collisions (iterate by row index) + // 7) MC particles from MC collisions with no reconstructed collision // ------------------------------------------------------------ for (int mcid = 0; mcid < static_cast(mcCollisions.size()); ++mcid) { - if (!mcReconstructed[mcid]) { - std::vector mcptvec; - const int mult = mcMult[mcid]; - for (auto const& pt : mcptvec) { - mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoCol"), mult, pt); - NPMCNTable(pt, -2, mult, -2); + if (mcCollisionHasRecoCollision[mcid]) { + continue; + } + + const float multMC = mcMult[mcid]; + + for (auto const& mcp : mcParticles) { + if (mcp.mcCollisionId() != mcid) { + continue; + } + + if (!isAcceptedMCParticle(mcp)) { + continue; + } + + mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoCol"), + multMC, + mcp.pt()); + + if (writeMcCollision[mcid]) { + // Missed collision: accepted truth particle from an MC collision with no reconstructed collision. + NPMCNTable(mcp.pt(), -2.f, -2.f, multMC); } } } @@ -1022,6 +1132,20 @@ struct NonPromptCascadeTask { } ds++; } + auto tracksThisColl = tracks.sliceBy(perCollisionSel, coll.globalIndex()); + int multreco = 0; + std::vector recoPts; + // std::cout << "tracks:" << tracksThisColl.size() << std::endl; + for (auto const& track : tracksThisColl) { + // std::cout << track.pt() << " tracks " << track.isGlobalTrack() << std::endl; + if (std::fabs(track.eta()) < cfgEtaCutdNdeta && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { + if (track.isGlobalTrack()) { + multreco++; + recoPts.push_back(track.pt()); + } + } + } + mRegistrydNdeta.fill(HIST("hdNdetaData"), multreco); if (writeFlag) { if (mRunNumber != bc.runNumber()) { mRunNumber = bc.runNumber(); @@ -1030,23 +1154,13 @@ struct NonPromptCascadeTask { globalBC, coll.numContrib(), coll.multNTracksGlobal(), + multreco, coll.centFT0M(), coll.multFT0M()); - auto collIdx = NPCollsTable.lastIndex(); - auto tracksThisColl = tracks.sliceBy(perCollisionSel, coll.globalIndex()); - float multreco = 0.; - // std::cout << "tracks:" << tracksThisColl.size() << std::endl; - for (auto const& track : tracksThisColl) { - // std::cout << track.pt() << " tracks " << track.isGlobalTrack() << std::endl; - if (std::fabs(track.eta()) < cfgEtaCutdNdeta && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { - if (track.isGlobalTrack()) { - multreco++; - NPRecoCandTable(collIdx, track.pt()); - } - } + for (auto const& pt : recoPts) { + NPRecoCandTable(collIdx, pt); } - mRegistrydNdeta.fill(HIST("hdNdetaData"), multreco); } } } @@ -1077,7 +1191,7 @@ struct NonPromptCascadeTask { } float centFT0M = coll.centFT0M(); float multFT0M = coll.multFT0M(); - NPCollsTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); + NPCollsTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), 0, centFT0M, multFT0M); } } }; From 8c9ff56b2f619d763421eb317c300545eb28839c Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Mon, 18 May 2026 18:48:28 +0200 Subject: [PATCH 215/449] [ALICE3] Add particle production time to otf decayer (#16290) --- ALICE3/Core/Decayer.h | 30 ++++--- ALICE3/Core/TrackUtilities.cxx | 68 +++++++++++++++ ALICE3/Core/TrackUtilities.h | 11 +++ ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 24 +++++- ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx | 87 ++------------------ 5 files changed, 124 insertions(+), 96 deletions(-) diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 7189223573c..51296ffe67d 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -61,13 +61,12 @@ class Decayer const double ctau = o2::constants::physics::LightSpeedCm2S * particleInfo->Lifetime(); // cm const double betaGamma = particle.p() / mass; const double rxyz = -betaGamma * ctau * std::log(1 - u); - double vx, vy, vz; double px, py, e; if (!charge) { - vx = particle.vx() + rxyz * (particle.px() / particle.p()); - vy = particle.vy() + rxyz * (particle.py() / particle.p()); - vz = particle.vz() + rxyz * (particle.pz() / particle.p()); + mVx = particle.vx() + rxyz * (particle.px() / particle.p()); + mVy = particle.vy() + rxyz * (particle.py() / particle.p()); + mVz = particle.vz() + rxyz * (particle.pz() / particle.p()); px = particle.px(); py = particle.py(); } else { @@ -75,14 +74,14 @@ class Decayer o2::math_utils::CircleXYf_t circle; o2::upgrade::convertOTFParticleToO2Track(particle, track, pdgDB); - float sna, csa; + float sna{}, csa{}; track.getCircleParams(mBz, circle, sna, csa); const double rxy = rxyz / std::sqrt(1. + track.getTgl() * track.getTgl()); const double theta = rxy / circle.rC; - vx = ((particle.vx() - circle.xC) * std::cos(theta) - (particle.vy() - circle.yC) * std::sin(theta)) + circle.xC; - vy = ((particle.vy() - circle.yC) * std::cos(theta) + (particle.vx() - circle.xC) * std::sin(theta)) + circle.yC; - vz = particle.vz() + rxyz * (particle.pz() / track.getP()); + mVx = ((particle.vx() - circle.xC) * std::cos(theta) - (particle.vy() - circle.yC) * std::sin(theta)) + circle.xC; + mVy = ((particle.vy() - circle.yC) * std::cos(theta) + (particle.vx() - circle.xC) * std::sin(theta)) + circle.yC; + mVz = particle.vz() + rxyz * (particle.pz() / track.getP()); px = particle.px() * std::cos(theta) - particle.py() * std::sin(theta); py = particle.py() * std::cos(theta) + particle.px() * std::sin(theta); @@ -125,7 +124,7 @@ class Decayer o2::upgrade::OTFParticle particle; TLorentzVector dau = *decay.GetDecay(i); particle.setPDG(pdgCodesDaughters[i]); - particle.setVxVyVz(vx, vy, vz); + particle.setVxVyVz(mVx, mVy, mVz); particle.setPxPyPzE(dau.Px(), dau.Py(), dau.Pz(), dau.E()); decayProducts.push_back(particle); } @@ -133,17 +132,24 @@ class Decayer return decayProducts; } + // Setters + void setBField(const double b) { mBz = b; } void setSeed(const int seed) { mRand3.SetSeed(seed); // For decay length sampling gRandom->SetSeed(seed); // For TGenPhaseSpace } - void setBField(const double b) { mBz = b; } + // Getters + float getSecondaryVertexX() const { return static_cast(mVx); } + float getSecondaryVertexY() const { return static_cast(mVy); } + float getSecondaryVertexZ() const { return static_cast(mVz); } + float getDecayRadius() const { return static_cast(std::hypot(mVx, mVy)); } private: - TRandom3 mRand3; - double mBz; + double mBz{20.}; // kG + double mVx{-1.}, mVy{-1.}, mVz{-1.}; + TRandom3 mRand3{}; }; } // namespace upgrade diff --git a/ALICE3/Core/TrackUtilities.cxx b/ALICE3/Core/TrackUtilities.cxx index 739e1df28ae..4239864e933 100644 --- a/ALICE3/Core/TrackUtilities.cxx +++ b/ALICE3/Core/TrackUtilities.cxx @@ -45,3 +45,71 @@ void o2::upgrade::convertTLorentzVectorToO2Track(const int charge, // Initialize TrackParCov in-place new (&o2track)(o2::track::TrackParCov)(x, particle.Phi(), params, covm); } + +float o2::upgrade::computeParticleVelocity(float momentum, float mass) +{ + const float a = momentum / mass; + // uses light speed in cm/ps so output is in those units + return o2::constants::physics::LightSpeedCm2PS * a / std::sqrt((1.f + a * a)); +} + +float o2::upgrade::computeTrackLength(o2::track::TrackParCov track, float radius, float magneticField) +{ + // don't make use of the track parametrization + float length = -100; + + o2::math_utils::CircleXYf_t trcCircle; + float sna, csa; + track.getCircleParams(magneticField, trcCircle, sna, csa); + + // distance between circle centers (one circle is at origin -> easy) + const float centerDistance = std::hypot(trcCircle.xC, trcCircle.yC); + + // condition of circles touching - if not satisfied returned length will be -100 + if (centerDistance < trcCircle.rC + radius && centerDistance > std::fabs(trcCircle.rC - radius)) { + length = 0.0f; + + // base radical direction + const float ux = trcCircle.xC / centerDistance; + const float uy = trcCircle.yC / centerDistance; + // calculate perpendicular vector (normalized) for +/- displacement + const float vx = -uy; + const float vy = +ux; + // calculate coordinate for radical line + const float radical = (centerDistance * centerDistance - trcCircle.rC * trcCircle.rC + radius * radius) / (2.0f * centerDistance); + // calculate absolute displacement from center-to-center axis + const float displace = (0.5f / centerDistance) * std::sqrt( + (-centerDistance + trcCircle.rC - radius) * + (-centerDistance - trcCircle.rC + radius) * + (-centerDistance + trcCircle.rC + radius) * + (centerDistance + trcCircle.rC + radius)); + + // possible intercept points of track and TOF layer in 2D plane + const float point1[2] = {radical * ux + displace * vx, radical * uy + displace * vy}; + const float point2[2] = {radical * ux - displace * vx, radical * uy - displace * vy}; + + // decide on correct intercept point + std::array mom; + track.getPxPyPzGlo(mom); + const float scalarProduct1 = point1[0] * mom[0] + point1[1] * mom[1]; + const float scalarProduct2 = point2[0] * mom[0] + point2[1] * mom[1]; + + // get start point + std::array startPoint; + track.getXYZGlo(startPoint); + + float cosAngle = -1000, modulus = -1000; + + if (scalarProduct1 > scalarProduct2) { + modulus = std::hypot(point1[0] - trcCircle.xC, point1[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); + cosAngle = (point1[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point1[1] - trcCircle.yC) * (startPoint[1] - trcCircle.yC); + } else { + modulus = std::hypot(point2[0] - trcCircle.xC, point2[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); + cosAngle = (point2[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point2[1] - trcCircle.yC) * (startPoint[1] - trcCircle.yC); + } + cosAngle /= modulus; + length = trcCircle.rC * std::acos(cosAngle); + length *= std::sqrt(1.0f + track.getTgl() * track.getTgl()); + } + return length; +} diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index d61c72956cb..b80ea1b2341 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -104,6 +104,17 @@ o2::track::TrackParCov convertMCParticleToO2Track(McParticleType& particle, return o2track; } +/// returns velocity in centimeters per picoseconds +/// \param momentum the momentum of the track +/// \param mass the mass of the particle +float computeParticleVelocity(float momentum, float mass); + +/// function to calculate track length of this track up to a certain radius +/// \param track the input track (TrackParCov) +/// \param radius the radius of the layer you're calculating the length to +/// \param magneticField the magnetic field to use when propagating +float computeTrackLength(o2::track::TrackParCov track, float radius, float magneticField); + } // namespace o2::upgrade #endif // ALICE3_CORE_TRACKUTILITIES_H_ diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 38c51110feb..4bf984db338 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -77,6 +77,7 @@ struct OnTheFlyDecayer { o2::upgrade::Decayer decayer; Service pdgDB; std::map> mDecayDaughters; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable seed{"seed", 0, "Set seed for particle decayer"}; Configurable magneticField{"magneticField", 20., "Magnetic field (kG)"}; @@ -84,9 +85,9 @@ struct OnTheFlyDecayer { {DefaultParameters[0], NumDecays, NumParameters, ParticleNames, ParameterNames}, "Enable option for particle to be decayed: 0 - no, 1 - yes"}; - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - + static constexpr float PicoToNano = 1.e-3f; int mCollisionId{-1}; + std::vector mEnabledDecays; void init(o2::framework::InitContext&) { @@ -133,12 +134,29 @@ struct OnTheFlyDecayer { particle.setIsAlive(false); std::vector decayStack = decayer.decayParticle(pdgDB, particle); + const float decayRadius = decayer.getDecayRadius(); + const float trackVelocity = o2::upgrade::computeParticleVelocity(particle.p(), pdgDB->GetParticle(particle.pdgCode())->Mass()); + const int charge = pdgDB->GetParticle(particle.pdgCode())->Charge() / 3; + float trackLength{-1.f}; + if (!charge) { + const float dx = particle.vx() - decayer.getSecondaryVertexX(); + const float dy = particle.vy() - decayer.getSecondaryVertexY(); + const float dz = particle.vz() - decayer.getSecondaryVertexZ(); + trackLength = std::hypot(dx, dy, dz); + } else { + o2::track::TrackParCov o2track; + o2::upgrade::convertOTFParticleToO2Track(particle, o2track, pdgDB); + trackLength = o2::upgrade::computeTrackLength(o2track, decayRadius, magneticField); + } + + const float trackTimeNS = trackLength / trackVelocity * PicoToNano; particle.setIndicesDaughter(allParticles.size(), allParticles.size() + (decayStack.size() - 1)); for (o2::upgrade::OTFParticle daughter : decayStack) { daughter.setIndicesMother(i, i); daughter.setCollisionId(mCollisionId); daughter.setIsAlive(true); daughter.setIsPrimary(false); + daughter.setProductionTime(trackTimeNS); allParticles.push_back(daughter); ndau++; } @@ -175,7 +193,7 @@ struct OnTheFlyDecayer { histos.fill(HIST("hNaNBookkeeping"), 0); } - // todo: status codes and vt + // todo: status codes tableMcParticlesWithDau(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index 4617ca73657..99d9de97f22 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -448,81 +448,6 @@ struct OnTheFlyTofPid { return outerTOFLayer.isTrackInActiveArea(track); } - /// function to calculate track length of this track up to a certain radius - /// \param track the input track - /// \param radius the radius of the layer you're calculating the length to - /// \param magneticField the magnetic field to use when propagating - static float computeTrackLength(o2::track::TrackParCov track, float radius, float magneticField) - { - // don't make use of the track parametrization - float length = -100; - - o2::math_utils::CircleXYf_t trcCircle; - float sna, csa; - track.getCircleParams(magneticField, trcCircle, sna, csa); - - // distance between circle centers (one circle is at origin -> easy) - const float centerDistance = std::hypot(trcCircle.xC, trcCircle.yC); - - // condition of circles touching - if not satisfied returned length will be -100 - if (centerDistance < trcCircle.rC + radius && centerDistance > std::fabs(trcCircle.rC - radius)) { - length = 0.0f; - - // base radical direction - const float ux = trcCircle.xC / centerDistance; - const float uy = trcCircle.yC / centerDistance; - // calculate perpendicular vector (normalized) for +/- displacement - const float vx = -uy; - const float vy = +ux; - // calculate coordinate for radical line - const float radical = (centerDistance * centerDistance - trcCircle.rC * trcCircle.rC + radius * radius) / (2.0f * centerDistance); - // calculate absolute displacement from center-to-center axis - const float displace = (0.5f / centerDistance) * std::sqrt( - (-centerDistance + trcCircle.rC - radius) * - (-centerDistance - trcCircle.rC + radius) * - (-centerDistance + trcCircle.rC + radius) * - (centerDistance + trcCircle.rC + radius)); - - // possible intercept points of track and TOF layer in 2D plane - const float point1[2] = {radical * ux + displace * vx, radical * uy + displace * vy}; - const float point2[2] = {radical * ux - displace * vx, radical * uy - displace * vy}; - - // decide on correct intercept point - std::array mom; - track.getPxPyPzGlo(mom); - const float scalarProduct1 = point1[0] * mom[0] + point1[1] * mom[1]; - const float scalarProduct2 = point2[0] * mom[0] + point2[1] * mom[1]; - - // get start point - std::array startPoint; - track.getXYZGlo(startPoint); - - float cosAngle = -1000, modulus = -1000; - - if (scalarProduct1 > scalarProduct2) { - modulus = std::hypot(point1[0] - trcCircle.xC, point1[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); - cosAngle = (point1[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point1[1] - trcCircle.yC) * (startPoint[1] - trcCircle.yC); - } else { - modulus = std::hypot(point2[0] - trcCircle.xC, point2[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); - cosAngle = (point2[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point2[1] - trcCircle.yC) * (startPoint[1] - trcCircle.yC); - } - cosAngle /= modulus; - length = trcCircle.rC * std::acos(cosAngle); - length *= std::sqrt(1.0f + track.getTgl() * track.getTgl()); - } - return length; - } - - /// returns velocity in centimeters per picoseconds - /// \param momentum the momentum of the tarck - /// \param mass the mass of the particle - float computeParticleVelocity(float momentum, float mass) - { - const float a = momentum / mass; - // uses light speed in cm/ps so output is in those units - return o2::constants::physics::LightSpeedCm2PS * a / std::sqrt((1.f + a * a)); - } - struct TracksWithTime { TracksWithTime(int pdgCode, std::pair innerTOFTime, @@ -696,8 +621,8 @@ struct OnTheFlyTofPid { } float trackLengthInnerTOF = -1, trackLengthOuterTOF = -1; if (xPv > kTrkXThreshold) { - trackLengthInnerTOF = computeTrackLength(o2track, simConfig.innerTOFRadius, mMagneticField); - trackLengthOuterTOF = computeTrackLength(o2track, simConfig.outerTOFRadius, mMagneticField); + trackLengthInnerTOF = o2::upgrade::computeTrackLength(o2track, simConfig.innerTOFRadius, mMagneticField); + trackLengthOuterTOF = o2::upgrade::computeTrackLength(o2track, simConfig.outerTOFRadius, mMagneticField); } // Check if the track hit a sensitive area of the TOF @@ -730,7 +655,7 @@ struct OnTheFlyTofPid { upgradeTofMC(-999.f, -999.f, -999.f, -999.f); continue; } - const float v = computeParticleVelocity(o2track.getP(), pdgInfo->Mass()); + const float v = o2::upgrade::computeParticleVelocity(o2track.getP(), pdgInfo->Mass()); const float expectedTimeInnerTOF = trackLengthInnerTOF > 0 ? trackLengthInnerTOF / v + eventCollisionTimePS : -999.f; // arrival time to the Inner TOF in ps const float expectedTimeOuterTOF = trackLengthOuterTOF > 0 ? trackLengthOuterTOF / v + eventCollisionTimePS : -999.f; // arrival time to the Outer TOF in ps upgradeTofMC(expectedTimeInnerTOF, trackLengthInnerTOF, expectedTimeOuterTOF, trackLengthOuterTOF); @@ -748,8 +673,8 @@ struct OnTheFlyTofPid { xPv = recoTrack.getX(); } if (xPv > kTrkXThreshold) { - trackLengthRecoInnerTOF = computeTrackLength(recoTrack, simConfig.innerTOFRadius, mMagneticField); - trackLengthRecoOuterTOF = computeTrackLength(recoTrack, simConfig.outerTOFRadius, mMagneticField); + trackLengthRecoInnerTOF = o2::upgrade::computeTrackLength(recoTrack, simConfig.innerTOFRadius, mMagneticField); + trackLengthRecoOuterTOF = o2::upgrade::computeTrackLength(recoTrack, simConfig.outerTOFRadius, mMagneticField); } // cache the track info needed for the event time calculation @@ -870,7 +795,7 @@ struct OnTheFlyTofPid { nSigmaOuterTOF[ii] = -100; momentumHypotheses[ii] = rigidity * kParticleCharges[ii]; // Total momentum for this hypothesis - const float v = computeParticleVelocity(momentumHypotheses[ii], kParticleMasses[ii]); + const float v = o2::upgrade::computeParticleVelocity(momentumHypotheses[ii], kParticleMasses[ii]); expectedTimeInnerTOF[ii] = trackLengthInnerTOF / v; expectedTimeOuterTOF[ii] = trackLengthOuterTOF / v; From 9cf192190baeb0602ff8f9ceb1ee7e8825f7a064 Mon Sep 17 00:00:00 2001 From: Katarzyna <116073883+kgwizdzi@users.noreply.github.com> Date: Mon, 18 May 2026 19:17:30 +0200 Subject: [PATCH 216/449] [PWGCF] FU: efficiency and D0 tasks update (#16293) --- .../Tasks/femtoUniverseEfficiencyBase.cxx | 26 +++++++++-------- .../Tasks/femtoUniversePairTaskTrackD0.cxx | 28 +++++++++++++++---- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx index 3506ce3f5c4..2c0148bcfa7 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx @@ -660,6 +660,13 @@ struct FemtoUniverseEfficiencyBase { } registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 4); + // TOF Matching efficiency + if (part.mLambda() == 1) { + registryTOFMatch.fill(HIST("part1/hTofMatchPtAfterPID"), part.pt()); + } else { + registryTOFMatch.fill(HIST("part1/hTpcPt"), part.pt()); + } + // Get the coresponding MC particle const auto mcParticle = part.fdMCParticle(); @@ -696,12 +703,6 @@ struct FemtoUniverseEfficiencyBase { registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part1/hRecoPt"), part.pt()); registryMCOrigin.fill(HIST("part1/hTruthPt"), mcParticle.pt()); - // TOF Matching efficiency - if (part.mLambda() == 1) { - registryTOFMatch.fill(HIST("part1/hTofMatchPtAfterPID"), part.pt()); - } else { - registryTOFMatch.fill(HIST("part1/hTpcPt"), part.pt()); - } } if (!confIsSame) { @@ -738,6 +739,13 @@ struct FemtoUniverseEfficiencyBase { } registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 4); + // TOF Matching efficiency + if (part.mLambda() == 1) { + registryTOFMatch.fill(HIST("part2/hTofMatchPtAfterPID"), part.pt()); + } else { + registryTOFMatch.fill(HIST("part2/hTpcPt"), part.pt()); + } + // Get the coresponding MC particle const auto mcParticle = part.fdMCParticle(); @@ -774,12 +782,6 @@ struct FemtoUniverseEfficiencyBase { registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part2/hRecoPt"), part.pt()); registryMCOrigin.fill(HIST("part2/hTruthPt"), mcParticle.pt()); - // TOF Matching efficiency - if (part.mLambda() == 1) { - registryTOFMatch.fill(HIST("part2/hTofMatchPtAfterPID"), part.pt()); - } else { - registryTOFMatch.fill(HIST("part2/hTpcPt"), mcParticle.pt()); - } } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx index 297bdb03f73..e52c49cb3e4 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx @@ -531,9 +531,15 @@ struct FemtoUniversePairTaskTrackD0 { registry.add("DebugBdt/hBdtScore2", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); registry.add("DebugBdt/hBdtScore3", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); if (fillBDTvsPt) { - registry.add("DebugBdtMcReco/hBdtScore1", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); - registry.add("DebugBdtMcReco/hBdtScore2", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); - registry.add("DebugBdtMcReco/hBdtScore3", ";BDT score;Entries", {HistType::kTH1F, {axisBdtScore}}); + registry.add("DebugBdtMcReco/hBdtScore1VsPt", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore2VsPt", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore3VsPt", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore1VsPtD0", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore2VsPtD0", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore3VsPtD0", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore1VsPtD0bar", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore2VsPtD0bar", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); + registry.add("DebugBdtMcReco/hBdtScore3VsPtD0bar", ";BDT score;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisBdtScore, {vbins}}}); } if (applyMLOpt) { registry.add("D0D0bar_MLSel/hMassVsPt1", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -1466,14 +1472,19 @@ struct FemtoUniversePairTaskTrackD0 { } } else if ((part.partType() == aod::femtouniverseparticle::ParticleType::kD0) && (part.pt() > ConfDmesons.confMinPtD0D0barReco) && (part.pt() < ConfDmesons.confMaxPtD0D0barReco)) { if (fillBDTvsPt && std::abs(mcpart.pdgMCTruth()) == o2::constants::physics::Pdg::kD0) { - registry.fill(HIST("DebugBdtMcReco/hBdtScore1"), part.decayVtxX()); - registry.fill(HIST("DebugBdtMcReco/hBdtScore2"), part.decayVtxY()); - registry.fill(HIST("DebugBdtMcReco/hBdtScore3"), part.decayVtxZ()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore1VsPt"), part.decayVtxX(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore2VsPt"), part.decayVtxY(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore3VsPt"), part.decayVtxZ(), part.pt()); } if (mcpart.pdgMCTruth() == ConfDmesons.confPDGCodeD0) { mcRecoRegistry.fill(HIST("hMcRecD0"), part.pt(), part.eta()); mcRecoRegistry.fill(HIST("hMcRecD0Pt"), part.pt()); mcRecoRegistry.fill(HIST("hMcRecD0Phi"), part.phi()); + if (fillBDTvsPt) { + registry.fill(HIST("DebugBdtMcReco/hBdtScore1VsPtD0"), part.decayVtxX(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore2VsPtD0"), part.decayVtxY(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore3VsPtD0"), part.decayVtxZ(), part.pt()); + } if (part.tpcNClsFound() == 0) { // prompt candidates mcRecoRegistry.fill(HIST("hMcRecD0Prompt"), part.pt(), part.eta()); mcRecoRegistry.fill(HIST("hMcRecD0PromptPt"), part.pt()); @@ -1487,6 +1498,11 @@ struct FemtoUniversePairTaskTrackD0 { mcRecoRegistry.fill(HIST("hMcRecD0bar"), part.pt(), part.eta()); mcRecoRegistry.fill(HIST("hMcRecD0barPt"), part.pt()); mcRecoRegistry.fill(HIST("hMcRecD0barPhi"), part.phi()); + if (fillBDTvsPt) { + registry.fill(HIST("DebugBdtMcReco/hBdtScore1VsPtD0bar"), part.decayVtxX(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore2VsPtD0bar"), part.decayVtxY(), part.pt()); + registry.fill(HIST("DebugBdtMcReco/hBdtScore3VsPtD0bar"), part.decayVtxZ(), part.pt()); + } if (part.tpcNClsFound() == 0) { // prompt candidates mcRecoRegistry.fill(HIST("hMcRecD0barPrompt"), part.pt(), part.eta()); mcRecoRegistry.fill(HIST("hMcRecD0barPromptPt"), part.pt()); From 6c666e570a58cb37720769245c3485a5b3fd415a Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Mon, 18 May 2026 21:03:29 +0200 Subject: [PATCH 217/449] [PWGCF] FemtoUniverse Cascase Task -- added process functions for track-track correlation (#16291) Co-authored-by: Shirajum Monira --- ...toUniversePairTaskTrackCascadeExtended.cxx | 334 +++++++++++++++--- 1 file changed, 280 insertions(+), 54 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 4e3aa093b56..8a7bcb9f90c 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file femtoUniversePairTaskTrackCascadeExtended.cxx -/// \brief Task for cascade correlations and QA +/// \brief Task for track and cascade correlations and QA /// \author Barbara Chytla, WUT Warsaw, barbara.chytla@cern.ch /// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch @@ -19,10 +19,12 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include #include @@ -76,15 +78,37 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"}; /// applying narrow cut - Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; - Configurable confEta{"confEta", 0.8, "Eta cut for the global track"}; + struct : o2::framework::ConfigurableGroup { + Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + Configurable confEta{"confEta", 0.8, "Eta cut for the global track"}; + } narrowcuts; - // configurations for correlation part - Configurable confTrackChoicePartOne{"confTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"}; - Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; - Configurable confCascPDGCodePartTwo{"confCascPDGCodePartTwo", 3312, "Particle 2 (Cascade) - PDG code"}; + // configurations for track particles + struct : o2::framework::ConfigurableGroup { + Configurable confTrackChoicePartOne{"confTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"}; + Configurable confTrackChoicePartTwo{"confTrackChoicePartTwo", 0, "0:Proton, 1:Pion, 2:Kaon"}; + Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; + Configurable confTrkPDGCodePartTwo{"confTrkPDGCodePartTwo", 2212, "Particle 1 (Track) - PDG code"}; + Configurable confChargePart1{"confChargePart1", 1, "sign of track particle 1"}; + Configurable confChargePart2{"confChargePart2", -1, "sign of track particle 2"}; + Configurable confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of track particle"}; + Configurable confLPtPart1{"confLPtPart1", 0.5f, "lower limit for pt of track particle"}; + Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "combined TPC and TOF Sigma for track particle for momentum > Confmom"}; + } trackparticleconfigs; + + /// configurations for cascades + Configurable confCascPDGCode{"confCascPDGCode", 3312, "Particle 2 (Cascade) - PDG code"}; Configurable confCascType1{"confCascType1", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"}; Configurable confCascType2{"confCascType2", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"}; + Configurable confHPtPart2{"confHPtPart2", 4.0f, "higher limit for pt of cascade"}; + Configurable confLPtPart2{"confLPtPart2", 0.3f, "lower limit for pt of cascade"}; + Configurable confmom{"confmom", 0.75, "momentum threshold for particle identification using TOF"}; + Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"}; + Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"}; + Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"}; + Configurable confUseStrangenessTOF{"confUseStrangenessTOF", true, "Enable strangeness TOF for cascade PID"}; + + /// configurations for correlation part Configurable confIsCPR{"confIsCPR", false, "Close Pair Rejection"}; Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; @@ -93,18 +117,6 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.0, "Delta Eta cut for Close Pair Rejection"}; Configurable confIsSameSignCPR{"confIsSameSignCPR", false, "Close Pair Rejection for same sign children of cascades"}; - Configurable confChargePart1{"confChargePart1", 1, "sign of particle 1"}; - Configurable confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of particle 1"}; - Configurable confLPtPart1{"confLPtPart1", 0.5f, "lower limit for pt of particle 1"}; - Configurable confHPtPart2{"confHPtPart2", 4.0f, "higher limit for pt of particle 2"}; - Configurable confLPtPart2{"confLPtPart2", 0.3f, "lower limit for pt of particle 2"}; - Configurable confmom{"confmom", 0.75, "momentum threshold for particle identification using TOF"}; - Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"}; - Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle (track) momentum > Confmom"}; - Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"}; - Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"}; - Configurable confUseStrangenessTOF{"confUseStrangenessTOF", true, "Use strangeness TOF for cascade PID"}; - ConfigurableAxis confkstarBins{"confkstarBins", {1500, 0., 6.}, "binning kstar"}; ConfigurableAxis confMultBins{"confMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; @@ -130,25 +142,29 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; Configurable confCCDBEfficiency{"confCCDBEfficiency", "", "CCDB path to efficiency object"}; - Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); + Filter collisionFilter = (nabs(aod::collision::posZ) < narrowcuts.confZVertexCut); using FilteredFDCollisions = soa::Filtered; using FilteredFDCollision = FilteredFDCollisions::iterator; - /// Partition for particle 1 using extended table (track) - Partition partsOneFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + /// Partition for the first track particle using extended table + Partition partsTrackOneFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == trackparticleconfigs.confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < narrowcuts.confEta) && (aod::femtouniverseparticle::pt < trackparticleconfigs.confHPtPart1) && (aod::femtouniverseparticle::pt > trackparticleconfigs.confLPtPart1); // used for track - cascade and track - track correlations + + /// Partition for the first track particle using bitmask (without extended table) + Partition partsTrackOneBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == trackparticleconfigs.confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < narrowcuts.confEta) && (aod::femtouniverseparticle::pt < trackparticleconfigs.confHPtPart1) && (aod::femtouniverseparticle::pt > trackparticleconfigs.confLPtPart1); + Partition partsTrackOneMCgenBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < narrowcuts.confEta) && (aod::femtouniverseparticle::pt < trackparticleconfigs.confHPtPart1) && (aod::femtouniverseparticle::pt > trackparticleconfigs.confLPtPart1); - /// Partition for particle 1 without extended table (track) - Partition partsOneBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); - Partition partsOneMCgenBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); - Partition partsOneMCrecoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + /// Partition for the second track particle using extended table + Partition partsTrackTwoFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == trackparticleconfigs.confChargePart2) && (nabs(aod::femtouniverseparticle::eta) < narrowcuts.confEta) && (aod::femtouniverseparticle::pt < trackparticleconfigs.confHPtPart1) && (aod::femtouniverseparticle::pt > trackparticleconfigs.confLPtPart1); // used for track - track correlations - /// Partition for particle 2 using extended table (cascade) + /// Partition for the second track particle using bitmask (without extended table) + Partition partsTrackTwoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == trackparticleconfigs.confChargePart2) && (nabs(aod::femtouniverseparticle::eta) < narrowcuts.confEta) && (aod::femtouniverseparticle::pt < trackparticleconfigs.confHPtPart1) && (aod::femtouniverseparticle::pt > trackparticleconfigs.confLPtPart1); + + /// Partition for cascades using extended table Partition partsTwoFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); - /// Partition for particle 2 without extended table (cascade) + /// Partition for cascades using bitmask (without extended table) Partition partsTwoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); Partition partsTwoMCgenBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); - Partition partsTwoMCrecoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); /// Histogramming for track particle FemtoUniverseParticleHisto trackHistoPartOnePos; @@ -166,8 +182,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { FemtoUniverseContainer sameEventCont; FemtoUniverseContainer mixedEventCont; FemtoUniversePairCleaner pairCleaner; + FemtoUniversePairCleaner pairCleanerTrack; FemtoUniversePairCleaner pairCleanerCasc; FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseDetaDphiStar pairCloseRejectionTrack; FemtoUniverseDetaDphiStar pairCloseRejectionCasc; HistogramRegistry CascQAExtra{"CascQAExtra", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -221,7 +239,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (mom <= confmom) { return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); } else if (hasTOF == 1) { - return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); + return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < trackparticleconfigs.confNsigmaCombinedParticle); } else { return false; } @@ -231,9 +249,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { bool isNSigmaCombinedBitmask(float mom, const T& part) { if (mom <= confmom) { - return ((part.pidCut() & (1u << confTrackChoicePartOne)) != 0); + return ((part.pidCut() & (1u << trackparticleconfigs.confTrackChoicePartOne)) != 0); } else if ((part.pidCut() & 512u) != 0) { - return ((part.pidCut() & (64u << confTrackChoicePartOne)) != 0); + return ((part.pidCut() & (64u << trackparticleconfigs.confTrackChoicePartOne)) != 0); } else { return false; } @@ -340,8 +358,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { registryMCreco.add("plus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); registryMCreco.add("minus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); - trackHistoPartOnePos.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, confTrkPDGCodePartOne); - trackHistoPartOneNeg.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, confTrkPDGCodePartOne); + trackHistoPartOnePos.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, trackparticleconfigs.confTrkPDGCodePartOne); + trackHistoPartOneNeg.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, trackparticleconfigs.confTrkPDGCodePartOne); posChildHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); negChildHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); bachHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "hBachelor"); @@ -349,14 +367,18 @@ struct femtoUniversePairTaskTrackCascadeExtended { sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); - sameEventCont.setPDGCodes(confTrkPDGCodePartOne, confCascPDGCodePartTwo); - mixedEventCont.setPDGCodes(confTrkPDGCodePartOne, confCascPDGCodePartTwo); + sameEventCont.setPDGCodes(trackparticleconfigs.confTrkPDGCodePartOne, confCascPDGCode); + mixedEventCont.setPDGCodes(trackparticleconfigs.confTrkPDGCodePartOne, confCascPDGCode); pairCleaner.init(&qaRegistry); + pairCleanerTrack.init(&qaRegistry); pairCleanerCasc.init(&qaRegistry); + if (confIsCPR.value) { if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) pairCloseRejection.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); + if (doprocessSameEventTrack || doprocessSameEventTrackBitmask || doprocessMixedEventTrack || doprocessMixedEventTrackBitmask) + pairCloseRejectionTrack.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) pairCloseRejectionCasc.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); } @@ -366,7 +388,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!plocalEffFile || plocalEffFile.get()->IsZombie()) LOGF(fatal, "Could not load efficiency histogram from %s", confLocalEfficiency.value.c_str()); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - pEffHistp1 = (confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); LOGF(info, "Loaded efficiency histograms for track-Cascade."); } else if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) { @@ -382,7 +404,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - pEffHistp1 = (confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrMinus", now)); // note: works only for protons for now + pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrMinus", now)); // note: works only for protons for now pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); LOGF(info, "Loaded efficiency histograms for track-Cascade from CCDB"); } else if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) { @@ -524,16 +546,16 @@ struct femtoUniversePairTaskTrackCascadeExtended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) + if (!isNSigmaCombined(part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne], tofNSigmas[trackparticleconfigs.confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) continue; if (part.mAntiLambda() > 0) { - qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); - qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartOne]); trackHistoPartOnePos.fillQA(part); } else if (part.mAntiLambda() < 0) { - qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); - qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartOne]); trackHistoPartOneNeg.fillQA(part); } } else { @@ -554,7 +576,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; // PID if constexpr (std::experimental::is_detected::value) { - if (!isParticleCombined(p1, confTrackChoicePartOne)) + if (!isParticleCombined(p1, trackparticleconfigs.confTrackChoicePartOne)) continue; } else { if (!isNSigmaCombinedBitmask(p1.p(), p1)) { @@ -606,13 +628,13 @@ struct femtoUniversePairTaskTrackCascadeExtended { void processSameEvent(const FilteredFDCollision& col, const FemtoFullParticles& parts) { - doSameEvent(col, parts, partsOneFull, partsTwoFull); + doSameEvent(col, parts, partsTrackOneFull, partsTwoFull); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEvent, "Enable processing same event for track - cascade", false); void processSameEventBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts) { - doSameEvent(col, parts, partsOneBasic, partsTwoBasic); + doSameEvent(col, parts, partsTrackOneBasic, partsTwoBasic); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventBitmask, "Enable processing same event for track - cascade using bitmask for PID", false); @@ -779,6 +801,141 @@ struct femtoUniversePairTaskTrackCascadeExtended { } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCascBitmask, "Enable processing same event for cascade - cascade using bitmask for PID", false); + /// track-track correlations + template + void doSameEventTrack(const FilteredFDCollision& col, const TableType& parts, PartitionType& partsOne, PartitionType& partsTwo) + { + const auto& magFieldTesla = col.magField(); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + eventHisto.fillQA(col); + + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + for (const auto& part : groupPartsOne) { + if constexpr (std::experimental::is_detected::value) { + /// PID plot for the first track particle + const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; + const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; + + if (!isNSigmaCombined(part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne], tofNSigmas[trackparticleconfigs.confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) + continue; + + if (part.mAntiLambda() > 0) { + qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartOne]); + trackHistoPartOneNeg.fillQA(part); + } + } else { + if (!isNSigmaCombinedBitmask(part.p(), part)) { + continue; + } + if (part.mAntiLambda() > 0) { + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + trackHistoPartOneNeg.fillQA(part); + } + } + } + + if (trackparticleconfigs.confChargePart1 != trackparticleconfigs.confChargePart2) { + for (const auto& part : groupPartsTwo) { + if constexpr (std::experimental::is_detected::value) { + /// PID plot for the first track particle + const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; + const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; + + if (!isNSigmaCombined(part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartTwo], tofNSigmas[trackparticleconfigs.confTrackChoicePartTwo], (part.pidCut() & 512u) != 0)) + continue; + + if (part.mAntiLambda() > 0) { + qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartTwo]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartTwo]); + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[trackparticleconfigs.confTrackChoicePartTwo]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[trackparticleconfigs.confTrackChoicePartTwo]); + trackHistoPartOneNeg.fillQA(part); + } + } else { + if (!isNSigmaCombinedBitmask(part.p(), part)) { + continue; + } + if (part.mAntiLambda() > 0) { + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + trackHistoPartOneNeg.fillQA(part); + } + } + } + } + + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + // PID for the first track particle + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p1, trackparticleconfigs.confTrackChoicePartOne)) + return; + } else { + if (!isNSigmaCombinedBitmask(p1.p(), p1)) { + return; + } + } + // PID for the second track particle + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p2, trackparticleconfigs.confTrackChoicePartTwo)) + return; + } else { + if (!isNSigmaCombinedBitmask(p2.p(), p2)) { + return; + } + } + // track cleaning + if (!pairCleanerTrack.isCleanPair(p1, p2, parts)) { + return; + } + + if (confIsCPR.value) { + if (pairCloseRejectionTrack.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + return; + } + } + + float weight = 1.0f; + if (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); + sameEventCont.setPair(p1, p2, multCol, confUse3D, weight); + }; + + /// Now build the combinations for track-track particles + if (trackparticleconfigs.confTrackChoicePartOne == trackparticleconfigs.confTrackChoicePartTwo && trackparticleconfigs.confChargePart1 == trackparticleconfigs.confChargePart2) { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } else { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } + } + + void processSameEventTrack(const FilteredFDCollision& col, const FemtoFullParticles& parts) + { + doSameEventTrack(col, parts, partsTrackOneFull, partsTrackTwoFull); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventTrack, "Enable processing same event for track - track", false); + + void processSameEventTrackBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts) + { + doSameEventTrack(col, parts, partsTrackOneBasic, partsTrackTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventTrackBitmask, "Enable processing same event for track - track using bitmask for PID", false); + /// track - cascade correlations template void doMixedEvent(const FilteredFDCollisions& cols, const TableType& parts, PartitionType& partsOne, PartitionType& partsTwo) @@ -804,7 +961,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; // PID if constexpr (std::experimental::is_detected::value) { - if (!isParticleCombined(p1, confTrackChoicePartOne)) + if (!isParticleCombined(p1, trackparticleconfigs.confTrackChoicePartOne)) continue; } else { if (!isNSigmaCombinedBitmask(p1.p(), p1)) { @@ -865,13 +1022,13 @@ struct femtoUniversePairTaskTrackCascadeExtended { void processMixedEvent(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) { - doMixedEvent(cols, parts, partsOneFull, partsTwoFull); + doMixedEvent(cols, parts, partsTrackOneFull, partsTwoFull); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEvent, "Enable processing mixed event for track - cascade", false); void processMixedEventBitmask(const FilteredFDCollisions& cols, const aod::FDParticles& parts) { - doMixedEvent(cols, parts, partsOneBasic, partsTwoBasic); + doMixedEvent(cols, parts, partsTrackOneBasic, partsTwoBasic); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventBitmask, "Enable processing mixed event for track - cascade using bitmask for PID", false); @@ -972,12 +1129,81 @@ struct femtoUniversePairTaskTrackCascadeExtended { } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventCascBitmask, "Enable processing mixed event for cascade - cascade using bitmask for PID", false); + /// track-track correlations + template + void doMixedEventTrack(const FilteredFDCollisions& cols, const TableType& parts, PartitionType& partsOne, PartitionType& partsTwo) + { + ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // PID for the first track particle + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p1, trackparticleconfigs.confTrackChoicePartOne)) + continue; + } else { + if (!isNSigmaCombinedBitmask(p1.p(), p1)) { + continue; + } + } + // PID for the second track particle + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p2, trackparticleconfigs.confTrackChoicePartTwo)) + continue; + } else { + if (!isNSigmaCombinedBitmask(p2.p(), p2)) { + continue; + } + } + // track cleaning + if (!pairCleanerTrack.isCleanPair(p1, p2, parts)) { + continue; + } + + if (confIsCPR.value) { + if (pairCloseRejectionTrack.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + continue; + } + } + + float weight = 1.0f; + if (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); + mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); + } + } + } + + void processMixedEventTrack(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) + { + doMixedEventTrack(cols, parts, partsTrackOneFull, partsTrackTwoFull); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventTrack, "Enable processing mixed event for track - track", false); + + void processMixedEventTrackBitmask(const FilteredFDCollisions& cols, const aod::FDParticles& parts) + { + doMixedEventTrack(cols, parts, partsTrackOneBasic, partsTrackTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventTrackBitmask, "Enable processing mixed event for track - track using bitmask for PID", false); + // MC truth for track - cascade void processSameEventMCgen(const FilteredFDCollision& col, [[maybe_unused]] const aod::FDParticles& parts) { const int multCol = confUseCent ? col.multV0M() : col.multNtr(); - auto groupPartsOne = partsOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsOne = partsTrackOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); eventHisto.fillQA(col); @@ -991,7 +1217,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { for (const auto& part : groupPartsOne) { int pdgCode = static_cast(part.pidCut()); - if (pdgCode != confTrkPDGCodePartOne) + if (pdgCode != trackparticleconfigs.confTrkPDGCodePartOne) continue; const auto& pdgTrackParticle = pdgMC->GetParticle(pdgCode); if (!pdgTrackParticle) { @@ -1006,7 +1232,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { } for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) + if (static_cast(p1.pidCut()) != trackparticleconfigs.confTrkPDGCodePartOne) continue; int pdgCodeCasc = static_cast(p2.pidCut()); if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) @@ -1062,7 +1288,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); - auto groupPartsOne = partsOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsOne = partsTrackOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); @@ -1072,7 +1298,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; } for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) + if (static_cast(p1.pidCut()) != trackparticleconfigs.confTrkPDGCodePartOne) continue; int pdgCodeCasc = static_cast(p2.pidCut()); if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) From 00033f7ed738ab73317c1ac773f57cdbb28f480c Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Mon, 18 May 2026 22:16:43 +0200 Subject: [PATCH 218/449] [PWGCF] FemtoUniverse V0 Task -- added ccdb timestamp configs for efficiency (#16296) Co-authored-by: Shirajum Monira --- ...toUniversePairTaskTrackCascadeExtended.cxx | 30 +++++++++++-------- .../femtoUniversePairTaskTrackV0Extended.cxx | 26 +++++++++------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 8a7bcb9f90c..e7da5f6ad9c 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -98,7 +99,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { /// configurations for cascades Configurable confCascPDGCode{"confCascPDGCode", 3312, "Particle 2 (Cascade) - PDG code"}; - Configurable confCascType1{"confCascType1", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"}; + Configurable confCascType1{"confCascType1", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade and cascade-cascade combination"}; Configurable confCascType2{"confCascType2", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"}; Configurable confHPtPart2{"confHPtPart2", 4.0f, "higher limit for pt of cascade"}; Configurable confLPtPart2{"confLPtPart2", 0.3f, "lower limit for pt of cascade"}; @@ -139,8 +140,12 @@ struct femtoUniversePairTaskTrackCascadeExtended { } twotracksconfigs; // Efficiency - Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; - Configurable confCCDBEfficiency{"confCCDBEfficiency", "", "CCDB path to efficiency object"}; + struct : o2::framework::ConfigurableGroup { + Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + Configurable confCCDBEfficiency{"confCCDBEfficiency", "", "CCDB path to efficiency object"}; + Configurable confCCDBNoLaterThanTrack{"confCCDBNoLaterThanTrack", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable confCCDBNoLaterThanCasc{"confCCDBNoLaterThanCasc", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + } ccdbEffLoader; Filter collisionFilter = (nabs(aod::collision::posZ) < narrowcuts.confZVertexCut); using FilteredFDCollisions = soa::Filtered; @@ -383,10 +388,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { pairCloseRejectionCasc.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); } - if (!confLocalEfficiency.value.empty()) { - plocalEffFile = std::unique_ptr(TFile::Open(confLocalEfficiency.value.c_str(), "read")); + if (!ccdbEffLoader.confLocalEfficiency.value.empty()) { + plocalEffFile = std::unique_ptr(TFile::Open(ccdbEffLoader.confLocalEfficiency.value.c_str(), "read")); if (!plocalEffFile || plocalEffFile.get()->IsZombie()) - LOGF(fatal, "Could not load efficiency histogram from %s", confLocalEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram from %s", ccdbEffLoader.confLocalEfficiency.value.c_str()); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); @@ -396,20 +401,19 @@ struct femtoUniversePairTaskTrackCascadeExtended { pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); LOGF(info, "Loaded efficiency histograms for Cascade-Cascade."); } - } else if (!confCCDBEfficiency.value.empty()) { + } else if (!ccdbEffLoader.confCCDBEfficiency.value.empty()) { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - ccdb->setCreatedNotAfter(now); + ccdb->setCreatedNotAfter(std::max(ccdbEffLoader.confCCDBNoLaterThanTrack.value, ccdbEffLoader.confCCDBNoLaterThanCasc.value)); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrMinus", now)); // note: works only for protons for now - pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); + pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrPlus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrMinus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)); /// works only for protons + pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/Cascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/AntiCascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)); LOGF(info, "Loaded efficiency histograms for track-Cascade from CCDB"); } else if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) { - pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); - pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); + pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/Cascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/AntiCascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)); + pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/Cascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/AntiCascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)); LOGF(info, "Loaded efficiency histograms for Cascade-Cascade from CCDB."); } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index c33d24594a8..e54b10b83f7 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -202,7 +203,11 @@ struct FemtoUniversePairTaskTrackV0Extended { } ConfCPR; // Efficiency - Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + struct : o2::framework::ConfigurableGroup { + Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + Configurable confCCDBNoLaterThanTrack{"confCCDBNoLaterThanTrack", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable confCCDBNoLaterThanV0{"confCCDBNoLaterThanV0", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + } ccdbEffLoader; EffCorConfigurableGroup effCorConfGroup; EfficiencyCorrection effCorrection{&effCorConfGroup}; @@ -429,12 +434,12 @@ struct FemtoUniversePairTaskTrackV0Extended { pairCloseRejectionV0.init(&resultRegistry, &qaRegistry, ConfCPR.confDeltaEtaAxis, ConfCPR.confDeltaPhiStarAxis, ConfCPR.confCPRdeltaPhiCutMin.value, ConfCPR.confCPRdeltaPhiCutMax.value, ConfCPR.confCPRdeltaEtaCutMin.value, ConfCPR.confCPRdeltaEtaCutMax.value, ConfCPR.confCPRChosenRadii.value, ConfCPR.confCPRPlotPerRadii.value); } - if (!confLocalEfficiency.value.empty()) { - plocalEffFile = std::unique_ptr(TFile::Open(confLocalEfficiency.value.c_str(), "read")); + if (!ccdbEffLoader.confLocalEfficiency.value.empty()) { + plocalEffFile = std::unique_ptr(TFile::Open(ccdbEffLoader.confLocalEfficiency.value.c_str(), "read")); if (!plocalEffFile || plocalEffFile.get()->IsZombie()) - LOGF(fatal, "Could not load efficiency histogram from %s", confLocalEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram from %s", ccdbEffLoader.confLocalEfficiency.value.c_str()); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons pEffHistp2 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); LOGF(info, "Loaded efficiency histograms for track-V0."); } else if (doprocessSameEventV0 || doprocessSameEventV0Bitmask || doprocessMixedEventV0 || doprocessMixedEventV0Bitmask) { @@ -447,15 +452,14 @@ struct FemtoUniversePairTaskTrackV0Extended { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - ccdb->setCreatedNotAfter(now); + ccdb->setCreatedNotAfter(std::max(ccdbEffLoader.confCCDBNoLaterThanTrack.value, ccdbEffLoader.confCCDBNoLaterThanV0.value)); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrMinus", now)); // note: works only for protons for now - pEffHistp2 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); + pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrPlus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrMinus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)); // note: works only for protons + pEffHistp2 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)); LOGF(info, "Loaded efficiency histograms for track-V0 from CCDB."); } else if (doprocessSameEventV0 || doprocessSameEventV0Bitmask || doprocessMixedEventV0 || doprocessMixedEventV0Bitmask) { - pEffHistp1 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); - pEffHistp2 = (ConfV0Selection.confV0Type2 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); + pEffHistp1 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)); + pEffHistp2 = (ConfV0Selection.confV0Type2 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", ccdbEffLoader.confCCDBNoLaterThanV0.value)); LOGF(info, "Loaded efficiency histograms for V0-V0 from CCDB."); } } From e746b6538d7a37669221f8b623c5938c03619575 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Mon, 18 May 2026 22:25:37 +0200 Subject: [PATCH 219/449] [PWGDQ] Fixing issue with event mixing in table reader + flow (#16289) Co-authored-by: Lucamicheletti92 --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index d0f0a223ea6..40450cdb4a8 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -265,6 +265,7 @@ constexpr static uint32_t gkEventFillMapWithCovZdcFit = VarManager::ObjTypes::Re constexpr static uint32_t gkEventFillMapWithMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra; // New fillmap constexpr static uint32_t gkEventFillMapWithMultExtraWithQVector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra | VarManager::ObjTypes::CollisionQvect; +// constexpr static uint32_t gkEventFillMapWithMultExtraWithQVector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra | VarManager::ObjTypes::ReducedEventQvector; constexpr static uint32_t gkEventFillMapWithMultExtraZdc = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra | VarManager::ReducedZdc; constexpr static uint32_t gkEventFillMapWithMultExtraZdcFit = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra | VarManager::ReducedZdc | VarManager::ReducedFit; constexpr static uint32_t gkEventFillMapWithCovZdcFitMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ReducedZdc | VarManager::ReducedFit | VarManager::ReducedEventMultExtra; @@ -1389,8 +1390,8 @@ struct AnalysisSameEventPairing { { fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra") || context.mOptions.get("processBarrelOnlyWithQvectorCentrSkimmedNoCov"); fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed") || context.mOptions.get("processMixingBarrelSkimmedFlow") || context.mOptions.get("processMixingBarrelWithQvectorCentrSkimmedNoCov"); - fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMuonOnlySkimmedFlow") || context.mOptions.get("processMixingMuonSkimmed"); - fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed"); + fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMuonOnlySkimmedFlow"); + fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed") || context.mOptions.get("processMixingMuonSkimmedFlow"); fEnableBarrelMuonHistos = context.mOptions.get("processElectronMuonSkimmed"); fEnableBarrelMuonMixingHistos = context.mOptions.get("processMixingElectronMuonSkimmed"); @@ -2222,6 +2223,9 @@ struct AnalysisSameEventPairing { if constexpr ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0) { VarManager::FillPairVn(t1, t2); } + if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0) { + VarManager::FillPairVn(t1, t2); + } pairSign = t1.sign() + t2.sign(); // store the ambiguity number of the two dilepton legs in the last 4 digits of the two-track filter if (t1.muonAmbiguityInBunch() > 1) { @@ -2691,7 +2695,7 @@ struct AnalysisSameEventPairing { runSameSideMixing(events, muonAssocs, muons, muonAssocsPerCollision); } - void processMixingMuonSkimmedFlow(soa::Filtered& events, + void processMixingMuonSkimmedFlow(soa::Filtered& events, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { runSameSideMixing(events, muonAssocs, muons, muonAssocsPerCollision); From 739c94d703f55583090d1ce441beedd12eb3e174 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Mon, 18 May 2026 22:27:33 +0200 Subject: [PATCH 220/449] [PWGDQ] add code to emulate a shift of the dipole (#16294) --- PWGDQ/Tasks/muonGlobalAlignment.cxx | 40 ++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/muonGlobalAlignment.cxx b/PWGDQ/Tasks/muonGlobalAlignment.cxx index 9eb13445756..1186ef99d08 100644 --- a/PWGDQ/Tasks/muonGlobalAlignment.cxx +++ b/PWGDQ/Tasks/muonGlobalAlignment.cxx @@ -150,6 +150,7 @@ struct muonGlobalAlignment { Configurable fMftTracksMultiplicityMax{"cfgMftTracksMultiplicityMax", 0, "Maximum number of MFT tracks to be processed per event (zero means no limit)"}; Configurable fVertexZshift{"cfgVertexZshift", 0.0f, "Correction to the vertex z position"}; + Configurable fDipoleZshift{"cfgDipoleZshift", 0.0f, "Correction to the dipole z position"}; //// Variables for MFT alignment corrections struct : ConfigurableGroup { @@ -1200,6 +1201,15 @@ struct muonGlobalAlignment { if (mchTrack.getZ() < absBack && z > absFront) { // extrapolation through the absorber in the upstream direction o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrack, z); + } else if (z < absBack) { + // extrapolation downstream of the absorber, correct for dipole longitudinal shift if needed + if (fDipoleZshift.value != 0) { + mchTrack.setZ(mchTrack.getZ() + fDipoleZshift.value); + o2::mch::TrackExtrap::extrapToZCov(mchTrack, z + fDipoleZshift.value); + mchTrack.setZ(mchTrack.getZ() - fDipoleZshift.value); + } else { + o2::mch::TrackExtrap::extrapToZCov(mchTrack, z); + } } else { // all other cases o2::mch::TrackExtrap::extrapToZCov(mchTrack, z); @@ -1389,7 +1399,24 @@ struct muonGlobalAlignment { o2::mch::TrackExtrap::extrapToZ(mftTrackProp, -466.f); UpdateTrackMomentum(mftTrackProp, mchTrackPar); } - o2::mch::TrackExtrap::extrapToZ(mftTrackProp, z); + + if (fDipoleZshift.value != 0) { + // extrapolate to the back of the absorber, taking into account the dipole shift, + // to avoid that the correction bring the track starting point back into the absorber + if (fDipoleZshift.value < 0) { + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, -505.f); + } else if (fDipoleZshift.value > 0) { + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, -505.f - fDipoleZshift.value); + } + // shift the track starting point + mftTrackProp.setZ(mftTrackProp.getZ() + fDipoleZshift.value); + // extrapolate to the final z, corrected for the dipole shift + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, z + fDipoleZshift.value); + // remove the shift from the extrapolated track + mftTrackProp.setZ(mftTrackProp.getZ() - fDipoleZshift.value); + } else { + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, z); + } return MCHtoFwd(mftTrackProp); } @@ -1595,6 +1622,11 @@ struct muonGlobalAlignment { transformNew[cluster.deId()].LocalToMaster(local, master); } + // shift the clusters to correct the longitudinal shift of the dipole + if (fDipoleZshift.value != 0) { + master.SetZ(master.z() + fDipoleZshift.value); + } + if (applyCorrections) { auto correctionsIt = mMchAlignmentCorrections.find(cluster.deId()); if (correctionsIt != mMchAlignmentCorrections.end()) { @@ -1628,6 +1660,12 @@ struct muonGlobalAlignment { LOGF(fatal, "Muon track %d has no associated clusters.", mchTrack.globalIndex()); } + // subtract the longitudinal shift of the dipole from the track z + if (fDipoleZshift.value != 0) { + auto& trackParam = *(convertedTrack.begin()); + trackParam.setZ(trackParam.getZ() - fDipoleZshift.value); + } + return !removable; } From 718cdbbaff578988e6c89205469d9a21ea4316b1 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Mon, 18 May 2026 23:22:27 +0200 Subject: [PATCH 221/449] [PWGHF] Cut variation: add QA histograms, save output upon user's request (#16297) --- PWGHF/D2H/Macros/compute_fraction_cutvar.py | 167 +++++++++++++------- PWGHF/D2H/Macros/config_cutvar_example.json | 12 ++ PWGHF/D2H/Macros/cut_variation.py | 14 +- 3 files changed, 137 insertions(+), 56 deletions(-) diff --git a/PWGHF/D2H/Macros/compute_fraction_cutvar.py b/PWGHF/D2H/Macros/compute_fraction_cutvar.py index 0099185472b..0e5ced6f8a5 100644 --- a/PWGHF/D2H/Macros/compute_fraction_cutvar.py +++ b/PWGHF/D2H/Macros/compute_fraction_cutvar.py @@ -14,12 +14,34 @@ import numpy as np # pylint: disable=import-error import ROOT # pylint: disable=import-error +from enum import IntEnum, auto sys.path.insert(0, '..') from cut_variation import CutVarMinimiser +from cut_variation import MinimisationStatus from style_formatter import set_object_style # pylint: disable=no-member,too-many-locals,too-many-statements +class PlotType(IntEnum): + Rawy = 0 + Eff = auto() + Frac = auto() + Cov = auto() + Unc = auto() + N = auto() + +class ObjectToSave(IntEnum): + Canvas = 0 + RawYield = auto() + Uncertainty = auto() + Efficiency = auto() + Fraction = auto() + CorrectedYield = auto() + CorrelationMatrix = auto() + Covariance = auto() + CorrectedFraction = auto() + MinimisationStatus = auto() + N = auto() def main(config): """ @@ -61,17 +83,31 @@ def main(config): if (pt_bin_to_process != -1 and pt_bin_to_process < 1) or pt_bin_to_process > hist_rawy[0].GetNbinsX(): sys.exit("\33[31mFatal error: pt_bin_to_process must be a positive value up to number of bins in raw yield histogram. Exit.") - is_draw_title_rawy = cfg.get("is_draw_title", {}).get("rawy", True) - is_draw_title_eff = cfg.get("is_draw_title", {}).get("eff", False) - is_draw_title_frac = cfg.get("is_draw_title", {}).get("frac", False) - is_draw_title_cov = cfg.get("is_draw_title", {}).get("cov", False) - is_draw_title_unc = cfg.get("is_draw_title", {}).get("unc", True) - - is_save_canvas_as_macro_rawy = cfg.get("is_save_canvas_as_macro", {}).get("rawy", False) - is_save_canvas_as_macro_eff = cfg.get("is_save_canvas_as_macro", {}).get("eff", False) - is_save_canvas_as_macro_frac = cfg.get("is_save_canvas_as_macro", {}).get("frac", False) - is_save_canvas_as_macro_cov = cfg.get("is_save_canvas_as_macro", {}).get("cov", False) - is_save_canvas_as_macro_unc = cfg.get("is_save_canvas_as_macro", {}).get("unc", False) + is_draw_title = [False] * PlotType.N + is_draw_title[PlotType.Rawy] = cfg.get("is_draw_title", {}).get("rawy", True) + is_draw_title[PlotType.Eff] = cfg.get("is_draw_title", {}).get("eff", False) + is_draw_title[PlotType.Frac] = cfg.get("is_draw_title", {}).get("frac", False) + is_draw_title[PlotType.Cov] = cfg.get("is_draw_title", {}).get("cov", False) + is_draw_title[PlotType.Unc] = cfg.get("is_draw_title", {}).get("unc", True) + + is_save_canvas_as_macro = [False] * PlotType.N + is_save_canvas_as_macro[PlotType.Rawy] = cfg.get("is_save_canvas_as_macro", {}).get("rawy", False) + is_save_canvas_as_macro[PlotType.Eff] = cfg.get("is_save_canvas_as_macro", {}).get("eff", False) + is_save_canvas_as_macro[PlotType.Frac] = cfg.get("is_save_canvas_as_macro", {}).get("frac", False) + is_save_canvas_as_macro[PlotType.Cov] = cfg.get("is_save_canvas_as_macro", {}).get("cov", False) + is_save_canvas_as_macro[PlotType.Unc] = cfg.get("is_save_canvas_as_macro", {}).get("unc", False) + + is_save_to_root_file = [False] * ObjectToSave.N + is_save_to_root_file[ObjectToSave.Canvas] = cfg.get("is_save_to_root_file", {}).get("canvas", True) + is_save_to_root_file[ObjectToSave.RawYield] = cfg.get("is_save_to_root_file", {}).get("raw_yield", True) + is_save_to_root_file[ObjectToSave.Uncertainty] = cfg.get("is_save_to_root_file", {}).get("uncertainty", True) + is_save_to_root_file[ObjectToSave.Efficiency] = cfg.get("is_save_to_root_file", {}).get("efficiency", True) + is_save_to_root_file[ObjectToSave.Fraction] = cfg.get("is_save_to_root_file", {}).get("fraction", True) + is_save_to_root_file[ObjectToSave.CorrectedYield] = cfg.get("is_save_to_root_file", {}).get("corrected_yield", True) + is_save_to_root_file[ObjectToSave.CorrelationMatrix] = cfg.get("is_save_to_root_file", {}).get("correlation_matrix", True) + is_save_to_root_file[ObjectToSave.Covariance] = cfg.get("is_save_to_root_file", {}).get("covariance", True) + is_save_to_root_file[ObjectToSave.CorrectedFraction] = cfg.get("is_save_to_root_file", {}).get("corrected_fraction", True) + is_save_to_root_file[ObjectToSave.MinimisationStatus] = cfg.get("is_save_to_root_file", {}).get("minimisation_status", True) if cfg["central_efficiency"]["computerawfrac"]: infile_name = os.path.join(cfg["central_efficiency"]["inputdir"], cfg["central_efficiency"]["inputfile"]) @@ -100,7 +136,9 @@ def main(config): hist_covariance_npnp = hist_rawy[0].Clone("hCovNonPromptNonPrompt") hist_corrfrac_prompt = hist_rawy[0].Clone("hCorrFracPrompt") hist_corrfrac_nonprompt = hist_rawy[0].Clone("hCorrFracNonPrompt") - for histo in hist_corry_prompt, hist_corry_nonprompt, hist_covariance_pnp, hist_covariance_pp, hist_covariance_npnp, hist_corrfrac_prompt, hist_corrfrac_nonprompt: + hist_minimisation_status = hist_rawy[0].Clone("hMinimizationStatus") + hist_red_chi2 = hist_rawy[0].Clone("hChi2OverNdf") + for histo in hist_corry_prompt, hist_corry_nonprompt, hist_covariance_pnp, hist_covariance_pp, hist_covariance_npnp, hist_corrfrac_prompt, hist_corrfrac_nonprompt, hist_minimisation_status, hist_red_chi2: histo.Reset() hist_corry_prompt.GetYaxis().SetTitle("corrected yields prompt") hist_corry_nonprompt.GetYaxis().SetTitle("corrected yields non-prompt") @@ -109,6 +147,13 @@ def main(config): hist_covariance_npnp.GetYaxis().SetTitle("#sigma(non-prompt, non-prompt)") hist_corrfrac_prompt.GetYaxis().SetTitle("corrected fraction prompt") hist_corrfrac_nonprompt.GetYaxis().SetTitle("corrected fraction non-prompt") + hist_minimisation_status.GetYaxis().SetTitle("minimisation status") + hist_red_chi2.GetYaxis().SetTitle("#chi^{2}/ndf") + hist_minimisation_status_title = "" + for min_status in MinimisationStatus: + hist_minimisation_status_title += (str(min_status.value) + " = " + min_status.name + ", ") + hist_minimisation_status_title = hist_minimisation_status_title[:-2] + hist_minimisation_status.SetTitle(hist_minimisation_status_title) set_object_style( hist_corry_prompt, color=ROOT.kRed + 1, @@ -124,6 +169,8 @@ def main(config): set_object_style(hist_covariance_pnp) set_object_style(hist_covariance_pp) set_object_style(hist_covariance_npnp) + set_object_style(hist_minimisation_status) + set_object_style(hist_red_chi2) set_object_style( hist_corrfrac_prompt, color=ROOT.kRed + 1, @@ -158,16 +205,15 @@ def main(config): ) pt_bin_to_process_name_suffix = "" - if pt_bin_to_process != -1: - pt_bin_to_process_name_suffix = "_bin_" + str(pt_bin_to_process) + if pt_bin_to_process != -1: pt_bin_to_process_name_suffix = "_bin_" + str(pt_bin_to_process) output_name_template = cfg['output']['file'].replace(".root", "") + pt_bin_to_process_name_suffix + ".root" output = ROOT.TFile(os.path.join(cfg["output"]["directory"], output_name_template), "recreate") n_sets = len(hist_rawy) pt_axis_title = hist_rawy[0].GetXaxis().GetTitle() for ipt in range(hist_rawy[0].GetNbinsX()): - if pt_bin_to_process !=-1 and ipt+1 != pt_bin_to_process: - continue + if pt_bin_to_process !=-1 and ipt+1 != pt_bin_to_process: continue + all_vectors_monotonous = MinimisationStatus.Success pt_min = hist_rawy[0].GetXaxis().GetBinLowEdge(ipt + 1) pt_max = hist_rawy[0].GetXaxis().GetBinUpEdge(ipt + 1) print(f"\n\nINFO: processing pt range {ipt+1} from {pt_min} to {pt_max} {pt_axis_title}") @@ -183,16 +229,22 @@ def main(config): if cfg["minimisation"]["correlated"]: if not (np.all(rawy[1:] > rawy[:-1]) or np.all(rawy[1:] < rawy[:-1])): + all_vectors_monotonous = MinimisationStatus.MonotonyViolation print("\0\33[33mWARNING! main(): the raw yield vector is not monotonous. Check the input for stability.\0\33[0m") print(f"raw yield vector elements = {rawy}\n") if not (np.all(unc_rawy[1:] > unc_rawy[:-1]) or np.all(unc_rawy[1:] < unc_rawy[:-1])): + all_vectors_monotonous = MinimisationStatus.MonotonyViolation print("\0\33[33mWARNING! main(): the raw yield uncertainties vector is not monotonous. Check the input for stability.\0\33[0m") print(f"raw yield uncertainties vector elements = {unc_rawy}\n") + if not (np.all(effp[1:] > effp[:-1]) or np.all(effp[1:] < effp[:-1])): + sys.exit(f"\33[31mFatal error: the prompt efficiency vector is not monotonous. Check the input. Exit.\33[0m") + if not (np.all(effnp[1:] > effnp[:-1]) or np.all(effnp[1:] < effnp[:-1])): + sys.exit(f"\33[31mFatal error: the nonprompt efficiency vector is not monotonous. Check the input. Exit.\33[0m") minimiser = CutVarMinimiser(rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp) status = minimiser.minimise_system(cfg["minimisation"]["correlated"]) - if status: + if status != MinimisationStatus.Fail: hist_corry_prompt.SetBinContent(ipt + 1, minimiser.get_prompt_yield_and_error()[0]) hist_corry_prompt.SetBinError(ipt + 1, minimiser.get_prompt_yield_and_error()[1]) hist_corry_nonprompt.SetBinContent(ipt + 1, minimiser.get_nonprompt_yield_and_error()[0]) @@ -209,6 +261,8 @@ def main(config): hist_corrfrac_prompt.SetBinError(ipt + 1, corr_frac_prompt[1]) hist_corrfrac_nonprompt.SetBinContent(ipt + 1, corr_frac_nonprompt[0]) hist_corrfrac_nonprompt.SetBinError(ipt + 1, corr_frac_nonprompt[1]) + hist_minimisation_status.SetBinContent(ipt + 1, max(status, all_vectors_monotonous)) + hist_red_chi2.SetBinContent(ipt + 1, minimiser.get_red_chi2()) if cfg["central_efficiency"]["computerawfrac"]: raw_frac_prompt = minimiser.get_raw_prompt_fraction( hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) @@ -223,55 +277,56 @@ def main(config): hist_bin_title = f"bin # {ipt+1}; {pt_axis_title}#in ({pt_min}; {pt_max})" - hist_bin_title_rawy = hist_bin_title if is_draw_title_rawy else "" + hist_bin_title_rawy = hist_bin_title if is_draw_title[PlotType.Rawy] else "" canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_rawy) output.cd() - canv_rawy.Write() - for _, hist in histos_rawy.items(): - hist.Write() - if (is_save_canvas_as_macro_rawy): - canv_rawy.SaveAs(f"canv_rawy_{ipt+1}.C") + if is_save_to_root_file[ObjectToSave.Canvas]: canv_rawy.Write() + if is_save_to_root_file[ObjectToSave.RawYield]: + for _, hist in histos_rawy.items(): + hist.Write() + if is_save_canvas_as_macro[PlotType.Rawy]: canv_rawy.SaveAs(f"canv_rawy_{ipt+1}.C") - hist_bin_title_unc = hist_bin_title if is_draw_title_unc else "" + hist_bin_title_unc = hist_bin_title if is_draw_title[PlotType.Unc] else "" canv_unc, histos_unc, leg_unc = minimiser.plot_uncertainties(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_unc) output.cd() - canv_unc.Write() - for _, hist in histos_unc.items(): - hist.Write() - if (is_save_canvas_as_macro_unc): - canv_unc.SaveAs(f"canv_unc_{ipt+1}.C") + if is_save_to_root_file[ObjectToSave.Canvas]: canv_unc.Write() + if is_save_to_root_file[ObjectToSave.Uncertainty]: + for _, hist in histos_unc.items(): + hist.Write() + if is_save_canvas_as_macro[PlotType.Unc]: canv_unc.SaveAs(f"canv_unc_{ipt+1}.C") - hist_bin_title_eff = hist_bin_title if is_draw_title_eff else "" + hist_bin_title_eff = hist_bin_title if is_draw_title[PlotType.Eff] else "" canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_eff) output.cd() - canv_eff.Write() - for _, hist in histos_eff.items(): - hist.Write() - if (is_save_canvas_as_macro_eff): - canv_eff.SaveAs(f"canv_eff_{ipt+1}.C") + if is_save_to_root_file[ObjectToSave.Canvas]: canv_eff.Write() + if is_save_to_root_file[ObjectToSave.Efficiency]: + for _, hist in histos_eff.items(): + hist.Write() + if is_save_canvas_as_macro[PlotType.Eff]: canv_eff.SaveAs(f"canv_eff_{ipt+1}.C") - hist_bin_title_frac = hist_bin_title if is_draw_title_frac else "" + hist_bin_title_frac = hist_bin_title if is_draw_title[PlotType.Frac] else "" canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_frac) output.cd() - canv_frac.Write() - for _, hist in histos_frac.items(): - hist.Write() - if (is_save_canvas_as_macro_frac): - canv_frac.SaveAs(f"canv_frac_{ipt+1}.C") + if is_save_to_root_file[ObjectToSave.Canvas]: canv_frac.Write() + if is_save_to_root_file[ObjectToSave.Fraction]: + for _, hist in histos_frac.items(): + hist.Write() + if is_save_canvas_as_macro[PlotType.Frac]: canv_frac.SaveAs(f"canv_frac_{ipt+1}.C") - hist_bin_title_cov = hist_bin_title if is_draw_title_cov else "" + hist_bin_title_cov = hist_bin_title if is_draw_title[PlotType.Cov] else "" canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_cov) output.cd() - canv_cov.Write() - histo_cov.Write() - if (is_save_canvas_as_macro_cov): - canv_cov.SaveAs(f"canv_cov_{ipt+1}.C") + if is_save_to_root_file[ObjectToSave.Canvas]: canv_cov.Write() + if is_save_to_root_file[ObjectToSave.CorrelationMatrix]: histo_cov.Write() + if is_save_canvas_as_macro[PlotType.Cov]: canv_cov.SaveAs(f"canv_cov_{ipt+1}.C") else: print(f"Minimization for pT {pt_min}, {pt_max} not successful") + hist_minimisation_status.SetBinContent(ipt + 1, MinimisationStatus.Fail) canv_rawy = ROOT.TCanvas("c_rawy_minimization_error", "Minimization error", 500, 500) canv_eff = ROOT.TCanvas("c_eff_minimization_error", "Minimization error", 500, 500) canv_frac = ROOT.TCanvas("c_frac_minimization_error", "Minimization error", 500, 500) canv_cov = ROOT.TCanvas("c_conv_minimization_error", "Minimization error", 500, 500) + canv_unc = ROOT.TCanvas("c_unc_minimization_error", "Minimization error", 500, 500) canv_combined = ROOT.TCanvas(f"canv_combined_{ipt}", "", 1000, 1000) canv_combined.Divide(2, 2) @@ -309,13 +364,19 @@ def main(config): canv_unc.Print(f"{os.path.join(cfg['output']['directory'], output_name_unc_pdf)}{print_bracket}") output.cd() - hist_corry_prompt.Write() - hist_corry_nonprompt.Write() - hist_covariance_pnp.Write() - hist_covariance_pp.Write() - hist_covariance_npnp.Write() - hist_corrfrac_prompt.Write() - hist_corrfrac_nonprompt.Write() + if is_save_to_root_file[ObjectToSave.CorrectedYield]: + hist_corry_prompt.Write() + hist_corry_nonprompt.Write() + if is_save_to_root_file[ObjectToSave.Covariance]: + hist_covariance_pnp.Write() + hist_covariance_pp.Write() + hist_covariance_npnp.Write() + if is_save_to_root_file[ObjectToSave.CorrectedFraction]: + hist_corrfrac_prompt.Write() + hist_corrfrac_nonprompt.Write() + if is_save_to_root_file[ObjectToSave.MinimisationStatus]: + hist_minimisation_status.Write() + hist_red_chi2.Write() if cfg["central_efficiency"]["computerawfrac"]: hist_frac_raw_prompt.Write() hist_frac_raw_nonprompt.Write() diff --git a/PWGHF/D2H/Macros/config_cutvar_example.json b/PWGHF/D2H/Macros/config_cutvar_example.json index e1b768b807d..f13a2d53d7f 100644 --- a/PWGHF/D2H/Macros/config_cutvar_example.json +++ b/PWGHF/D2H/Macros/config_cutvar_example.json @@ -71,6 +71,18 @@ "cov": false, "unc": false }, + "is_save_to_root_file": { + "canvas": true, + "raw_yield": true, + "uncertainty": true, + "efficiency": true, + "fraction": true, + "corrected_yield": true, + "correlation_matrix": true, + "covariance": true, + "corrected_fraction": true, + "minimisation_status": true + }, "central_efficiency": { "computerawfrac": true, "inputdir": "path/to/central/efficiency", diff --git a/PWGHF/D2H/Macros/cut_variation.py b/PWGHF/D2H/Macros/cut_variation.py index f9b49f15710..6d45ac25607 100644 --- a/PWGHF/D2H/Macros/cut_variation.py +++ b/PWGHF/D2H/Macros/cut_variation.py @@ -11,9 +11,15 @@ import numpy as np # pylint: disable=import-error import ROOT # pylint: disable=import-error +from enum import IntEnum, auto sys.path.insert(0, '..') from style_formatter import set_global_style, set_object_style +class MinimisationStatus(IntEnum): + Undefined = 0 + Success = auto() + MonotonyViolation = auto() + Fail = auto() # pylint: disable=too-many-instance-attributes class CutVarMinimiser: @@ -171,7 +177,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) try: self.m_weights = np.linalg.inv(np.linalg.cholesky(self.m_cov_sets)) except np.linalg.LinAlgError: - return False + return MinimisationStatus.Fail self.m_weights = self.m_weights.T * self.m_weights m_eff_tr = self.m_eff.T @@ -179,7 +185,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) try: self.m_covariance = np.linalg.inv(np.linalg.cholesky(self.m_covariance)) except np.linalg.LinAlgError: - return False + return MinimisationStatus.Fail self.m_covariance = self.m_covariance.T * self.m_covariance self.m_corr_yields = self.m_covariance * (m_eff_tr * self.m_weights) * self.m_rawy @@ -196,9 +202,11 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) m_corr_yields_old = np.copy(self.m_corr_yields) print(f"INFO: number of processed iterations = {iteration+1}\n") + minimisation_status = MinimisationStatus.Success if correlated: m_cov_sets_diag = np.diag(self.m_cov_sets) if not (np.all(m_cov_sets_diag[1:] > m_cov_sets_diag[:-1]) or np.all(m_cov_sets_diag[1:] < m_cov_sets_diag[:-1])): + minimisation_status = MinimisationStatus.MonotonyViolation print("\033[33mWARNING! minimise_system(): the residual vector uncertainties elements are not monotonous. Check the input for stability.\033[0m") print(f"residual vector uncertainties elements = {np.sqrt(m_cov_sets_diag)}\n") @@ -229,7 +237,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) self.unc_frac_prompt[i_set] = unc_fp self.unc_frac_nonprompt[i_set] = unc_fnp - return True + return minimisation_status def get_red_chi2(self): """ From 541b9f76a0593bdaf62f9e0bd43fb9b328b744d7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 19 May 2026 06:51:28 +0200 Subject: [PATCH 222/449] [Common] Do not add configurables when not needed. (#16298) --- Common/TableProducer/propagationServiceV2.cxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Common/TableProducer/propagationServiceV2.cxx b/Common/TableProducer/propagationServiceV2.cxx index da9667f7378..151c39eb2bc 100644 --- a/Common/TableProducer/propagationServiceV2.cxx +++ b/Common/TableProducer/propagationServiceV2.cxx @@ -76,11 +76,6 @@ struct propagationServiceV2 { o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables; o2::common::StandardCCDBLoader ccdbLoader; - // Declarative CCDB path overrides (replace grpmagPath / mVtxPath in StandardCCDBLoaderConfigurables) - // Option names: "ccdb:fGRPMagField" and "ccdb:fMeanVertex" respectively. - o2::framework::ConfigurableCCDBPath grpmagPath; - o2::framework::ConfigurableCCDBPath mVtxPath; - // boilerplate: strangeness builder stuff o2::pwglf::strangenessbuilder::products products; o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; From e497cf0edf4f65f65f9ff21e847bbb42657b3346 Mon Sep 17 00:00:00 2001 From: hfribert Date: Tue, 19 May 2026 09:40:05 +0200 Subject: [PATCH 223/449] [ALICE3] TrackerPID improved plotting and LUT handling (#16287) Co-authored-by: Henrik Fribert --- .../TableProducer/OTF/onTheFlyTrackerPid.cxx | 265 +++++++++++------- 1 file changed, 164 insertions(+), 101 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx index fdb0e72afe2..7fbcc3e234b 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx @@ -87,32 +87,27 @@ static constexpr size_t kMaxValidHitsForTruncation56 = 3; static constexpr size_t kMaxValidHitsForTruncation34 = 2; static constexpr size_t kMaxValidHitsForTruncation12 = 1; -// Constants for LUT binning -// To do: Include in LUT header or similar -static constexpr int kLUTEtaBins = 50; -static constexpr float kLUTEtaMin = -2.5f; -static constexpr float kLUTEtaMax = 2.5f; -static constexpr int kLUTPtBins = 500; -static constexpr float kLUTPtMin = 0.0f; -static constexpr float kLUTPtMax = 10.0f; - class ToTLUT { public: - explicit ToTLUT(int maxLayers, float analysisEtaMinVal = 0.0f, float analysisEtaMaxVal = 1.0f, float analysisPtMinVal = 0.0f, float analysisPtMaxVal = 10.0f) + explicit ToTLUT(int maxLayers, + int etaBins, float etaMin, float etaMax, + int pBins, float pMin, float pMax, + float analysisEtaMinVal = 0.0f, float analysisEtaMaxVal = 1.0f, + float analysisPMinVal = 0.0f, float analysisPMaxVal = 10.0f) : mMaxLayers(maxLayers), mAnalysisEtaMin(analysisEtaMinVal), mAnalysisEtaMax(analysisEtaMaxVal), - mAnalysisPtMin(analysisPtMinVal), - mAnalysisPtMax(analysisPtMaxVal), - mEtaBins(kLUTEtaBins), - mEtaMin(kLUTEtaMin), - mEtaMax(kLUTEtaMax), - mPtBins(kLUTPtBins), - mPtMin(kLUTPtMin), - mPtMax(kLUTPtMax), - mEtaBinWidth((kLUTEtaMax - kLUTEtaMin) / kLUTEtaBins), - mPtBinWidth((kLUTPtMax - kLUTPtMin) / kLUTPtBins) + mAnalysisPMin(analysisPMinVal), + mAnalysisPMax(analysisPMaxVal), + mEtaBins(etaBins), + mEtaMin(etaMin), + mEtaMax(etaMax), + mPBins(pBins), + mPMin(pMin), + mPMax(pMax), + mEtaBinWidth((etaMax - etaMin) / etaBins), + mPBinWidth((pMax - pMin) / pBins) { mPdgToIndexMap.reserve(10); mIndexToPdgMap.reserve(10); @@ -174,7 +169,7 @@ class ToTLUT mPdgToIndexMap[pdg] = currentPdgIdx; mIndexToPdgMap.push_back(pdg); - size_t totalSize = (currentPdgIdx + 1) * mMaxLayers * mEtaBins * mPtBins; + size_t totalSize = (currentPdgIdx + 1) * mMaxLayers * mEtaBins * mPBins; if (mLUTHistogramFlat.size() < totalSize) { mLUTHistogramFlat.resize(totalSize, nullptr); } @@ -193,28 +188,30 @@ class ToTLUT continue; } - for (int ptBin = 0; ptBin < mPtBins; ++ptBin) { - float ptMinBin = mPtMin + ptBin * mPtBinWidth; - float ptMaxBin = ptMinBin + mPtBinWidth; - float ptCenter = (ptMinBin + ptMaxBin) / 2.0f; + for (int pBin = 0; pBin < mPBins; ++pBin) { + float pMinBin = mPMin + pBin * mPBinWidth; + float pMaxBin = pMinBin + mPBinWidth; + float pCenter = (pMinBin + pMaxBin) / 2.0f; - if (ptCenter < mAnalysisPtMin || ptCenter >= mAnalysisPtMax) { + if (pCenter < mAnalysisPMin || pCenter >= mAnalysisPMax) { continue; } - TString histName = Form("tot_%d_barrel%d_eta%.2f-%.2f_pt%.2f-%.2f", pdg, layer, etaMinBin, etaMaxBin, ptMinBin, ptMaxBin); + TString histName = Form("tot_%d_barrel%d_eta%.2f-%.2f_p%.2f-%.2f", pdg, layer, etaMinBin, etaMaxBin, pMinBin, pMaxBin); TH1F* histFromFile = dynamic_cast(f->Get(histName)); if (histFromFile) { TH1F* clonedHist = static_cast(histFromFile->Clone()); clonedHist->SetDirectory(nullptr); - size_t flatIdx = getFlatIndex(currentPdgIdx, layer, etaBin, ptBin); + size_t flatIdx = getFlatIndex(currentPdgIdx, layer, etaBin, pBin); mLUTHistogramFlat[flatIdx] = clonedHist; } else { - size_t flatIdx = getFlatIndex(currentPdgIdx, layer, etaBin, ptBin); + size_t flatIdx = getFlatIndex(currentPdgIdx, layer, etaBin, pBin); mLUTHistogramFlat[flatIdx] = nullptr; - success = false; + if (layer >= kMinLayerForTruncation) { + success = false; + } } } } @@ -225,14 +222,14 @@ class ToTLUT return success; } - TH1F* getHistogramForSampling(int pdgIdx, int layer, int etaBin, int ptBin) const + TH1F* getHistogramForSampling(int pdgIdx, int layer, int etaBin, int pBin) const { if (pdgIdx < 0 || static_cast(pdgIdx) >= getNumPdgTypes() || layer < 0 || layer >= mMaxLayers || - etaBin < 0 || etaBin >= mEtaBins || ptBin < 0 || ptBin >= mPtBins) { + etaBin < 0 || etaBin >= mEtaBins || pBin < 0 || pBin >= mPBins) { return nullptr; } - size_t flatIdx = getFlatIndex(pdgIdx, layer, etaBin, ptBin); + size_t flatIdx = getFlatIndex(pdgIdx, layer, etaBin, pBin); return (flatIdx < mLUTHistogramFlat.size()) ? mLUTHistogramFlat[flatIdx] : nullptr; } @@ -251,15 +248,15 @@ class ToTLUT return std::min(static_cast((clampedEta - mEtaMin) / mEtaBinWidth), mEtaBins - 1); } - inline int getPtBin(float pt) const + inline int getPBin(float p) const { - const float clampedPt = std::max(mPtMin, std::min(pt, mPtMax - 1e-6f)); - return std::min(static_cast((clampedPt - mPtMin) / mPtBinWidth), mPtBins - 1); + const float clampedP = std::max(mPMin, std::min(p, mPMax - 1e-6f)); + return std::min(static_cast((clampedP - mPMin) / mPBinWidth), mPBins - 1); } - inline size_t getFlatIndex(int pdgIdx, int layer, int etaBin, int ptBin) const + inline size_t getFlatIndex(int pdgIdx, int layer, int etaBin, int pBin) const { - return ((pdgIdx * mMaxLayers + layer) * mEtaBins + etaBin) * mPtBins + ptBin; + return ((pdgIdx * mMaxLayers + layer) * mEtaBins + etaBin) * mPBins + pBin; } size_t getNumPdgTypes() const @@ -275,17 +272,17 @@ class ToTLUT int mMaxLayers; float mAnalysisEtaMin; float mAnalysisEtaMax; - float mAnalysisPtMin; - float mAnalysisPtMax; + float mAnalysisPMin; + float mAnalysisPMax; int mEtaBins; float mEtaMin; float mEtaMax; - int mPtBins; - float mPtMin; - float mPtMax; + int mPBins; + float mPMin; + float mPMax; float mEtaBinWidth; - float mPtBinWidth; + float mPBinWidth; private: o2::ccdb::BasicCCDBManager* mCcdbManager = nullptr; @@ -295,6 +292,8 @@ static constexpr int kNumHypothesisParticles = 9; std::array, kNumHypothesisParticles>, kNumHypothesisParticles> h2dBarrelNsigmaTrue; std::array, kNumHypothesisParticles> h2dHitsPerTrackVsP; std::array, kNumHypothesisParticles> h2dToTvsPperParticle; +std::array, kNumHypothesisParticles> h2dHitsPerTrackVsPLin; +std::array, kNumHypothesisParticles> h2dToTvsPperParticleLin; struct OnTheFlyTrackerPid { @@ -393,22 +392,42 @@ struct OnTheFlyTrackerPid { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Configurable lutTotEl{"lutTotEl", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_11", "ToT LUT for electrons"}; - Configurable lutTotMu{"lutTotMu", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_13", "ToT LUT for muons"}; - Configurable lutTotPi{"lutTotPi", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_211", "ToT LUT for pions"}; - Configurable lutTotKa{"lutTotKa", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_321", "ToT LUT for kaons"}; - Configurable lutTotPr{"lutTotPr", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_2212", "ToT LUT for protons"}; - Configurable lutTotDe{"lutTotDe", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_1000010020", "ToT LUT for deuteron"}; - Configurable lutTotTr{"lutTotTr", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_1000010030", "ToT LUT for triton"}; - Configurable lutTotHe{"lutTotHe", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_1000020030", "ToT LUT for helium-3"}; - Configurable lutTotAl{"lutTotAl", "ccdb:Users/h/hfribert/ToT_LUTs/PDG_1000020040", "ToT LUT for alphas"}; + Configurable lutTotEl{"lutTotEl", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_11", "ToT LUT for electrons"}; + Configurable lutTotMu{"lutTotMu", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_13", "ToT LUT for muons"}; + Configurable lutTotPi{"lutTotPi", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_211", "ToT LUT for pions"}; + Configurable lutTotKa{"lutTotKa", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_321", "ToT LUT for kaons"}; + Configurable lutTotPr{"lutTotPr", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_2212", "ToT LUT for protons"}; + Configurable lutTotDe{"lutTotDe", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_1000010020", "ToT LUT for deuteron"}; + Configurable lutTotTr{"lutTotTr", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_1000010030", "ToT LUT for triton"}; + Configurable lutTotHe{"lutTotHe", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_1000020030", "ToT LUT for helium-3"}; + Configurable lutTotAl{"lutTotAl", "ccdb:Users/h/hfribert/ToT_LUTs_ALMIRA/Scale1/PDG_1000020040", "ToT LUT for alphas"}; Configurable maxBarrelLayers{"maxBarrelLayers", 11, "Maximum number of barrel layers"}; Configurable numLogBins{"numLogBins", 200, "Number of logarithmic momentum bins"}; Configurable analysisEtaMin{"analysisEtaMin", 0.0f, "Minimum |eta| for LUT loading optimization"}; Configurable analysisEtaMax{"analysisEtaMax", 1.0f, "Maximum |eta| for LUT loading optimization"}; - Configurable analysisPtMin{"analysisPtMin", 0.0f, "Minimum pT (GeV/c) for LUT loading optimization"}; - Configurable analysisPtMax{"analysisPtMax", 10.0f, "Maximum pT (GeV/c) for LUT loading optimization"}; + Configurable analysisPMin{"analysisPMin", 0.0f, "Minimum |p| (GeV/c) for LUT loading optimization"}; + Configurable analysisPMax{"analysisPMax", 10.0f, "Maximum |p| (GeV/c) for LUT loading optimization"}; + + // LUT binning (has to match LUTs) + Configurable lutEtaBins{"lutEtaBins", 50, "Number of eta bins in the LUT"}; + Configurable lutEtaMin{"lutEtaMin", -2.5f, "Minimum eta in the LUT"}; + Configurable lutEtaMax{"lutEtaMax", 2.5f, "Maximum eta in the LUT"}; + Configurable lutPBins{"lutPBins", 500, "Number of momentum bins in the LUT"}; + Configurable lutPMin{"lutPMin", 0.0f, "Minimum momentum in the LUT (GeV/c)"}; + Configurable lutPMax{"lutPMax", 10.0f, "Maximum momentum in the LUT (GeV/c)"}; + + // ToT histogram axis + Configurable totHistBins{"totHistBins", 600, "Number of bins on the ToT axis"}; + Configurable totHistMin{"totHistMin", 0.0f, "Minimum of the ToT axis (#mus/10#mum)"}; + Configurable totHistMax{"totHistMax", 10.0f, "Maximum of the ToT axis (#mus/10#mum)"}; + + // Momentum axis binning choice + Configurable enableLogPBins{"enableLogPBins", true, "Enable logarithmic momentum binning for ToT vs p histograms"}; + Configurable enableLinearPBins{"enableLinearPBins", false, "Enable linear momentum binning for ToT vs p histograms"}; + Configurable numLinearBins{"numLinearBins", 500, "Number of linear momentum bins"}; + Configurable linearPMin{"linearPMin", 0.0f, "Minimum momentum for linear-binned histograms (GeV/c)"}; + Configurable linearPMax{"linearPMax", 10.0f, "Maximum momentum for linear-binned histograms (GeV/c)"}; std::vector mLogBins; @@ -442,7 +461,11 @@ struct OnTheFlyTrackerPid { << "). Please adjust maxBarrelLayers."; } - mToTLUT = std::make_unique(maxBarrelLayers.value, analysisEtaMin.value, analysisEtaMax.value, analysisPtMin.value, analysisPtMax.value); + mToTLUT = std::make_unique(maxBarrelLayers.value, + lutEtaBins.value, lutEtaMin.value, lutEtaMax.value, + lutPBins.value, lutPMin.value, lutPMax.value, + analysisEtaMin.value, analysisEtaMax.value, + analysisPMin.value, analysisPMax.value); mToTLUT->setCcdbManager(ccdb.operator->()); @@ -472,17 +495,30 @@ struct OnTheFlyTrackerPid { mLogBins.push_back(std::pow(10, logMin + i * dLog)); } - const AxisSpec axisMomentum{mLogBins, "#it{p/z} (GeV/#it{c})"}; - const AxisSpec axisToT{600, 0., 300., "ToT (#mus/10#mum)"}; + const AxisSpec axisToT{totHistBins.value, static_cast(totHistMin.value), static_cast(totHistMax.value), "ToT (#mus/10#mum)"}; const AxisSpec axisNsigma{200, -10., 10., "N#sigma"}; const AxisSpec axisLayer{maxBarrelLayers.value, -0.5, static_cast(maxBarrelLayers.value) - 0.5, "Layer"}; const AxisSpec axisHitsPerTrack{maxBarrelLayers.value + 1, -0.5, static_cast(maxBarrelLayers.value) + 0.5, "# Hits per track"}; - histos.add("hToTvsP", "ToT vs #it{p/z}; #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {axisMomentum, axisToT}); - histos.add("hToTvsPt", "ToT vs #it{p}; #it{p} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {mLogBins, axisToT}); + if (!enableLogPBins.value && !enableLinearPBins.value) { + LOG(fatal) << "At least one of enableLogPBins or enableLinearPBins must be true."; + } + histos.add("hHitLayers", "Number of hits on each detector layer;Layer;Counts", kTH1F, {axisLayer}); histos.add("hHitMultiplicity", "Hit multiplicity along the track; # Hits per track;Counts", kTH1F, {axisHitsPerTrack}); + if (enableLogPBins.value) { + const AxisSpec axisMomentumLog{mLogBins, "#it{p/z} (GeV/#it{c})"}; + histos.add("hToTvsP", "ToT vs #it{p/z}; #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {axisMomentumLog, axisToT}); + histos.add("hToTvsMom", "ToT vs #it{p}; #it{p} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {mLogBins, axisToT}); + } + + if (enableLinearPBins.value) { + const AxisSpec axisMomentumLin{numLinearBins.value, static_cast(linearPMin.value), static_cast(linearPMax.value), "#it{p/z} (GeV/#it{c})"}; + histos.add("hToTvsPLin", "ToT vs #it{p/z} (linear); #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {axisMomentumLin, axisToT}); + histos.add("hToTvsMomLin", "ToT vs #it{p} (linear); #it{p} (GeV/#it{c}); ToT (#mus/10#mum)", kTH2F, {axisMomentumLin, axisToT}); + } + std::vector> particleInfo = { {11, "Elec"}, {13, "Muon"}, {211, "Pion"}, {321, "Kaon"}, {2212, "Prot"}, {1000010020, "Deut"}, {1000010030, "Trit"}, {1000020030, "He3"}, {1000020040, "Al"}}; @@ -508,39 +544,55 @@ struct OnTheFlyTrackerPid { else if (trueName == "Al") trueNamePretty = "#it{^{4}He}"; - std::string hitsVsPName = "HitsPerTrack/hHitsPerTrackVsP_" + trueName; - std::string hitsVsPTitle = "N_hits vs #it{p/z} for " + trueNamePretty + "; #it{p/z} (GeV/#it{c}); N_hits"; - h2dHitsPerTrackVsP[iTrue] = histos.add(hitsVsPName.c_str(), hitsVsPTitle.c_str(), kTH2F, {axisMomentum, axisHitsPerTrack}); - - std::string totVsPName = "ToTvsP/hToTvsP_" + trueName; - std::string totVsPTitle = "ToT vs #it{p/z} for " + trueNamePretty + "; #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)"; - h2dToTvsPperParticle[iTrue] = histos.add(totVsPName.c_str(), totVsPTitle.c_str(), kTH2F, {axisMomentum, axisToT}); - - for (size_t iHyp = 0; iHyp < particleInfo.size(); ++iHyp) { - std::string hypName = particleInfo[iHyp].second; - std::string hypNamePretty = hypName; // Fallback - if (hypName == "Elec") - hypNamePretty = "#it{e}"; - else if (hypName == "Muon") - hypNamePretty = "#it{#mu}"; - else if (hypName == "Pion") - hypNamePretty = "#it{#pi}"; - else if (hypName == "Kaon") - hypNamePretty = "#it{K}"; - else if (hypName == "Prot") - hypNamePretty = "#it{p}"; - else if (hypName == "Deut") - hypNamePretty = "#it{d}"; - else if (hypName == "Trit") - hypNamePretty = "#it{t}"; - else if (hypName == "He3") - hypNamePretty = "#it{^{3}He}"; - else if (hypName == "Al") - hypNamePretty = "#it{^{4}He}"; - - std::string histName = "NSigma/BarrelNsigmaTrue" + trueName + "Vs" + hypName + "Hypothesis"; - std::string histTitle = "Nsigma (True " + trueNamePretty + " vs Hyp " + hypNamePretty + "); #it{p/z} (GeV/#it{c}); N#sigma"; - h2dBarrelNsigmaTrue[iTrue][iHyp] = histos.add(histName.c_str(), histTitle.c_str(), kTH2F, {axisMomentum, axisNsigma}); + if (enableLogPBins.value) { + const AxisSpec axisMomentumLog{mLogBins, "#it{p/z} (GeV/#it{c})"}; + + std::string hitsVsPName = "HitsPerTrack/hHitsPerTrackVsP_" + trueName; + std::string hitsVsPTitle = "N_hits vs #it{p/z} for " + trueNamePretty + "; #it{p/z} (GeV/#it{c}); N_hits"; + h2dHitsPerTrackVsP[iTrue] = histos.add(hitsVsPName.c_str(), hitsVsPTitle.c_str(), kTH2F, {axisMomentumLog, axisHitsPerTrack}); + + std::string totVsPName = "ToTvsP/hToTvsP_" + trueName; + std::string totVsPTitle = "ToT vs #it{p/z} for " + trueNamePretty + "; #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)"; + h2dToTvsPperParticle[iTrue] = histos.add(totVsPName.c_str(), totVsPTitle.c_str(), kTH2F, {axisMomentumLog, axisToT}); + + for (size_t iHyp = 0; iHyp < particleInfo.size(); ++iHyp) { + std::string hypName = particleInfo[iHyp].second; + std::string hypNamePretty = hypName; // Fallback + if (hypName == "Elec") + hypNamePretty = "#it{e}"; + else if (hypName == "Muon") + hypNamePretty = "#it{#mu}"; + else if (hypName == "Pion") + hypNamePretty = "#it{#pi}"; + else if (hypName == "Kaon") + hypNamePretty = "#it{K}"; + else if (hypName == "Prot") + hypNamePretty = "#it{p}"; + else if (hypName == "Deut") + hypNamePretty = "#it{d}"; + else if (hypName == "Trit") + hypNamePretty = "#it{t}"; + else if (hypName == "He3") + hypNamePretty = "#it{^{3}He}"; + else if (hypName == "Al") + hypNamePretty = "#it{^{4}He}"; + + std::string histName = "NSigma/BarrelNsigmaTrue" + trueName + "Vs" + hypName + "Hypothesis"; + std::string histTitle = "Nsigma (True " + trueNamePretty + " vs Hyp " + hypNamePretty + "); #it{p/z} (GeV/#it{c}); N#sigma"; + h2dBarrelNsigmaTrue[iTrue][iHyp] = histos.add(histName.c_str(), histTitle.c_str(), kTH2F, {axisMomentumLog, axisNsigma}); + } + } + + if (enableLinearPBins.value) { + const AxisSpec axisMomentumLin{numLinearBins.value, static_cast(linearPMin.value), static_cast(linearPMax.value), "#it{p/z} (GeV/#it{c})"}; + + std::string hitsVsPLinName = "HitsPerTrackLin/hHitsPerTrackVsPLin_" + trueName; + std::string hitsVsPLinTitle = "N_hits vs #it{p/z} for " + trueNamePretty + " (linear); #it{p/z} (GeV/#it{c}); N_hits"; + h2dHitsPerTrackVsPLin[iTrue] = histos.add(hitsVsPLinName.c_str(), hitsVsPLinTitle.c_str(), kTH2F, {axisMomentumLin, axisHitsPerTrack}); + + std::string totVsPLinName = "ToTvsPLin/hToTvsPLin_" + trueName; + std::string totVsPLinTitle = "ToT vs #it{p/z} for " + trueNamePretty + " (linear); #it{p/z} (GeV/#it{c}); ToT (#mus/10#mum)"; + h2dToTvsPperParticleLin[iTrue] = histos.add(totVsPLinName.c_str(), totVsPLinTitle.c_str(), kTH2F, {axisMomentumLin, axisToT}); } } } @@ -581,7 +633,6 @@ struct OnTheFlyTrackerPid { continue; } - const float pt = mcParticle.pt(); const float p = mcParticle.p(); const float eta = mcParticle.eta(); const int truePdgCode = std::abs(mcParticle.pdgCode()); @@ -602,7 +653,7 @@ struct OnTheFlyTrackerPid { continue; } - const int binnedPt = mToTLUT->getPtBin(pt); + const int binnedP = mToTLUT->getPBin(p); const int binnedEta = mToTLUT->getEtaBin(std::abs(eta)); uint16_t hitMap = 0; @@ -629,13 +680,18 @@ struct OnTheFlyTrackerPid { } histos.fill(HIST("hHitMultiplicity"), nHitLayers); - h2dHitsPerTrackVsP[truePdgIdx]->Fill(rigidity, nHitLayers); + if (enableLogPBins.value) { + h2dHitsPerTrackVsP[truePdgIdx]->Fill(rigidity, nHitLayers); + } + if (enableLinearPBins.value) { + h2dHitsPerTrackVsPLin[truePdgIdx]->Fill(rigidity, nHitLayers); + } std::vector validToTs; for (int layer = kMinLayerForTruncation; layer < maxBarrelLayers.value; ++layer) { if ((hitMap >> layer) & 0x1) { - TH1F* totHist = mToTLUT->getHistogramForSampling(truePdgIdx, layer, binnedEta, binnedPt); + TH1F* totHist = mToTLUT->getHistogramForSampling(truePdgIdx, layer, binnedEta, binnedP); if (totHist && totHist->GetEntries() > 1) { float sampledToT = totHist->GetRandom(); @@ -665,14 +721,21 @@ struct OnTheFlyTrackerPid { } truncatedMeanToT = sum / static_cast(nUse); - histos.fill(HIST("hToTvsPt"), p, truncatedMeanToT); - histos.fill(HIST("hToTvsP"), rigidity, truncatedMeanToT); - h2dToTvsPperParticle[truePdgIdx]->Fill(rigidity, truncatedMeanToT); + if (enableLogPBins.value) { + histos.fill(HIST("hToTvsMom"), p, truncatedMeanToT); + histos.fill(HIST("hToTvsP"), rigidity, truncatedMeanToT); + h2dToTvsPperParticle[truePdgIdx]->Fill(rigidity, truncatedMeanToT); + } + if (enableLinearPBins.value) { + histos.fill(HIST("hToTvsMomLin"), p, truncatedMeanToT); + histos.fill(HIST("hToTvsPLin"), rigidity, truncatedMeanToT); + h2dToTvsPperParticleLin[truePdgIdx]->Fill(rigidity, truncatedMeanToT); + } } nSigmaValues.fill(999.f); - if (truncatedMeanToT > 0) { + if (enableLogPBins.value && truncatedMeanToT > 0) { for (size_t iHyp = 0; iHyp < mHypothesisPdgCodes.size(); ++iHyp) { int hypPdgCode = mHypothesisPdgCodes[iHyp]; int hypPdgIdx = mToTLUT->getPdgIndex(hypPdgCode); From 56441b28644877e77550b2c57be2d86d3090e4ad Mon Sep 17 00:00:00 2001 From: glegras <71757105+glegras@users.noreply.github.com> Date: Tue, 19 May 2026 10:39:03 +0200 Subject: [PATCH 224/449] [PWGDQ] Add track-to-collision association in dalitzSelection.cxx (#16259) --- PWGDQ/Tasks/DalitzSelection.cxx | 260 ++++++++++++++++++++++++-------- 1 file changed, 196 insertions(+), 64 deletions(-) diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index 70eb8415d27..317015a044f 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -24,10 +24,10 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" #include #include @@ -52,6 +52,7 @@ #include #include #include +#include #include using namespace o2; @@ -60,20 +61,23 @@ using namespace o2::framework::expressions; using namespace o2::aod; using namespace o2::soa; -using MyEvents = soa::Join; +// using MyEvents = soa::Join +using MyEventsWithCent = soa::Join; -using MyBarrelTracks = soa::Join; -constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision; -constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID; +// constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision; +constexpr static uint32_t EventFillMapWithCent = VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; +constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackPID; struct DalitzSelection { Produces dalitzbits; Preslice perCollision = aod::track::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; // Configurables // cuts @@ -102,6 +106,7 @@ struct DalitzSelection { struct : ConfigurableGroup { Configurable fConfigEnableLikeSign{"cfgEnableLikeSign", false, "Whether or not also add like-sign pairs (for studying combinatorial background which might contain misID or non-primary electrons)"}; Configurable fQA{"cfgQA", true, "QA histograms"}; + Configurable fRemoveDoubleCounting{"cfgRemoveDoubleCounting", true, "If a track/pair is selected for several collisions, we still count it only once"}; // Configurables for TPC post-calibration maps Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; @@ -126,6 +131,11 @@ struct DalitzSelection { std::map fDalitzmap; // whether it is selected as dalitz decay daughter with symmetric or tag cut std::map fDalitzmapProbe; // whether it is selected as dalitz decay daughter with probe cut + // maps to remove ambiguities + std::map fDalitzmapAmbiguity; + std::map fDalitzmapProbeAmbiguity; + std::map, uint8_t> fAmbiguousPairs; + AnalysisCompositeCut* fEventCut; std::vector fTrackCuts; std::vector fTrackCutsProbe; @@ -295,13 +305,22 @@ struct DalitzSelection { fOutputList.setObject(fHistMan->GetMainHistogramList()); } - template - void runTrackSelection(TTracks const& tracksBarrel) + template + void runTrackSelection(TTracks const& tracksBarrel, TEvent const& collision) { - for (const auto& track : tracksBarrel) { + for (const auto& track1 : tracksBarrel) { uint8_t filterMap = uint8_t(0); uint8_t filterMapProbe = uint8_t(0); - VarManager::FillTrack(track); + int fullTrackIdx = 0; + if constexpr (isReassoc) { + auto const& fullTrack = track1.template track_as(); + VarManager::FillTrack(fullTrack); + VarManager::FillTrackCollision(fullTrack, collision); + fullTrackIdx = fullTrack.globalIndex(); + } else { + VarManager::FillTrack(track1); + fullTrackIdx = track1.globalIndex(); + } int i = 0; for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { if ((*cut).IsSelected(VarManager::fgValues)) { @@ -317,35 +336,63 @@ struct DalitzSelection { } } if (filterMap) { - fTrackmap[track.globalIndex()] = filterMap; + fTrackmap[fullTrackIdx] = filterMap; } if (filterMapProbe) { - fTrackmapProbe[track.globalIndex()] = filterMapProbe; + fTrackmapProbe[fullTrackIdx] = filterMapProbe; } } // end loop over tracks } - template - void runDalitzPairing(TTracks const& tracks1, TTracks const& tracks2) + template + void runDalitzPairing(TTracks const& tracks1, TTracks const& tracks2, TEvent collision) { + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + // keep track of selections from previous events to check if the track was already selected or not + fDalitzmapAmbiguity = fDalitzmap; + fDalitzmapProbeAmbiguity = fDalitzmapProbe; + } + for (const auto& [track1, track2] : o2::soa::combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (track1.globalIndex() == track2.globalIndex()) { + + int trackIdx1; + int trackIdx2; + bool isLikeSign; + if constexpr (isReassoc) { + auto const& fullTrack1 = track1.template track_as(); + auto const& fullTrack2 = track2.template track_as(); + trackIdx1 = fullTrack1.globalIndex(); + trackIdx2 = fullTrack2.globalIndex(); + isLikeSign = (fullTrack1.sign() * fullTrack2.sign() > 0); + } else { + trackIdx1 = track1.globalIndex(); + trackIdx2 = track2.globalIndex(); + isLikeSign = (track1.sign() * track2.sign() > 0); + } + + if (trackIdx1 == trackIdx2) { continue; } - if (!fIsTagAndProbe && track1.globalIndex() >= track2.globalIndex()) { + if (!fIsTagAndProbe && trackIdx1 >= trackIdx2) { continue; } - if (!fConfigOptions.fConfigEnableLikeSign && (track1.sign() * track2.sign() > 0)) { + if (!fConfigOptions.fConfigEnableLikeSign && isLikeSign) { continue; } - uint8_t twoTracksFilterMap = fTrackmap[track1.globalIndex()] & (fIsTagAndProbe ? fTrackmapProbe[track2.globalIndex()] : fTrackmap[track2.globalIndex()]); + uint8_t twoTracksFilterMap = fTrackmap[trackIdx1] & (fIsTagAndProbe ? fTrackmapProbe[trackIdx2] : fTrackmap[trackIdx2]); if (!twoTracksFilterMap) { continue; } // pairing - VarManager::FillPair(track1, track2); + if constexpr (isReassoc) { + auto const& fullTrack1 = track1.template track_as(); + auto const& fullTrack2 = track2.template track_as(); + VarManager::FillPair(fullTrack1, fullTrack2); + } else { + VarManager::FillPair(track1, track2); + } // Fill pair selection map and fill pair histogram int icut = 0; @@ -355,21 +402,35 @@ struct DalitzSelection { continue; } if ((*pairCut).IsSelected(VarManager::fgValues)) { - if (track1.sign() * track2.sign() < 0) { - fDalitzmap[track1.globalIndex()] |= (uint8_t(1) << icut); + bool isPairAlreadySelected = false; + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + // if we remove double counting and the pair is already selected, we don't fill the histograms + std::pair iPair(trackIdx1, trackIdx2); + if (fAmbiguousPairs.find(iPair) != fAmbiguousPairs.end()) { + if (fAmbiguousPairs[iPair] & (static_cast(1) << icut)) { // if this pair is already stored with this cut + isPairAlreadySelected = true; + } else { + fAmbiguousPairs[iPair] |= static_cast(1) << icut; + } + } else { + fAmbiguousPairs[iPair] = static_cast(1) << icut; + } + } + if (!isLikeSign) { + fDalitzmap[trackIdx1] |= (uint8_t(1) << icut); if (fIsTagAndProbe) { - fDalitzmapProbe[track2.globalIndex()] |= (uint8_t(1) << icut); - if (fConfigOptions.fQA) { + fDalitzmapProbe[trackIdx2] |= (uint8_t(1) << icut); + if (fConfigOptions.fQA && !isPairAlreadySelected) { fHistMan->FillHistClass(Form("Pair_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } } else { - fDalitzmap[track2.globalIndex()] |= (uint8_t(1) << icut); - if (fConfigOptions.fQA) { + fDalitzmap[trackIdx2] |= (uint8_t(1) << icut); + if (fConfigOptions.fQA && !isPairAlreadySelected) { fHistMan->FillHistClass(Form("Pair_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } } } else { - if (fConfigOptions.fQA) { + if (fConfigOptions.fQA && !isPairAlreadySelected) { fHistMan->FillHistClass(fIsTagAndProbe ? Form("PairLS_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()) : Form("PairLS_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } } // end if like-sign @@ -380,12 +441,37 @@ struct DalitzSelection { // Fill Hists if (fConfigOptions.fQA) { for (const auto& track : tracks1) { - uint8_t filterMap = fDalitzmap[track.globalIndex()]; - uint8_t filterMapProbe = fDalitzmapProbe[track.globalIndex()]; - if (!filterMap && !filterMapProbe) { - continue; + uint8_t filterMap; + uint8_t filterMapProbe; + if constexpr (isReassoc) { + auto const& fullTrack = track.template track_as(); + filterMap = fDalitzmap[fullTrack.globalIndex()]; + filterMapProbe = fDalitzmapProbe[fullTrack.globalIndex()]; + if (fConfigOptions.fRemoveDoubleCounting) { + // we remove track selections which were already selected before + uint8_t previousFilterMap = fDalitzmapAmbiguity[fullTrack.globalIndex()]; + uint8_t previousFilterMapProbe = fDalitzmapProbeAmbiguity[fullTrack.globalIndex()]; + filterMap &= ~previousFilterMap; + filterMapProbe &= ~previousFilterMapProbe; + } + + if (!filterMap && !filterMapProbe) { + continue; + } + + VarManager::FillTrack(fullTrack); + // The caveat here is that we only fill the DCA to the first selected collision + VarManager::FillTrackCollision(fullTrack, collision); + } else { + filterMap = fDalitzmap[track.globalIndex()]; + filterMapProbe = fDalitzmapProbe[track.globalIndex()]; + + if (!filterMap && !filterMapProbe) { + continue; + } + + VarManager::FillTrack(track); } - VarManager::FillTrack(track); int icut = 0; auto trackCut = fTrackCuts.begin(); @@ -403,7 +489,41 @@ struct DalitzSelection { } } - void processFullTracks(MyEvents const& collisions, aod::BCsWithTimestamps const&, soa::Filtered const& filteredTracks, MyBarrelTracks const& tracks) + void initNewRun(int64_t timestamp) + { + + VarManager::ResetValues(0, VarManager::kNRunWiseVariables); + + // We setup the magnetic field, because the conversion rejection cut might depend on it + float magField = 0.; + if (fConfigOptions.fUseRemoteField.value) { + grpmag = fCCDB->getForTimeStamp(fConfigOptions.grpmagPath, timestamp); + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", timestamp); + } + } else { + magField = fConfigOptions.fConfigMagField.value; + } + LOGF(info, "setting mag field to %f", magField); + if (magField == 0.) { + LOGF(fatal, "magnetic field not set correctly, please check"); + } + VarManager::SetMagneticField(magField); + + if (fConfigOptions.fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigOptions.fConfigCcdbPathTPC.value, timestamp); + VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + } + } + + void processFullTracks(MyEventsWithCent const& collisions, aod::BCsWithTimestamps const&, soa::Filtered const& filteredTracks, MyBarrelTracks const& tracks) { const int pairType = VarManager::kDecayToEE; fDalitzmap.clear(); @@ -413,7 +533,7 @@ struct DalitzSelection { fTrackmap.clear(); fTrackmapProbe.clear(); VarManager::ResetValues(VarManager::kNRunWiseVariables, VarManager::kNBarrelTrackVariables); - VarManager::FillEvent(collision); + VarManager::FillEvent(collision); bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); if (isEventSelected) { @@ -423,41 +543,52 @@ struct DalitzSelection { auto bc = collision.template bc_as(); if (fCurrentRun != bc.runNumber()) { - VarManager::ResetValues(0, VarManager::kNRunWiseVariables); - - // We setup the magnetic field, because the conversion rejection cut might depend on it - float magField = 0.; - if (fConfigOptions.fUseRemoteField.value) { - grpmag = fCCDB->getForTimeStamp(fConfigOptions.grpmagPath, bc.timestamp()); - if (grpmag != nullptr) { - magField = grpmag->getNominalL3Field(); - } else { - LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bc.timestamp()); - } - } else { - magField = fConfigOptions.fConfigMagField.value; - } - LOGF(info, "setting mag field to %f", magField); - if (magField == 0.) { - LOGF(fatal, "magnetic field not set correctly, please check"); - } - VarManager::SetMagneticField(magField); - - if (fConfigOptions.fConfigComputeTPCpostCalib) { - auto calibList = fCCDB->getForTimeStamp(fConfigOptions.fConfigCcdbPathTPC.value, bc.timestamp()); - VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); - } + initNewRun(bc.timestamp()); fCurrentRun = bc.runNumber(); } auto groupedFilteredTracks = filteredTracks.sliceBy(perCollision, collision.globalIndex()); - runTrackSelection(groupedFilteredTracks); - runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks); + runTrackSelection(groupedFilteredTracks, nullptr); + runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks, nullptr); + } + } + + for (const auto& track : tracks) { // Fill dalitz bits + dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + } + } + + void processFullTracksWithAssoc(MyEventsWithCent const& collisions, aod::BCsWithTimestamps const&, MyBarrelTracks const& tracks, TrackAssoc const& trackAssocs) + { + + const int pairType = VarManager::kDecayToEE; + fDalitzmap.clear(); + fDalitzmapProbe.clear(); + fDalitzmapAmbiguity.clear(); + fDalitzmapProbeAmbiguity.clear(); + fAmbiguousPairs.clear(); + + for (const auto& collision : collisions) { + fTrackmap.clear(); + fTrackmapProbe.clear(); + VarManager::ResetValues(VarManager::kNRunWiseVariables, VarManager::kNBarrelTrackVariables); + VarManager::FillEvent(collision); + bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); + + if (isEventSelected) { + + reinterpret_cast(fStatsList->At(0))->Fill(0); + + auto bc = collision.template bc_as(); + + if (fCurrentRun != bc.runNumber()) { + initNewRun(bc.timestamp()); + fCurrentRun = bc.runNumber(); + } + + auto groupedTracksAssoc = trackAssocs.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + runTrackSelection(groupedTracksAssoc, collision); + runDalitzPairing(groupedTracksAssoc, groupedTracksAssoc, collision); } } @@ -466,10 +597,11 @@ struct DalitzSelection { } } - void processDummy(MyEvents const&) + void processDummy(MyEventsWithCent const&) { } + PROCESS_SWITCH(DalitzSelection, processFullTracksWithAssoc, "Run Dalitz selection on AO2D tables with reassociation", false); PROCESS_SWITCH(DalitzSelection, processFullTracks, "Run Dalitz selection on AO2D tables", false); PROCESS_SWITCH(DalitzSelection, processDummy, "Do nothing", false); }; From 7ee5bb3532f6792d083cd12540fa26797c2b6bb4 Mon Sep 17 00:00:00 2001 From: Cristian-Moscatelli Date: Tue, 19 May 2026 11:17:41 +0200 Subject: [PATCH 225/449] [PWGLF] Add new task: PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents (#16128) Co-authored-by: Cristian Moscatelli Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Nuspex/CMakeLists.txt | 5 + .../Nuspex/deuteronInTriggeredEvents.cxx | 1105 +++++++++++++++++ 2 files changed, 1110 insertions(+) create mode 100644 PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index 978ec1613d1..1d3c88d03fa 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -44,6 +44,11 @@ o2physics_add_dpl_workflow(nuclei-spectra PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(deuteron-in-triggered-events + SOURCES deuteronInTriggeredEvents.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2::DetectorsBase O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(spectra-derived SOURCES spectraDerivedMaker.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx new file mode 100644 index 00000000000..8749d248835 --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx @@ -0,0 +1,1105 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file deuteronInTriggeredEvents.cxx +/// +/// \brief (Anti-)nuclei spectra analysis task in jet-triggered events +/// \author Cristian Moscatelli (cristian.moscatelli@cern.ch) +/// +/// Based on PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +/// \since 05/2026 +// +// ================ +// Executable + dependencies: +// +// data (run3): +// o2-analysis-lf-deuteron-in-triggered-events, o2-analysis-event-selection-service +// o2-analysis-propagationservice, o2-analysis-trackselection, o2-analysis-track-extra-v002-converter +// o2-analysis-pid-tof-merge, o2-analysis-pid-tpc-service, o2-analysis-ft0-corrected-table +// +// mc: +// same as Data and o2-analysis-mccollision-converter + +#include "PWGLF/DataModel/LFSlimNucleiTables.h" +// +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetUtilities.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // for PDG codes +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct NucleusCandidate { + int globalIndex = 0; + int collTrackIndex = 0; + float pt = 0.f; + float eta = 0.f; + float phi = 0.f; + float tpcInnerParam = 0.f; + float beta = 0.f; + float zVertex = 0.f; + int nContrib = 0; + float DCAxy = 0.f; + float DCAz = 0.f; + float TPCsignal = 0.f; + float ITSchi2 = 0.f; + float TPCchi2 = 0.f; + float TOFchi2 = 0.f; + std::array nSigmaTPC{}; + std::array tofMasses{}; + bool fillTree = false; + bool fillDCAHist = false; + bool correctPV = false; + bool isSecondary = false; + bool fromWeakDecay = false; + uint16_t flags = 0; + uint8_t TPCfindableCls = 0; + uint8_t TPCcrossedRows = 0; + uint8_t ITSclsMap = 0; + uint8_t TPCnCls = 0; + uint8_t TPCnClsShared = 0; + uint8_t ITSnCls = 0; + uint32_t clusterSizesITS = 0; +}; + +namespace nuclei +{ +constexpr double bbMomScalingDefault[5][2]{ + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}}; +constexpr double betheBlochDefault[5][6]{ + {-136.71, 0.441, 0.2269, 1.347, 0.8035, 0.09}, + {-136.71, 0.441, 0.2269, 1.347, 0.8035, 0.09}, + {-239.99, 1.155, 1.099, 1.137, 1.006, 0.09}, + {-321.34, 0.6539, 1.591, 0.8225, 2.363, 0.09}, + {-586.66, 1.859, 4.435, 0.282, 3.201, 0.09}}; +constexpr double nSigmaTPCdefault[5][2]{ + {-5., 5.}, + {-5., 5.}, + {-5., 5.}, + {-5., 5.}, + {-5., 5.}}; +constexpr double DCAcutDefault[5][2]{ + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}}; +constexpr int TreeConfigDefault[5][2]{ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; +constexpr int DCAHistDefault[5][2]{ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}; +constexpr double DownscalingDefault[5][1]{ + {1.}, + {1.}, + {1.}, + {1.}, + {1.}}; +constexpr int species{5}; // Number of analysed species +constexpr int codes[5]{2212, 1000010020, 1000010030, 1000020030, 1000020040}; // PGD code of these particles +constexpr float charges[5]{1.f, 1.f, 1.f, 2.f, 2.f}; // Their charge +constexpr float masses[5]{MassProton, MassDeuteron, MassTriton, MassHelium3, MassAlpha}; // Their masses +static const std::vector matter{"M", "A"}; // Type of particles (matter or antimatter) +static const std::vector pidName{"TPC", "TOF"}; // Type of PID +static const std::vector hfMothCodes{511, 521, 531, 541, 5122}; // b-mesons + Lambda_b +static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; // Particles name +static const std::vector treeConfigNames{"Filter trees", "Use TOF selection"}; +static const std::vector DCAConfigNames{"Save DCA hist", "Matter/Antimatter"}; +static const std::vector nSigmaConfigName{"nsigma_min", "nsigma_max"}; // label for nsigmaTPC selection +static const std::vector nDCAConfigName{"max DCAxy", "max DCAz"}; // label for DCA selection +static const std::vector DownscalingConfigName{"Fraction of kept candidates"}; // Fraction of candidates to be kept +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; // BB paramteters +static const std::vector binnedVariableNames{"DCAxy", "DCAz", "TPCnsigma", "TOFnsigma", "TOFmass"}; +static const std::vector chargeLabelNames{"Positive", "Negative"}; // Particles charge (pos or neg) + +float pidCuts[2][5][2]; +// This is a set of 2x5x2 3D histograms +// described by smart pointer. +// Keep in mind: first index: TPC or TOF. Second index: type of particle. Third index: charge. +std::shared_ptr hNsigma[2][5][2]; +std::shared_ptr hTOFmass[5][2]; +std::shared_ptr hGenNuclei[5][2]; +std::shared_ptr hMomRes[5][2]; +std::shared_ptr hNsigmaEta[2][5][2]; +std::shared_ptr hTOFmassEta[5][2]; +std::shared_ptr hDCAxy[2][5][2]; +std::shared_ptr hDCAz[2][5][2]; +std::shared_ptr hGloTOFtracks[2]; +std::shared_ptr hDeltaP[2][5]; +std::shared_ptr hDCAHists[2][5]; +o2::base::MatLayerCylSet* lut = nullptr; // describe detector material + +std::vector candidates; + +enum evSel { + kTVX = 0, + kTFBorder, // Here we can substitute with sel8 + kITSROFborder, + kZvtx, + kNoSameBunchPileup, + kIsGoodZvtxFT0vsPV, + kIsGoodITSLayersAll, + kIsEPtriggered, + kIsJetTriggered, // Check: evSel for event with at least one jet over pT-threshold + kNevSels +}; + +static const std::vector eventSelectionTitle{"Event selections"}; +static const std::vector eventSelectionLabels{"TVX", "TF border", "ITS ROF border", "Z vtx", "No same-bunch pile-up", "kIsGoodZvtxFT0vsPV", "isGoodITSLayersAll", "isEPtriggered", "IsJetTriggered"}; + +constexpr int EvSelDefault[9][1]{ + {1}, + {1}, + {1}, // Default: sel8 + {0}, + {0}, + {0}, + {0}, + {0}, + {1}}; // Triggered on jets + +enum evGenSel : uint8_t { + kGenIsJetTriggered = 1 << 0, + kGenHasRecoEv = 1 << 1 +}; + +enum triggerListName { + fChJetLowPt = 0, + fChJetHighPt = 1 +}; +} // namespace nuclei + +struct DeuteronInTriggeredEvents { + enum { + kProton = BIT(0), + kDeuteron = BIT(1), + kTriton = BIT(2), + kHe3 = BIT(3), + kHe4 = BIT(4), + kHasTOF = BIT(5), + kHasTRD = BIT(6), + kIsAmbiguous = BIT(7), /// just a placeholder now + kITSrof = BIT(8), + kIsPhysicalPrimary = BIT(9), /// MC flags starting from the second half of the short + kIsSecondaryFromMaterial = BIT(10), + kIsSecondaryFromWeakDecay = BIT(11) /// the last 4 bits are reserved for the PID in tracking + }; + + Produces nucleiTable; // For data + Produces nucleiTableMCExtension; // For MC analysis + Produces GenEventMCSel; // For MC reco events + Service ccdb; + Zorro zorro; // Definition of Zorro: helpful for skimmed data + OutputObj zorroSummary{"zorroSummary"}; + + Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; + + struct : o2::framework::ConfigurableGroup { + std::string prefix{"cfgTrackCut"}; + Configurable> dcaMax{"dcaMax", {nuclei::DCAcutDefault[0], 5, 2, nuclei::names, nuclei::nDCAConfigName}, "Max DCAxy and DCAz for light nuclei"}; + Configurable etaMax{"etaMax", 0.8f, "Max Eta for tracks"}; + Configurable itsNClusMin{"itsNClusMin", 5, "Minimum number of ITS clusters"}; + Configurable itsChi2ClusMax{"itsChi2ClusMax", 36.f, "Max ITS Chi2 per cluster"}; + Configurable rapidityMax{"rapidityMax", 1.f, "Maximum rapidity for tracks"}; + Configurable rapidityMin{"rapidityMin", -1.f, "Minimum rapidity for tracks"}; + Configurable rapidityToggle{"rapidityToggle", false, "If true, use rapidity cuts"}; + Configurable tpcChi2ClusMax{"tpcChi2ClusMax", 4.f, "Max TPC Chi2 per cluster"}; + Configurable tpcNCrossedRowsMin{"tpcNCrossedRowsMin", 70, "Minimum number of TPC crossed rows"}; + Configurable tpcNCrossedRowsOverFindableMin{"tpcNCrossedRowsOverFindableMin", 0.8f, "Minimum ratio of crossed rows over findable clusters"}; + Configurable tpcNClsMin{"tpcNClsMin", 80, "Minimum number of TPC clusters"}; + Configurable tpcRigidityMin{"tpcRigidityMin", 0.5f, "Minimum TPC rigidity for tracks"}; + Configurable> tpcNSigmaMax{"tpcNSigmaMax", {nuclei::nSigmaTPCdefault[0], 5, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; + } cfgTrackCut; + + Configurable cfgCutPtMinTree{"cfgCutPtMinTree", 0.2f, "Minimum track transverse momentum for tree saving"}; + Configurable cfgCutPtMaxTree{"cfgCutPtMaxTree", 15.0f, "Maximum track transverse momentum for tree saving"}; + + // Event selections + Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 9, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + + Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {nuclei::bbMomScalingDefault[0], 5, 2, nuclei::names, nuclei::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], 5, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgDownscaling{"cfgDownscaling", {nuclei::DownscalingDefault[0], 5, 1, nuclei::names, nuclei::DownscalingConfigName}, "Fraction of kept candidates for light nuclei"}; + Configurable> cfgTreeConfig{"cfgTreeConfig", {nuclei::TreeConfigDefault[0], 5, 2, nuclei::names, nuclei::treeConfigNames}, "Filtered trees configuration"}; + Configurable cfgFillGenSecondaries{"cfgFillGenSecondaries", 0, "Fill generated secondaries (0: no, 1: only weak decays, 2: all of them)"}; + Configurable> cfgDCAHists{"cfgDCAHists", {nuclei::DCAHistDefault[0], 5, 2, nuclei::names, nuclei::DCAConfigNames}, "DCA hist configuration"}; + + Configurable cfgNsigmaTPCcutDCAhists{"cfgNsigmaTPCcutDCAhists", 3., "TPC nsigma cut for DCA hists"}; + Configurable cfgDeltaTOFmassCutDCAhists{"cfgDeltaTOFmassCutDCAhists", 0.2, "Delta TOF mass cut for DCA hists"}; + ConfigurableAxis cfgDCAxyBinsProtons{"cfgDCAxyBinsProtons", {1500, -1.5f, 1.5f}, "DCAxy binning for Protons"}; + ConfigurableAxis cfgDCAxyBinsDeuterons{"cfgDCAxyBinsDeuterons", {1500, -1.5f, 1.5f}, "DCAxy binning for Deuterons"}; + ConfigurableAxis cfgDCAxyBinsTritons{"cfgDCAxyBinsTritons", {1500, -1.5f, 1.5f}, "DCAxy binning for Tritons"}; + ConfigurableAxis cfgDCAxyBinsHe3{"cfgDCAxyBinsHe3", {1500, -1.5f, 1.5f}, "DCAxy binning for He3"}; + ConfigurableAxis cfgDCAxyBinsAlpha{"cfgDCAxyBinsAlpha", {1500, -1.5f, 1.5f}, "DCAxy binning for Alpha"}; + + ConfigurableAxis cfgPtBinsProtons{"cfgPtBinsProtons", {100, 0., 10.}, "Pt binning for Protons"}; + ConfigurableAxis cfgPtBinsDeuterons{"cfgPtBinsDeuterons", {100, 0., 10.}, "Pt binning for Deuterons"}; + ConfigurableAxis cfgPtBinsTritons{"cfgPtBinsTritons", {100, 0., 10.}, "Pt binning for Tritons"}; + ConfigurableAxis cfgPtBinsHe3{"cfgPtBinsHe3", {100, 0., 10.}, "Pt binning for He3"}; + ConfigurableAxis cfgPtBinsAlpha{"cfgPtBinsAlpha", {100, 0., 10.}, "Pt binning for Alpha"}; + + Configurable cfgCMrapidity{"cfgCMrapidity", 0.f, "Rapidity of the center of mass (only for p-Pb)"}; + ConfigurableAxis cfgMomResBins{"cfgMomResBins", {200, -1., 1.}, "Momentum resolution binning"}; + ConfigurableAxis cfgNsigmaTPCbins{"cfgNsigmaTPCbins", {100, -5., 5.}, "nsigma_TPC binning"}; + ConfigurableAxis cfgNsigmaTOFbins{"cfgNsigmaTOFbins", {100, -5., 5.}, "nsigma_TOF binning"}; + ConfigurableAxis cfgTOFmassBins{"cfgTOFmassBins", {200, -5., 5.}, "TOF mass binning"}; + ConfigurableAxis cfgNITSClusBins{"cfgNITSClusBins", {3, 4.5, 7.5}, "N ITS clusters binning"}; + ConfigurableAxis cfgNTPCClusBins{"cfgNTPCClusBins", {3, 89.5, 159.5}, "N TPC clusters binning"}; + + // Configurable for working with skimmed data + Configurable cfgApplyMCEvSel{"cfgApplyMCEvSel", false, "If true, apply jet-trigger selection on gen events"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable cfgTriggerList{"cfgTriggerList", 0, "0 : Low jet-pT thr, 1 : High jet-pT thr"}; + + // Configurable for jet identification + Configurable cfgRJet{"cfgRJet", 0.6, "R_jet"}; + Configurable cfgEtaJet{"cfgEtaJet", 0.9, "Jet acceptance"}; + + // running variables for track tuner + o2::dataformats::DCA mDcaInfoCov; + o2::track::TrackParametrizationWithError mTrackParCov; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + // CCDB options + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; + Configurable cfgCCDBurl{"cfgCCDBurl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgZorroCCDBpath{"cfgZorroCCDBpath", "EventFiltering/Zorro/", "path to the zorro ccdb objects"}; + int mRunNumber = 0; + float mBz = 0.f; + + // Utility object for jet background subtraction methods + JetBkgSubUtils backgroundSub; + + using TrackCandidates = soa::Join; + + HistogramRegistry spectra{"spectra", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + double computeAbsoDecL(aod::McParticles::iterator particle) + { + if (!particle.has_daughters()) + return -1.f; + + float mothVtx[3]{particle.vx(), particle.vy(), particle.vz()}; + float dauVtx[3]{0.f, 0.f, 0.f}; + auto daughters = particle.daughters_as(); + for (const auto& dau : daughters) { + if (std::abs(dau.pdgCode()) != PDG_t::kGamma && std::abs(dau.pdgCode()) != PDG_t::kElectron) { + dauVtx[0] = dau.vx(); + dauVtx[1] = dau.vy(); + dauVtx[2] = dau.vz(); + break; + } + } + return std::hypot(mothVtx[0] - dauVtx[0], mothVtx[1] - dauVtx[1], mothVtx[2] - dauVtx[2]); + } + + template + bool eventSelectionWithHisto(Tcoll& collision) + { + spectra.fill(HIST("hEventSelections"), 0); + + if (cfgEventSelections->get(nuclei::evSel::kTVX) && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kTVX + 1); + + if (cfgEventSelections->get(nuclei::evSel::kTFBorder) && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kTFBorder + 1); + + if (cfgEventSelections->get(nuclei::evSel::kITSROFborder) && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kITSROFborder + 1); + + if (cfgEventSelections->get(nuclei::evSel::kZvtx) && std::abs(collision.posZ()) > cfgCutVertex) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kZvtx + 1); + + if (cfgEventSelections->get(nuclei::evSel::kNoSameBunchPileup) && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kNoSameBunchPileup + 1); + + if (cfgEventSelections->get(nuclei::evSel::kIsGoodZvtxFT0vsPV) && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsGoodZvtxFT0vsPV + 1); + + if (cfgEventSelections->get(nuclei::evSel::kIsGoodITSLayersAll) && !collision.selection_bit(aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsGoodITSLayersAll + 1); + + if constexpr ( + requires { + collision.triggereventep(); + }) { + if (cfgEventSelections->get(nuclei::evSel::kIsEPtriggered) && !collision.triggereventep()) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsEPtriggered + 1); + } + + auto bc = collision.template bc_as(); + initCCDB(bc); + + gRandom->SetSeed(bc.timestamp()); + + if (cfgSkimmedProcessing) { + bool isTriggered = zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + if (!isTriggered) + return false; + } + + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsJetTriggered + 1); + + return true; + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), (cfgTriggerList.value == nuclei::fChJetLowPt) ? "fJetChLowPt" : (cfgTriggerList.value == nuclei::fChJetHighPt) ? "fJetChHighPt" + : throw std::runtime_error("Invalid TriggerList value")); + zorro.populateHistRegistry(spectra, bc.runNumber()); + } + auto timestamp = bc.timestamp(); + mRunNumber = bc.runNumber(); + + o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(nuclei::lut); + mBz = static_cast(grpmag->getNominalL3Field()); + LOGF(info, "Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG", timestamp, mRunNumber, mBz); + } + + void init(o2::framework::InitContext&) + { + zorroSummary.setObject(zorro.getZorroSummary()); + zorro.setBaseCCDBPath(cfgZorroCCDBpath.value); + ccdb->setURL(cfgCCDBurl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + const AxisSpec nSigmaAxes[2]{{cfgNsigmaTPCbins, "n#sigma_{TPC}"}, {cfgNsigmaTOFbins, "n#sigma_{TOF}"}}; + const AxisSpec tofMassAxis{cfgTOFmassBins, "TOF mass - PDG mass"}; + const AxisSpec ptResAxis{cfgMomResBins, "#Delta#it{p}_{T}/#it{p}_{T}"}; + const AxisSpec nITSClusAxis{cfgNITSClusBins, "N ITS clusters"}; + const AxisSpec nTPCClusAxis{cfgNTPCClusBins, "N TPC clusters"}; + const AxisSpec hasTRDAxis{2, -0.5, 1.5, "Has TRD"}; + const AxisSpec correctPVAxis{2, -0.5, 1.5, "Correct PV"}; + const AxisSpec isSecondaryAxis{2, -0.5, 1.5, "Is secondary"}; + const AxisSpec fromWeakDecayAxis{2, -0.5, 1.5, "From weak decay"}; + + const AxisSpec ptAxes[5]{ + {cfgPtBinsProtons, "#it{p}_{T} (GeV/#it{c})"}, + {cfgPtBinsDeuterons, "#it{p}_{T} (GeV/#it{c})"}, + {cfgPtBinsTritons, "#it{p}_{T} (GeV/#it{c})"}, + {cfgPtBinsHe3, "#it{p}_{T} (GeV/#it{c})"}, + {cfgPtBinsAlpha, "#it{p}_{T} (GeV/#it{c})"}}; + const AxisSpec dcaxyAxes[5]{ + {cfgDCAxyBinsProtons, "DCA_{xy} (cm)"}, + {cfgDCAxyBinsDeuterons, "DCA_{xy} (cm)"}, + {cfgDCAxyBinsTritons, "DCA_{xy} (cm)"}, + {cfgDCAxyBinsHe3, "DCA_{xy} (cm)"}, + {cfgDCAxyBinsAlpha, "DCA_{xy} (cm)"}}; + const AxisSpec dcazAxes[5]{ + {cfgDCAxyBinsProtons, "DCA_{z} (cm)"}, + {cfgDCAxyBinsDeuterons, "DCA_{z} (cm)"}, + {cfgDCAxyBinsTritons, "DCA_{z} (cm)"}, + {cfgDCAxyBinsHe3, "DCA_{z} (cm)"}, + {cfgDCAxyBinsAlpha, "DCA_{z} (cm)"}}; + const AxisSpec etaAxis{40, -1., 1., "#eta"}; + + spectra.add("hEventSelections", "hEventSelections", {HistType::kTH1D, {{nuclei::evSel::kNevSels + 1, -0.5f, static_cast(nuclei::evSel::kNevSels) + 0.5f}}}); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(1, "all"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kTVX + 2, "TVX"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kTFBorder + 2, "TFborder"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kITSROFborder + 2, "ITSROFborder"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kZvtx + 2, "Zvtx"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kNoSameBunchPileup + 2, "kNoSameBunchPileup"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodZvtxFT0vsPV + 2, "isGoodZvtxFT0vsPV"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodITSLayersAll + 2, "IsGoodITSLayersAll"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsEPtriggered + 2, "IsEPtriggered"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsJetTriggered + 2, "IsJetTriggered"); + + // Distribution of z-vertex of selected events + spectra.add("hRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); + // Distribution of z-vertex of generated events + if (doprocessMC) { + spectra.add("hGenVtxZ", " generated collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); + } + spectra.add("hTpcSignalData", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + spectra.add("hTpcSignalDataSelected", "Specific energy loss for selected particles", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + spectra.add("hTofSignalData", "TOF beta", HistType::kTH2F, {{500, 0., 5., "#it{p} (GeV/#it{c})"}, {750, 0, 1.5, "TOF #beta"}}); + + for (unsigned int iC{0}; iC < nuclei::matter.size(); ++iC) { + nuclei::hGloTOFtracks[iC] = spectra.add(fmt::format("hTPCTOFtracks{}", nuclei::matter[iC]).data(), fmt::format("Global vs TOF matched {} tracks in a collision", nuclei::chargeLabelNames[iC]).data(), HistType::kTH2D, {{300, -0.5, 300.5, "Number of global tracks"}, {300, -0.5, 300.5, "Number of TOF matched tracks"}}); + + for (int iS{0}; iS < nuclei::species; ++iS) { + nuclei::hNsigma[0][iS][iC] = spectra.add(fmt::format("h{}nsigma{}_{}", nuclei::pidName[0], nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("n#sigma_{{}} {} {}", nuclei::pidName[0], nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTH2D, {ptAxes[iS], nSigmaAxes[0]}); + nuclei::hNsigmaEta[0][iS][iC] = spectra.add(fmt::format("h{}nsigmaEta{}_{}", nuclei::pidName[0], nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("n#sigma_{{}} {} {} vs #eta", nuclei::pidName[0], nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTH3D, {etaAxis, ptAxes[iS], nSigmaAxes[0]}); + + for (unsigned int iPID{0}; iPID < nuclei::matter.size(); ++iPID) { + nuclei::hDCAxy[iPID][iS][iC] = spectra.add(fmt::format("hDCAxy{}_{}_{}", nuclei::pidName[iPID], nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCAxy {} {} {}", nuclei::pidName[iPID], nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTH2D, {ptAxes[iS], dcaxyAxes[iS]}); + nuclei::hDCAz[iPID][iS][iC] = spectra.add(fmt::format("hDCAz{}_{}_{}", nuclei::pidName[iPID], nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCAz {} {} {}", nuclei::pidName[iPID], nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTH2D, {ptAxes[iS], dcazAxes[iS]}); + } + nuclei::hTOFmass[iS][iC] = spectra.add(fmt::format("h{}TOFmass{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("TOF mass - {} PDG mass", nuclei::names[iS]).data(), HistType::kTH2D, {ptAxes[iS], tofMassAxis}); + nuclei::hTOFmassEta[iS][iC] = spectra.add(fmt::format("h{}TOFmassEta{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("TOF mass - {} PDG mass", nuclei::names[iS]).data(), HistType::kTH3D, {etaAxis, ptAxes[iS], tofMassAxis}); + nuclei::hDeltaP[iC][iS] = spectra.add(fmt::format("hDeltaP{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("#Delta#it{{p}}/#it{{p}} {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTH2D, {{232, 0.2, 6., "#it{p} (GeV/#it{{c}})"}, {200, -1.0, 1.0, "(#it{p}_{IU} - #it{p}_{TPC}) / #it{p}"}}); + if (doprocessMC) { + nuclei::hMomRes[iS][iC] = spectra.add(fmt::format("h{}MomRes{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Momentum resolution {}", nuclei::names[iS]).data(), HistType::kTH2D, {ptAxes[iS], ptResAxis}); + nuclei::hGenNuclei[iS][iC] = spectra.add(fmt::format("h{}Gen{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("Generated {}", nuclei::names[iS]).data(), HistType::kTH1D, {ptAxes[iS]}); + nuclei::hDCAHists[iC][iS] = spectra.add(fmt::format("hDCAHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCA histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {ptAxes[iS], dcaxyAxes[iS], dcazAxes[iS], nSigmaAxes[0], tofMassAxis, nITSClusAxis, nTPCClusAxis, correctPVAxis, isSecondaryAxis, fromWeakDecayAxis}); + } else { + nuclei::hDCAHists[iC][iS] = spectra.add(fmt::format("hDCAHists{}_{}", nuclei::matter[iC], nuclei::names[iS]).data(), fmt::format("DCA histograms {} {}", nuclei::matter[iC], nuclei::names[iS]).data(), HistType::kTHnSparseF, {ptAxes[iS], dcaxyAxes[iS], dcazAxes[iS], nSigmaAxes[0], tofMassAxis, nITSClusAxis, nTPCClusAxis}); + } + } + } + + // Setting the nsigma interval in which the the candidate is kept + // The first index is set to 0 because it is for TPC + for (int iS{0}; iS < nuclei::species; ++iS) { + for (unsigned int iMax{0}; iMax < nuclei::pidName.size(); ++iMax) { + nuclei::pidCuts[0][iS][iMax] = cfgTrackCut.tpcNSigmaMax->get(iS, iMax); + } + } + + nuclei::lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + } + + // Find hit on ITS layer + template + bool hasHitITS(const TrackIts& track, int layer) + { + int ibit = layer - 1; + return (track.itsClusterMap() & (1 << ibit)); + } + + template + bool isJetTriggered(Ttrks const& tracks, nuclei::triggerListName triggerCondition) + { + // Defining trigger condition + double jetPtThreshold(0.0); + + switch (triggerCondition) { + case nuclei::fChJetLowPt: + jetPtThreshold = 30.0; + break; + case nuclei::fChJetHighPt: + jetPtThreshold = 55.0; + break; + default: + return false; // Non-valid trigger + } + + // Loop over tracks + int id(-1); + std::vector fjParticles; + fjParticles.clear(); + for (auto const& track : tracks) { + id++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); + fourMomentum.set_user_index(id); + fjParticles.emplace_back(fourMomentum); + } + + if (fjParticles.empty()) + return false; // reject 0-particles events + + // Cluster particles using the the anti-kT algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, cfgRJet); // Defining the algorithm to cluster, and the jet radius + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // Activate area evaluation, and set area evaluation method + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); // Declare the will of applying clustering algorithm with area evaluation to the selected candidates + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + + if (jets.empty()) + return false; // skip events with no reconstructed jets + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], cfgRJet); + + // Analyse only leading jet + const auto& jet = jets[0]; + if (std::fabs(jet.eta()) > cfgEtaJet) + return false; // Jet must be fully contained in the acceptance + + // Jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < jetPtThreshold) + return false; + + return true; + } + + template + bool isMCJetTriggered(McParts const& McParticles, aod::McParticles const& particlesMC, nuclei::triggerListName triggerCondition) + { + // Defining trigger condition + double jetPtThreshold(0.0); + + switch (triggerCondition) { + case nuclei::fChJetLowPt: + jetPtThreshold = 30.0; + break; + case nuclei::fChJetHighPt: + jetPtThreshold = 55.0; + break; + default: + return false; // Non-valid trigger + } + + std::vector fjParticles; + fjParticles.clear(); + + for (auto const& particle : McParticles) { + + // MC particles per collision + if (!isPhysicalPrimaryOrFromHF(particle, particlesMC)) + continue; + + double minPtParticle = 0.1; + if (std::fabs(particle.eta()) > cfgEtaJet || particle.pt() < minPtParticle) + continue; + + // Build 4-momentum assuming charged pion mass + static constexpr float kMassPionChargedSquared = o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged; + const double energy = std::sqrt(particle.p() * particle.p() + kMassPionChargedSquared); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fourMomentum.set_user_index(particle.pdgCode()); + fjParticles.emplace_back(fourMomentum); + } + + if (fjParticles.empty()) + return false; // reject 0-particles events + + // Cluster particles using the the anti-kT algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, cfgRJet); // Defining the algorithm to cluster, and the jet radius + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // Activate area evaluation, and set area evaluation method + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); // Declare the will of applying clustering algorithm with area evaluation to the selected candidates + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + + if (jets.empty()) + return false; // skip events with no reconstructed jets + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], cfgRJet); + + // Analyse only leading jet + const auto& jet = jets[0]; + if (std::fabs(jet.eta()) > cfgEtaJet) + return false; // Jet must be fully contained in the acceptance + + // Jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < jetPtThreshold) + return false; + + return true; + } + + // Check if particle is a physical primary or a decay product of a heavy-flavor hadron + bool isPhysicalPrimaryOrFromHF(aod::McParticle const& particle, aod::McParticles const& mcParticles) + { + // Keep only pi, K, p, e, mu + int pdg = std::abs(particle.pdgCode()); + if (!(pdg == PDG_t::kPiPlus || pdg == PDG_t::kKPlus || pdg == PDG_t::kProton || pdg == PDG_t::kElectron || pdg == PDG_t::kMuonMinus)) + return false; + + // Constants for identifying heavy-flavor (charm and bottom) content from PDG codes + static constexpr int kCharmQuark = 4; + static constexpr int kBottomQuark = 5; + static constexpr int hundreds = 100; + static constexpr int thousands = 1000; + + // Check if particle is from heavy-flavor decay + bool fromHF = false; + if (particle.has_mothers()) { + auto mother = mcParticles.iteratorAt(particle.mothersIds()[0]); + int motherPdg = std::abs(mother.pdgCode()); + fromHF = (motherPdg / hundreds == kCharmQuark || motherPdg / hundreds == kBottomQuark || motherPdg / thousands == kCharmQuark || motherPdg / thousands == kBottomQuark); + } + + // Select only physical primary particles or from heavy-flavor + return (particle.isPhysicalPrimary() || fromHF); + } + + // Track selection criteria for creating jets + template + bool passedTrackSelectionForJetReconstruction(const JetTrack& track) + { + static constexpr int MinTpcCr = 70; + static constexpr double MaxChi2Tpc = 4.0; + static constexpr double MaxChi2Its = 36.0; + static constexpr double MinPtTrack = 0.1; + static constexpr double DcaxyMaxTrackPar0 = 0.0105; + static constexpr double DcaxyMaxTrackPar1 = 0.035; + static constexpr double DcaxyMaxTrackPar2 = 1.1; + static constexpr double DcazMaxTrack = 2.0; + + // General part + if (std::fabs(track.eta()) > cfgEtaJet) + return false; + if (track.pt() < MinPtTrack) + return false; + if (std::fabs(track.dcaXY()) > (DcaxyMaxTrackPar0 + DcaxyMaxTrackPar1 / std::pow(track.pt(), DcaxyMaxTrackPar2))) + return false; // DCAxy cut + if (std::fabs(track.dcaZ()) > DcazMaxTrack) + return false; // DCAz cut + // Part relative to ITS + if (!track.hasITS()) + return false; + if ((!hasHitITS(track, 1)) && (!hasHitITS(track, 2)) && (!hasHitITS(track, 3))) + return false; // Has Inner Barrel hit + if (track.itsChi2NCl() >= MaxChi2Its) + return false; + // Part relative to TPC + if (!track.hasTPC()) + return false; + if (track.tpcNClsCrossedRows() < MinTpcCr) + return false; + if (track.tpcChi2NCl() >= MaxChi2Tpc) + return false; + + return true; + } + + template + void fillDataInfo(Tcoll const& collision, Ttrks const& tracks) + { + spectra.fill(HIST("hRecVtxZData"), collision.posZ()); + + const o2::math_utils::Point3D collVtx{collision.posX(), collision.posY(), collision.posZ()}; + + const double bgScalings[5][2]{ + {nuclei::charges[0] * cfgMomentumScalingBetheBloch->get(0u, 0u) / nuclei::masses[0], nuclei::charges[0] * cfgMomentumScalingBetheBloch->get(0u, 1u) / nuclei::masses[0]}, + {nuclei::charges[1] * cfgMomentumScalingBetheBloch->get(1u, 0u) / nuclei::masses[1], nuclei::charges[1] * cfgMomentumScalingBetheBloch->get(1u, 1u) / nuclei::masses[1]}, + {nuclei::charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / nuclei::masses[2], nuclei::charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / nuclei::masses[2]}, + {nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 0u) / nuclei::masses[3], nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 1u) / nuclei::masses[3]}, + {nuclei::charges[4] * cfgMomentumScalingBetheBloch->get(4u, 0u) / nuclei::masses[4], nuclei::charges[4] * cfgMomentumScalingBetheBloch->get(4u, 1u) / nuclei::masses[4]}}; + + int nGloTracks[2]{0, 0}, nTOFTracks[2]{0, 0}; + + constexpr float MinMomentumForDeltaP = 0.2f; + + for (const auto& track : tracks) { // start loop over tracks + if (std::abs(track.eta()) > cfgTrackCut.etaMax || + track.tpcInnerParam() < cfgTrackCut.tpcRigidityMin || + track.itsNCls() < cfgTrackCut.itsNClusMin || + track.tpcNClsFound() < cfgTrackCut.tpcNClsMin || + track.tpcNClsCrossedRows() < cfgTrackCut.tpcNCrossedRowsMin || + track.tpcNClsCrossedRows() < cfgTrackCut.tpcNCrossedRowsOverFindableMin * track.tpcNClsFindable() || + track.tpcChi2NCl() > cfgTrackCut.tpcChi2ClusMax || + track.itsChi2NCl() > cfgTrackCut.itsChi2ClusMax) { + continue; + } + // temporary fix: tpcInnerParam() returns the momentum in all the software tags before --- CM: what does it mean + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + + spectra.fill(HIST("hTpcSignalData"), correctedTpcInnerParam * track.sign(), track.tpcSignal()); + float nSigma[2][5]{ + {-10., -10., -10., -10., -10.}, + {0.f, 0.f, 0.f, 0.f, 0.f}}; /// then we will calibrate the TOF mass for the He3 and Alpha + const int iC{track.sign() < 0}; + + /// Checking if we have outliers in the TPC-TOF correlation + nGloTracks[iC]++; + if (track.hasTOF()) { + nTOFTracks[iC]++; + } + + bool selectedTPC[5]{false}, goodToAnalyse{false}; + std::array nSigmaTPC; + // This part apply a selection on tracks: + // if the nsigma of the track is less than a certain value, it is accepted + for (int iS{0}; iS < nuclei::species; ++iS) { // The first index here is set to 0 because it is TPC analysis + double expBethe{common::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScalings[iS][iC]), cfgBetheBlochParams->get(iS, 0u), cfgBetheBlochParams->get(iS, 1u), cfgBetheBlochParams->get(iS, 2u), cfgBetheBlochParams->get(iS, 3u), cfgBetheBlochParams->get(iS, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(iS, 5u)}; + nSigma[0][iS] = static_cast((track.tpcSignal() - expBethe) / expSigma); + nSigmaTPC[iS] = nSigma[0][iS]; + selectedTPC[iS] = (nSigma[0][iS] > nuclei::pidCuts[0][iS][0] && nSigma[0][iS] < nuclei::pidCuts[0][iS][1]); + goodToAnalyse = goodToAnalyse || selectedTPC[iS]; + if (selectedTPC[iS] && track.p() > MinMomentumForDeltaP) { + nuclei::hDeltaP[iC][iS]->Fill(track.p(), 1 - correctedTpcInnerParam / track.p()); // Important: see of there is a shift between track momentum and tpc innerparam + } + } + if (!goodToAnalyse) { + continue; + } + + mDcaInfoCov.set(999, 999, 999, 999, 999); + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + std::array dcaInfo; + o2::base::Propagator::Instance()->propagateToDCA(collVtx, mTrackParCov, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfo); + + float beta{o2::pid::tof::Beta::GetBeta(track)}; + spectra.fill(HIST("hTpcSignalDataSelected"), correctedTpcInnerParam * track.sign(), track.tpcSignal()); + spectra.fill(HIST("hTofSignalData"), correctedTpcInnerParam, beta); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0 + uint16_t flag = static_cast((track.pidForTracking() & 0xF) << 12); // Store the PID of the track in the 12-15 bit + std::array tofMasses{-3.f, -3.f, -3.f, -3.f, -3.f}; + bool fillTree{false}; + bool fillDCAHist{false}; + bool correctPV{false}; + bool isSecondary{false}; + bool fromWeakDecay{false}; + + if (track.hasTOF()) { + flag |= kHasTOF; + } + if (track.hasTRD()) { + flag |= kHasTRD; + } + if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + flag |= kITSrof; + } + + for (int iS{0}; iS < nuclei::species; ++iS) { + bool selectedTOF{false}; + if (std::abs(dcaInfo[1]) > cfgTrackCut.dcaMax->get(iS, 1)) { + continue; + } + ROOT::Math::LorentzVector> fvector{mTrackParCov.getPt() * nuclei::charges[iS], mTrackParCov.getEta(), mTrackParCov.getPhi(), nuclei::masses[iS]}; + float y{fvector.Rapidity() + cfgCMrapidity}; + for (unsigned int iPID{0}; iPID < nuclei::pidName.size(); ++iPID) { /// 0 TPC, 1 TOF + if (selectedTPC[iS]) { + if (iPID && !track.hasTOF()) { + continue; + } else if (iPID) { + selectedTOF = true; /// temporarly skipped + float charge{nuclei::charges[iS]}; + tofMasses[iS] = correctedTpcInnerParam * charge * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]; + } + if (!cfgTrackCut.rapidityToggle || (y > cfgTrackCut.rapidityMin && y < cfgTrackCut.rapidityMax)) { + if (std::abs(nSigmaTPC[iS]) < cfgNsigmaTPCcutDCAhists && (!iPID || std::abs(tofMasses[iS]) < cfgDeltaTOFmassCutDCAhists)) { + nuclei::hDCAxy[iPID][iS][iC]->Fill(fvector.pt(), dcaInfo[0]); + nuclei::hDCAz[iPID][iS][iC]->Fill(fvector.pt(), dcaInfo[1]); + } + if (std::abs(dcaInfo[0]) < cfgTrackCut.dcaMax->get(iS, 0u)) { + if (!iPID) { /// temporary exclusion of the TOF nsigma PID for the He3 and Alpha + nuclei::hNsigma[iPID][iS][iC]->Fill(fvector.pt(), nSigma[iPID][iS]); + nuclei::hNsigmaEta[iPID][iS][iC]->Fill(fvector.eta(), fvector.pt(), nSigma[iPID][iS]); + } + if (iPID) { + nuclei::hTOFmass[iS][iC]->Fill(fvector.pt(), tofMasses[iS]); + nuclei::hTOFmassEta[iS][iC]->Fill(fvector.eta(), fvector.pt(), tofMasses[iS]); + } + } + } + } + } + if (selectedTPC[iS]) { + if (cfgTreeConfig->get(iS, 1u) && !selectedTOF) { + continue; + } + !fillTree && cfgTreeConfig->get(iS, 0u) ? fillTree = true : fillTree; + !fillDCAHist && cfgDCAHists->get(iS, iC) ? fillDCAHist = true : fillDCAHist; + bool setPartFlag = cfgTreeConfig->get(iS, 0u) || cfgDCAHists->get(iS, iC); + if (setPartFlag) { + if (cfgDownscaling->get(iS) < 1. && gRandom->Rndm() > cfgDownscaling->get(iS)) { + continue; + } + flag |= BIT(iS); + } + } + } + if (flag & (kProton | kDeuteron | kTriton | kHe3 | kHe4) || doprocessMC) { /// ignore PID pre-selections for the MC + if (fillTree) { + if (flag & kTriton) { + if (track.pt() < cfgCutPtMinTree || track.pt() > cfgCutPtMaxTree || track.sign() > 0) + continue; + } + } + nuclei::candidates.emplace_back(NucleusCandidate{ + static_cast(track.globalIndex()), static_cast(track.collisionId()), (1 - 2 * iC) * mTrackParCov.getPt(), mTrackParCov.getEta(), mTrackParCov.getPhi(), + correctedTpcInnerParam, beta, collision.posZ(), collision.numContrib(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), + nSigmaTPC, tofMasses, fillTree, fillDCAHist, correctPV, isSecondary, fromWeakDecay, flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), + static_cast(track.tpcNClsFound()), static_cast(track.tpcNClsShared()), static_cast(track.itsNCls()), static_cast(track.itsClusterSizes())}); + } + } // end loop over tracks + + nuclei::hGloTOFtracks[0]->Fill(nGloTracks[0], nTOFTracks[0]); + nuclei::hGloTOFtracks[1]->Fill(nGloTracks[1], nTOFTracks[1]); + } + + void processData(soa::Join::iterator const& collision, TrackCandidates const& tracks, aod::BCsWithTimestamps const&) + { + nuclei::candidates.clear(); + if (!eventSelectionWithHisto(collision)) { + return; + } + + fillDataInfo(collision, tracks); // Apply selection on track candidates and saving in structure nuclei + + for (size_t i1{0}; i1 < nuclei::candidates.size(); ++i1) { + auto& c1 = nuclei::candidates[i1]; + if (c1.fillTree) { + nucleiTable(c1.pt, c1.eta, c1.phi, c1.tpcInnerParam, c1.beta, c1.zVertex, c1.nContrib, c1.DCAxy, c1.DCAz, c1.TPCsignal, c1.ITSchi2, c1.TPCchi2, c1.TOFchi2, c1.flags, c1.TPCfindableCls, c1.TPCcrossedRows, c1.ITSclsMap, c1.TPCnCls, c1.TPCnClsShared, c1.clusterSizesITS); + } + if (c1.fillDCAHist) { + for (int iS{0}; iS < nuclei::species; ++iS) { + if (c1.flags & BIT(iS)) { + nuclei::hDCAHists[c1.pt < 0][iS]->Fill(std::abs(c1.pt), c1.DCAxy, c1.DCAz, c1.nSigmaTPC[iS], c1.tofMasses[iS], c1.ITSnCls, c1.TPCnCls); + } + } + } + } + } + PROCESS_SWITCH(DeuteronInTriggeredEvents, processData, "Data analysis", true); + + Preslice tracksPerCollisions = aod::track::collisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + void processMC(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& tracks, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) + { + nuclei::candidates.clear(); + + std::vector goodCollisions(mcCollisions.size(), false); + std::vector eventMask(mcCollisions.size(), 0); + + // Jet trigger condition + auto trigger = static_cast(cfgTriggerList.value); + + for (const auto& c : mcCollisions) { + + spectra.fill(HIST("hGenVtxZ"), c.posZ()); + + auto mcParticlesPerColl = particlesMC.sliceBy(perMcCollision, c.globalIndex()); + auto& mask = eventMask[c.globalIndex()]; + + if (isMCJetTriggered(mcParticlesPerColl, particlesMC, trigger)) + mask |= nuclei::kIsJetTriggered; + } + + for (const auto& collision : collisions) { + if (!eventSelectionWithHisto(collision)) { + continue; + } + + // Avoid unwanted memory leaks + if (!collision.has_mcCollision()) + continue; + + int mcId = collision.mcCollisionId(); + if (mcId < 0 || mcId >= static_cast(eventMask.size())) + continue; + + const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); + + if (cfgApplyMCEvSel) { + if (!isJetTriggered(slicedTracks, trigger)) + continue; + } + + goodCollisions[mcId] = true; + auto& mask = eventMask[mcId]; + mask |= nuclei::kGenHasRecoEv; + + GenEventMCSel(mask); + fillDataInfo(collision, slicedTracks); + } + + std::vector isReconstructed(particlesMC.size(), false); + for (auto& c : nuclei::candidates) { + auto label = tracks.iteratorAt(c.globalIndex); + if (label.mcParticleId() < -1 || label.mcParticleId() >= particlesMC.size()) { + continue; + } + auto particle = particlesMC.iteratorAt(label.mcParticleId()); + bool storeIt{false}; + for (int iS{0}; iS < nuclei::species; ++iS) { + if (std::abs(particle.pdgCode()) == nuclei::codes[iS]) { + if (c.fillTree && !storeIt) { + nuclei::hMomRes[iS][particle.pdgCode() < 0]->Fill(1., std::abs(c.pt * nuclei::charges[iS]), 1. - std::abs(c.pt * nuclei::charges[iS]) / particle.pt()); + storeIt = cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u); /// store only the particles of interest + } + auto coll = collisions.iteratorAt(c.collTrackIndex); + int collMCGlobId = coll.mcCollisionId(); + if (particle.mcCollisionId() == collMCGlobId) { + c.correctPV = true; + } + if (!c.correctPV) { + c.flags |= kIsAmbiguous; + } + if (c.fillDCAHist && cfgDCAHists->get(iS, c.pt < 0)) { + nuclei::hDCAHists[c.pt < 0][iS]->Fill(std::abs(c.pt), c.DCAxy, c.DCAz, c.nSigmaTPC[iS], c.tofMasses[iS], c.ITSnCls, c.TPCnCls, c.correctPV, c.isSecondary, c.fromWeakDecay); + } + } + } + if (!storeIt) { + continue; + } + if (particle.y() < cfgTrackCut.rapidityMin || particle.y() > cfgTrackCut.rapidityMax) { + continue; + } + + int motherPdgCode = 0; + float motherDecRadius = -1; + isReconstructed[particle.globalIndex()] = true; + if (particle.isPhysicalPrimary()) { + c.flags |= kIsPhysicalPrimary; + if (particle.has_mothers()) { + for (const auto& motherparticle : particle.mothers_as()) { + if (std::find(nuclei::hfMothCodes.begin(), nuclei::hfMothCodes.end(), std::abs(motherparticle.pdgCode())) != nuclei::hfMothCodes.end()) { + c.flags |= kIsSecondaryFromWeakDecay; + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + break; + } + } + } + } else if (particle.has_mothers()) { + c.flags |= kIsSecondaryFromWeakDecay; + for (const auto& motherparticle : particle.mothers_as()) { + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + } + } else { + c.flags |= kIsSecondaryFromMaterial; + } + + isReconstructed[particle.globalIndex()] = true; + float absoDecL = computeAbsoDecL(particle); + nucleiTableMCExtension(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.nContrib, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absoDecL, eventMask[particle.mcCollisionId()]); + } + + int index{0}; + for (const auto& particle : particlesMC) { + int pdg{std::abs(particle.pdgCode())}; + for (int iS{0}; iS < nuclei::species; ++iS) { + if (pdg != nuclei::codes[iS]) { + continue; + } + if (particle.y() < cfgTrackCut.rapidityMin || particle.y() > cfgTrackCut.rapidityMax) { + continue; + } + + uint16_t flags = 0; + int motherPdgCode = 0; + float motherDecRadius = -1; + if (particle.isPhysicalPrimary()) { + flags |= kIsPhysicalPrimary; + nuclei::hGenNuclei[iS][particle.pdgCode() < 0]->Fill(1., particle.pt()); + // antinuclei from B hadrons are classified as physical primaries + if (particle.has_mothers()) { + for (const auto& motherparticle : particle.mothers_as()) { + if (std::find(nuclei::hfMothCodes.begin(), nuclei::hfMothCodes.end(), std::abs(motherparticle.pdgCode())) != nuclei::hfMothCodes.end()) { + flags |= kIsSecondaryFromWeakDecay; + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + break; + } + } + } + } else if (particle.getProcess() == TMCProcess::kPDecay) { + if (!particle.has_mothers()) { + continue; // skip secondaries from weak decay without mothers + } + flags |= kIsSecondaryFromWeakDecay; + for (const auto& motherparticle : particle.mothers_as()) { + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + } + } else { + flags |= kIsSecondaryFromMaterial; + } + + if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { + if ((flags & kIsPhysicalPrimary) == 0 && cfgFillGenSecondaries == 0) { + continue; // skip secondaries if not requested + } + if ((flags & (kIsPhysicalPrimary | kIsSecondaryFromWeakDecay)) == 0 && cfgFillGenSecondaries == 1) { + continue; // skip secondaries from material if not requested + } + float absDecL = computeAbsoDecL(particle); + nucleiTableMCExtension(999., 999., 999., 0., 0., 999., -1, 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absDecL, eventMask[particle.mcCollisionId()]); + } + break; + } + index++; + } + } + PROCESS_SWITCH(DeuteronInTriggeredEvents, processMC, "MC analysis", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From ed2e880a0ffac94cebe2953d10b29c645dc805eb Mon Sep 17 00:00:00 2001 From: Lieuwe <153300723+Lolle2001@users.noreply.github.com> Date: Tue, 19 May 2026 11:37:51 +0200 Subject: [PATCH 226/449] [PWGJE] Update to `jetD0AngSubstructure.cxx` to include Monte Carlo calculations. (#16002) Co-authored-by: Copilot --- PWGJE/Tasks/jetD0AngSubstructure.cxx | 939 ++++++++++++++++++++++++--- 1 file changed, 842 insertions(+), 97 deletions(-) diff --git a/PWGJE/Tasks/jetD0AngSubstructure.cxx b/PWGJE/Tasks/jetD0AngSubstructure.cxx index 9650d7ea4bb..c8df1ac97dd 100644 --- a/PWGJE/Tasks/jetD0AngSubstructure.cxx +++ b/PWGJE/Tasks/jetD0AngSubstructure.cxx @@ -8,17 +8,23 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// -// \file JetD0AngSubstructure.cxx -// -// \brief Analysis task for the reconstruction and study of charged jets -// containing D_0 mesons in pp collisions. -// \inherited from D0 fragmentation and Ds -// \P. Dhankher + +/// \file jetD0AngSubstructure.cxx +/// +/// \brief Analysis task for the reconstruction and study of charged jets containing D_0 mesons in pp collisions. The code is partially inherited from hfFragmentationFunction.cxx. +/// +/// \author P. Dhankher +/// \author L.J. Huisman #include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +// +#include "PWGHF/Core/DecayChannels.h" + +#include "Common/Core/RecoDecay.h" #include #include @@ -31,13 +37,16 @@ #include #include +#include #include +#include + #include #include #include #include - +// using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -45,65 +54,279 @@ using namespace o2::framework::expressions; // Definition of a custom AOD table to store jet–D0 quantities namespace o2::aod { -namespace jet_obj -{ +/* // Jet-related quantities -DECLARE_SOA_COLUMN(JetHfDist, jetHfDist, float); -DECLARE_SOA_COLUMN(JetPt, jetPt, float); -DECLARE_SOA_COLUMN(JetEta, jetEta, float); -DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); -DECLARE_SOA_COLUMN(JetNConst, jetNConst, int); -DECLARE_SOA_COLUMN(JetAng, jetAng, float); +*/ + +DECLARE_SOA_COLUMN(ExpJetHfDist, expJetHfDist, float); +DECLARE_SOA_COLUMN(ExpJetPt, expJetPt, float); +DECLARE_SOA_COLUMN(ExpJetEta, expJetEta, float); +DECLARE_SOA_COLUMN(ExpJetPhi, expJetPhi, float); +DECLARE_SOA_COLUMN(ExpJetNConst, expJetNConst, int); +DECLARE_SOA_COLUMN(ExpJetAng, expJetAng, float); // D0 candidate quantities -DECLARE_SOA_COLUMN(HfPt, hfPt, float); -DECLARE_SOA_COLUMN(HfEta, hfEta, float); -DECLARE_SOA_COLUMN(HfPhi, hfPhi, float); -DECLARE_SOA_COLUMN(HfMass, hfMass, float); -DECLARE_SOA_COLUMN(HfY, hfY, float); +DECLARE_SOA_COLUMN(ExpHfZParallel, expHfZParallel, float); + +DECLARE_SOA_COLUMN(ExpHfPt, expHfPt, float); +DECLARE_SOA_COLUMN(ExpHfEta, expHfEta, float); +DECLARE_SOA_COLUMN(ExpHfPhi, expHfPhi, float); +DECLARE_SOA_COLUMN(ExpHfMass, expHfMass, float); +DECLARE_SOA_COLUMN(ExpHfY, expHfY, float); // ML scores -DECLARE_SOA_COLUMN(HfMlScore0, hfMlScore0, float); -DECLARE_SOA_COLUMN(HfMlScore1, hfMlScore1, float); -DECLARE_SOA_COLUMN(HfMlScore2, hfMlScore2, float); -} // namespace jet_obj +DECLARE_SOA_COLUMN(ExpHfMlScore0, expHfMlScore0, float); +DECLARE_SOA_COLUMN(ExpHfMlScore1, expHfMlScore1, float); +DECLARE_SOA_COLUMN(ExpHfMlScore2, expHfMlScore2, float); + +/* +// MCP quantities (Particle Level) +*/ +// Jets +DECLARE_SOA_COLUMN(McpJetHfDist, mcpJetHfDist, float); +DECLARE_SOA_COLUMN(McpJetPt, mcpJetPt, float); +DECLARE_SOA_COLUMN(McpJetEta, mcpJetEta, float); +DECLARE_SOA_COLUMN(McpJetPhi, mcpJetPhi, float); +DECLARE_SOA_COLUMN(McpJetNConst, mcpJetNConst, float); +DECLARE_SOA_COLUMN(McpJetAng, mcpJetAng, float); +// D0 candidates (Heavy Flavour) +DECLARE_SOA_COLUMN(McpHfZParallel, mcpHfZParallel, float); + +DECLARE_SOA_COLUMN(McpHfPt, mcpHfPt, float); +DECLARE_SOA_COLUMN(McpHfEta, mcpHfEta, float); +DECLARE_SOA_COLUMN(McpHfPhi, mcpHfPhi, float); +// DECLARE_SOA_COLUMN(HfMass,mcpHfMass, float); +DECLARE_SOA_COLUMN(McpHfY, mcpHfY, float); +DECLARE_SOA_COLUMN(McpHfPrompt, mcpHfPrompt, bool); +DECLARE_SOA_COLUMN(McpHfMatch, mcpHfMatch, bool); + +/* +// MCD quantities (Detector Level) +*/ +// Jets +DECLARE_SOA_COLUMN(McdJetHfDist, mcdJetHfDist, float); +DECLARE_SOA_COLUMN(McdJetPt, mcdJetPt, float); +DECLARE_SOA_COLUMN(McdJetEta, mcdJetEta, float); +DECLARE_SOA_COLUMN(McdJetPhi, mcdJetPhi, float); +DECLARE_SOA_COLUMN(McdJetNConst, mcdJetNConst, float); +DECLARE_SOA_COLUMN(McdJetAng, mcdJetAng, float); +// D0 candidates (Heavy Flavour) +DECLARE_SOA_COLUMN(McdHfZParallel, mcdHfZParallel, float); + +DECLARE_SOA_COLUMN(McdHfPt, mcdHfPt, float); +DECLARE_SOA_COLUMN(McdHfEta, mcdHfEta, float); +DECLARE_SOA_COLUMN(McdHfPhi, mcdHfPhi, float); +DECLARE_SOA_COLUMN(McdHfMass, mcdHfMass, float); +DECLARE_SOA_COLUMN(McdHfY, mcdHfY, float); +DECLARE_SOA_COLUMN(McdHfPrompt, mcdHfPrompt, bool); +DECLARE_SOA_COLUMN(McdHfMatch, mcdHfMatch, bool); +// Other +DECLARE_SOA_COLUMN(McdHfMatchedFrom, mcdHfMatchedFrom, int); +DECLARE_SOA_COLUMN(McdHfSelectedAs, mcdHfSelectedAs, int); +// ML scores +DECLARE_SOA_COLUMN(McdHfMlScore0, mcdHfMlScore0, float); +DECLARE_SOA_COLUMN(McdHfMlScore1, mcdHfMlScore1, float); +DECLARE_SOA_COLUMN(McdHfMlScore2, mcdHfMlScore2, float); + +/* // AOD table definition -DECLARE_SOA_TABLE(JetObjTable, "AOD", "JETOBJTABLE", - jet_obj::JetHfDist, - jet_obj::JetPt, - jet_obj::JetEta, - jet_obj::JetPhi, - jet_obj::JetNConst, - jet_obj::JetAng, - jet_obj::HfPt, - jet_obj::HfEta, - jet_obj::HfPhi, - jet_obj::HfMass, - jet_obj::HfY, - jet_obj::HfMlScore0, - jet_obj::HfMlScore1, - jet_obj::HfMlScore2); +*/ +DECLARE_SOA_TABLE(EXPJetObjTable, "AOD", "EXPJETOBJTABLE", + ExpJetHfDist, + ExpJetPt, + ExpJetEta, + ExpJetPhi, + ExpJetNConst, + ExpJetAng, + ExpHfZParallel, + ExpHfPt, + ExpHfEta, + ExpHfPhi, + ExpHfMass, + ExpHfY, + ExpHfMlScore0, + ExpHfMlScore1, + ExpHfMlScore2); +DECLARE_SOA_TABLE(MCPJetObjTable, "AOD", "MCPJETOBJTABLE", + McpJetHfDist, + McpJetPt, + McpJetEta, + McpJetPhi, + McpJetNConst, + McpJetAng, + McpHfZParallel, + McpHfPt, + McpHfEta, + McpHfPhi, + McpHfY, + McpHfPrompt, + McpHfMatch); +DECLARE_SOA_TABLE(MCDJetObjTable, "AOD", "MCDJETOBJTABLE", + McdJetHfDist, + McdJetPt, + McdJetEta, + McdJetPhi, + McdJetNConst, + McdJetAng, + McdHfZParallel, + McdHfPt, + McdHfEta, + McdHfPhi, + McdHfMass, + McdHfY, + McdHfPrompt, + McdHfMatch, + McdHfMlScore0, + McdHfMlScore1, + McdHfMlScore2, + McdHfMatchedFrom, + McdHfSelectedAs); +DECLARE_SOA_TABLE(MatchJetDistanceTable, "AOD", "MATCHTABLE", + McpJetHfDist, + McpJetPt, + McpJetEta, + McpJetPhi, + McpJetNConst, + McpJetAng, + McpHfZParallel, + McpHfPt, + McpHfEta, + McpHfPhi, + McpHfY, + McpHfPrompt, + McdJetHfDist, + McdJetPt, + McdJetEta, + McdJetPhi, + McdJetNConst, + McdJetAng, + McdHfZParallel, + McdHfPt, + McdHfEta, + McdHfPhi, + McdHfMass, + McdHfY, + McdHfPrompt, + McdHfMlScore0, + McdHfMlScore1, + McdHfMlScore2, + McdHfMatchedFrom, + McdHfSelectedAs); + } // namespace o2::aod + +// Helps to avoid typos in histogram names when using the "HIST" macro +/* +hf(l): Heavy flavour +ex(p): Experimental data (detector level) +mcd: Monte Carlo data (detector level) +mcp: Monte Carlo data (particle level) +*/ +namespace histnames +{ + +/* +// Experimental Data (analyseDataChargedSubstructure) +*/ +constexpr const char* ExCol = "exCol"; // Collision Counter +constexpr const char* ExJet = "exJet"; // Jet Counter +constexpr const char* ExJetPt = "exJetPt"; // Jet pT +constexpr const char* ExJetEta = "exJetEta"; // Jet eta +constexpr const char* ExJetPhi = "exJetPhi"; // Jet phi +constexpr const char* ExJetAng = "exJetAng"; // Jet angularity +constexpr const char* ExJetProj = "exJetProj"; // Projection of HF candidate momentum on jet axis +constexpr const char* ExJetDist = "exJetDist"; // Jet–HF candidate angular distance +constexpr const char* ExJetDistProj = "exJetDistProj"; // Jet–HF candidate distance vs projection +constexpr const char* ExHflPt = "exHflPt"; // HF candidate pT +constexpr const char* ExHflMass = "exHflMass"; // HF candidate mass +constexpr const char* ExHflEta = "exHflEta"; // HF candidate eta +constexpr const char* ExHflPhi = "exHflPhi"; // HF candidate phi +/* +// Monte Carlo Data Efficiency (analyseMonteCarloEfficiency) +*/ +constexpr const char* McEffCol = "mcEffCol"; // Collision Counter +constexpr const char* McEffJet = "mcEffJet"; // Jet Counter +constexpr const char* McEffDetJetPt = "mcEffDetJetPt"; // Detector level jet pT +constexpr const char* McEffDetJetEta = "mcEffDetJetEta"; // Detector level jet eta +constexpr const char* McEffDetJetPhi = "mcEffDetJetPhi"; // Detector level jet phi +constexpr const char* McEffDetJetAng = "mcEffDetJetAng"; // Detector level jet angularity +constexpr const char* McEffDetHflPt = "mcEffDetHflPt"; // Detector level HF candidate pT +constexpr const char* McEffDetHflMass = "mcEffDetHflMass"; // Detector level HF candidate mass +constexpr const char* McEffDetHflEta = "mcEffDetHflEta"; // Detector level HF candidate eta +constexpr const char* McEffDetHflPhi = "mcEffDetHflPhi"; // Detector level HF candidate phi +constexpr const char* McEffParJetPt = "mcEffParJetPt"; // Particle level jet pT +constexpr const char* McEffParJetEta = "mcEffParJetEta"; // Particle level jet eta +constexpr const char* McEffParJetPhi = "mcEffParJetPhi"; // Particle level jet phi +constexpr const char* McEffParJetAng = "mcEffParJetAng"; // Particle level jet angularity +constexpr const char* McEffParHflPt = "mcEffParHflPt"; // Particle level HF candidate pT +// constexpr const char* McEffpar_hfl_mass = "mcEffpar_hfl_mass"; // Particle level HF candidate mass -> PDG value +constexpr const char* McEffParHflEta = "mcEffParHflEta"; // Particle level HF candidate eta +constexpr const char* McEffParHflPhi = "mcEffParHflPhi"; // Particle level HF candidate phi +/* +// Monte Carlo Data Matching (analyseMonteCarlo) +*/ +constexpr const char* McCol = "mcCol"; // Collision Counter +constexpr const char* McJet = "mcJet"; // Jet Counter +constexpr const char* McDetJetPt = "mcDetJetPt"; // Detector level jet pT +constexpr const char* McDetJetEta = "mcDetJetEta"; // Detector level jet eta +constexpr const char* McDetJetPhi = "mcDetJetPhi"; // Detector level jet phi +constexpr const char* McDetJetAng = "mcDetJetAng"; // Detector level jet angularity +constexpr const char* McDetHflPt = "mcDetHflPt"; // Detector level HF candidate pT (matched) +constexpr const char* McDetHflMass = "mcDetHflMass"; // Detector level HF candidate mass (matched) +constexpr const char* McDetHflEta = "mcDetHflEta"; // Detector level HF candidate eta (matched) +constexpr const char* McDetHflPhi = "mcDetHflPhi"; // Detector level HF candidate phi (matched) +// constexpr const char* McParJet_pt = "mcParJet_pt"; // Particle level jet pT +// constexpr const char* McParJet_eta = "mcParJet_eta"; // Particle level jet eta +// constexpr const char* McParJet_phi = "mcParJet_phi"; // Particle level jet phi +// constexpr const char* McParJet_ang = "mcParJet_ang"; // Particle level jet angularity +// constexpr const char* McParHfl_pt = "mcParHfl_pt"; // Particle level HF candidate pT +// constexpr const char* McParHfl_mass = "mcParHfl_mass"; // Particle level HF candidate mass -> PDG value +// constexpr const char* mc_par_hfl_eta = "mc_par_hfl_eta"; // Particle level HF candidate eta +// constexpr const char* mc_par_hfl_phi = "mc_par_hfl_phi"; // Particle level HF candidate phi + +} // namespace histnames + +consteval float getValFromBin(int bin) +{ + return static_cast(bin) - 0.5f; +} + +enum BinExpColCntr { AllCollisions = 1, + Sel8ZCut = 2 }; + +enum BinExpJetCntr { ChargedJets = 1 }; +enum BinMCColCntr { All = 1, + ZCut = 2, + Matched = 3, + MatchedSel8ZCut = 4 }; + +enum BinMCJetCntr { DetectorLevelJetInMCCollision = 1, + ParticleLevelJetInMCCollision = 2, + DetectorLevelJetWithMatchedCandidate = 3, + ParticleLevelJetWithMatchedCandidate = 4 +}; + struct JetD0AngSubstructure { - /** - * Histogram registry - * - * Contains: - * - Event and track histograms - * - Jet kinematic distributions - * - D0–jet substructure observables - */ - HistogramRegistry registry{"registry", - {{"h_collision_counter", "# of collisions;", {HistType::kTH1F, {{2, 0., 2.}}}}, - {"h_jet_counter", ";# of D^{0} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, - {"h_d0_jet_projection", ";z^{D^{0},jet}_{||};dN/dz^{D^{0},jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}}, - {"h_d0_jet_distance_vs_projection", ";#DeltaR_{D^{0},jet};z^{D^{0},jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}}, - {"h_d0_jet_distance", ";#DeltaR_{D^{0},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}}, - {"h_d0_jet_pt", ";p_{T,D^{0} jet};dN/dp_{T,D^{0} jet}", {HistType::kTH1F, {{200, 0., 10.}}}}, - {"h_d0_jet_eta", ";#eta_{T,D^{0} jet};dN/d#eta_{D^{0} jet}", {HistType::kTH1F, {{250, -5., 5.}}}}, - {"h_d0_jet_phi", ";#phi_{T,D^{0} jet};dN/d#phi_{D^{0} jet}", {HistType::kTH1F, {{250, -10., 10.}}}}, - {"h_d0_mass", ";m_{D^{0}});dN/dm_{D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}}, - {"h_d0_eta", ";#eta_{D^{0}});dN/d#eta_{D_{}}", {HistType::kTH1F, {{250, -5., 5.}}}}, - {"h_d0_phi", ";#phi_{D^{0}});dN/d#phi_{D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}}, - {"h_d0_ang", ";#lambda_{#kappa}^{#alpha};counts", {HistType::kTH1F, {{100, 0., 1.}}}}}}; + + // Output table producer + Produces objJetTable; + Produces mcdJetTable; + Produces mcpJetTable; + Produces matchJetTable; + // + using JetChargedTableD0 = soa::Join; + // MC Matching Tables + using JetD0MCDTable = soa::Join; + using JetD0MCPTable = soa::Join; + // Type Aliases for the constituent jets in the table (to be used for + // angularity calculation) + using JetD0MCDTableConstituent = JetD0MCDTable::iterator; + using JetD0MCPTableConstituent = JetD0MCPTable::iterator; + // Slices for access to proper HF MCD jet collision that is associated to + // MCCollision + PresliceUnsorted collisionsPerMCCollisionPreslice = aod::jmccollisionlb::mcCollisionId; + Preslice d0MCDJetsPerEXPCollisionPreslice = aod::jet::collisionId; + Preslice d0MCPJetsPerMCCollisionPreslice = aod::jet::mcCollisionId; + + HistogramRegistry registry{"registry", {}}; // Configurables Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -119,83 +342,605 @@ struct JetD0AngSubstructure { std::vector eventSelectionBits; int trackSelection = -1; - // Output table producer - Produces ObjJetTable; - - float angularity; - void init(o2::framework::InitContext&) { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + addHistograms(); } + void addHistograms() + { + /* + // Experimental Data Histograms + */ + // Definitions + registry.add(histnames::ExCol, "N_{coll};", {HistType::kTH1F, {{2, 0., 2.}}}); + registry.add(histnames::ExJet, "N_{jet};", {HistType::kTH1F, {{1, 0., 1.0}}}); + registry.add(histnames::ExJetPt, ";p_{T,jet};dN/dp_{T,jet}", {HistType::kTH1F, {{1000, 0., 50.}}}); + registry.add(histnames::ExJetEta, ";#eta_{jet};dN/d#eta_{jet}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::ExJetPhi, ";#phi_{jet};dN/d#phi_{jet}", {HistType::kTH1F, {{250, -10., 10.}}}); + registry.add(histnames::ExJetAng, ";angularity_{jet};dN/d(angularity)", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::ExJetDist, ";#DeltaR_{D^{0},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::ExJetDistProj, ";#DeltaR_{D^{0},jet};z^{D^{0},jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}); + registry.add(histnames::ExJetProj, ";z^{D^{0},jet}_{||};dN/dz^{D^{0},jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::ExHflPt, ";p_{T,D^{0}};dN/dp_{T,D^{0}}", {HistType::kTH1F, {{200, 0., 10.}}}); + registry.add(histnames::ExHflMass, ";m_{D^{0}};dN/dm_{D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::ExHflEta, ";#eta_{D^{0}};dN/d#eta_{D^{0}}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::ExHflPhi, ";#phi_{D^{0}};dN/d#phi_{D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}); + // Labels + auto expCollisionCounter = registry.get(HIST(histnames::ExCol)); + expCollisionCounter->GetXaxis()->SetBinLabel(BinExpColCntr::AllCollisions, "all"); + expCollisionCounter->GetXaxis()->SetBinLabel(BinExpColCntr::Sel8ZCut, "sel8 + zcut"); + + auto expJetCounter = registry.get(HIST(histnames::ExJet)); + expJetCounter->GetXaxis()->SetBinLabel(BinExpJetCntr::ChargedJets, "Charged jets with D0"); + /* + // Monte Carlo Data Efficiency Histograms + */ + // Definitions + registry.add(histnames::McEffCol, "N_{coll};", {HistType::kTH1F, {{4, 0., 4.0}}}); + registry.add(histnames::McEffJet, "N_{jet};", {HistType::kTH1F, {{4, 0., 4.0}}}); + registry.add(histnames::McEffDetJetPt, ";p_{T,det jet};dN/dp_{T,det jet}", {HistType::kTH1F, {{1000, 0., 50.}}}); + registry.add(histnames::McEffDetJetEta, ";#eta_{det jet};dN/d#eta_{det jet}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::McEffDetJetPhi, ";#phi_{det jet};dN/d#phi_{det jet}", {HistType::kTH1F, {{250, -10., 10.}}}); + registry.add(histnames::McEffDetJetAng, ";angularity_{det jet};dN/d(angularity)", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::McEffDetHflPt, ";p_{T,det D^{0}};dN/dp_{T,det D^{0}}", {HistType::kTH1F, {{200, 0., 10.}}}); + registry.add(histnames::McEffDetHflMass, ";m_{det D^{0}};dN/dm_{det D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::McEffDetHflEta, ";#eta_{det D^{0}};dN/d#eta_{det D^{0}}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::McEffDetHflPhi, ";#phi_{det D^{0}};dN/d#phi_{det D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}); + // Labels + auto mcCollisionCounter = registry.get(HIST(histnames::McEffCol)); + mcCollisionCounter->GetXaxis()->SetBinLabel(BinMCColCntr::All, "mccollisions"); + mcCollisionCounter->GetXaxis()->SetBinLabel(BinMCColCntr::ZCut, "z_cut"); + mcCollisionCounter->GetXaxis()->SetBinLabel(BinMCColCntr::Matched, "collisions"); + mcCollisionCounter->GetXaxis()->SetBinLabel(BinMCColCntr::MatchedSel8ZCut, "sel8"); + + auto jetCounter = registry.get(HIST(histnames::McEffJet)); + jetCounter->GetXaxis()->SetBinLabel(BinMCJetCntr::ParticleLevelJetInMCCollision, "particle level"); + jetCounter->GetXaxis()->SetBinLabel(BinMCJetCntr::DetectorLevelJetInMCCollision, "detector level"); + jetCounter->GetXaxis()->SetBinLabel(BinMCJetCntr::DetectorLevelJetWithMatchedCandidate, "particle matched jets"); + jetCounter->GetXaxis()->SetBinLabel(BinMCJetCntr::ParticleLevelJetWithMatchedCandidate, "detector matched jets"); + /* + // Monte Carlo Data Histograms + */ + registry.add(histnames::McCol, "N_{coll};", {HistType::kTH1F, {{4, 0., 4.0}}}); + registry.add(histnames::McJet, "N_{jet};", {HistType::kTH1F, {{4, 0., 4.0}}}); + registry.add(histnames::McDetJetPt, ";p_{T,det jet};dN/dp_{T,det jet}", {HistType::kTH1F, {{1000, 0., 50.}}}); + registry.add(histnames::McDetJetEta, ";#eta_{det jet};dN/d#eta_{det jet}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::McDetJetPhi, ";#phi_{det jet};dN/d#phi_{det jet}", {HistType::kTH1F, {{250, -10., 10.}}}); + registry.add(histnames::McDetJetAng, ";angularity_{det jet};dN/d(angularity)", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::McDetHflPt, ";p_{T,det D^{0}};dN/dp_{T,det D^{0}}", {HistType::kTH1F, {{200, 0., 10.}}}); + registry.add(histnames::McDetHflMass, ";m_{det D^{0}};dN/dm_{det D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add(histnames::McDetHflEta, ";#eta_{det D^{0}};dN/d#eta_{det D^{0}}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add(histnames::McDetHflPhi, ";#phi_{det D^{0}};dN/d#phi_{det D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}); + // Labels + auto mcCollisionCounter2 = registry.get(HIST(histnames::McCol)); + mcCollisionCounter2->GetXaxis()->SetBinLabel(BinMCColCntr::All, "mccollisions"); + mcCollisionCounter2->GetXaxis()->SetBinLabel(BinMCColCntr::ZCut, "z_cut"); + mcCollisionCounter2->GetXaxis()->SetBinLabel(BinMCColCntr::Matched, "collisions"); + mcCollisionCounter2->GetXaxis()->SetBinLabel(BinMCColCntr::MatchedSel8ZCut, "sel8"); + + auto jetCounter2 = registry.get(HIST(histnames::McJet)); + jetCounter2->GetXaxis()->SetBinLabel(BinMCJetCntr::DetectorLevelJetInMCCollision, "detector level"); + jetCounter2->GetXaxis()->SetBinLabel(BinMCJetCntr::ParticleLevelJetInMCCollision, "particle level"); + jetCounter2->GetXaxis()->SetBinLabel(BinMCJetCntr::DetectorLevelJetWithMatchedCandidate, "particle matched jets"); + jetCounter2->GetXaxis()->SetBinLabel(BinMCJetCntr::ParticleLevelJetWithMatchedCandidate, "detector matched jets"); + }; + template - void jetCalculateAngularity(T const& jet, U const& /*tracks*/) + float jetCalculateAngularityEXP(T const& jet, U const& /*tracks*/) { - angularity = 0.0; - for (auto& constituent : jet.template tracks_as()) { - angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent) / (jet.r() / 100.f), alpha); + float tAngularity = 0.0; + for (const auto& constituent : jet.template tracks_as()) { + tAngularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent) / (jet.r() / 100.f), alpha); } - angularity /= std::pow(jet.pt(), kappa); + tAngularity /= std::pow(jet.pt(), kappa); + return tAngularity; } - void processDataChargedSubstructure(aod::JetCollision const& collision, - soa::Join const& jets, - aod::CandidatesD0Data const&, aod::JetTracks const& tracks) + template + float jetCalculateAngularityMCD(JetTableMCDConstituent const& jet, aod::JetTracks const& tracks) { - // apply event selection and fill histograms for sanity check - registry.fill(HIST("h_collision_counter"), 0.5); + float a = 0.f; + for (const auto& id : jet.tracksIds()) { + const auto trk = tracks.iteratorAt(id); + a += std::pow(trk.pt(), kappa) * std::pow(jetutilities::deltaR(jet, trk) / (jet.r() / 100.f), alpha); + } + return a / std::pow(jet.pt(), kappa); + } + + template + float jetCalculateAngularityMCP(JetTableMCPConstituent const& jet, aod::JetParticles const& particles) + { + float a = 0.f; + for (const auto& id : jet.tracksIds()) { + const auto p = particles.iteratorAt(id); + a += std::pow(p.pt(), kappa) * std::pow(jetutilities::deltaR(jet, p) / (jet.r() / 100.f), alpha); + } + return a / std::pow(jet.pt(), kappa); + } + template + void analyseDataChargedSubstructure(aod::JetCollision const& collision, + JetChargedTable const& jets, + CandidatesTable const& /*candidates*/, + aod::JetTracks const& tracks) + { + // apply event selection and fill histograms for sanity check + registry.fill(HIST(histnames::ExCol), getValFromBin(BinExpColCntr::AllCollisions)); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { return; } - registry.fill(HIST("h_collision_counter"), 1.5); + registry.fill(HIST(histnames::ExCol), getValFromBin(BinExpColCntr::Sel8ZCut)); // Loop over jets containing D0 candidates for (const auto& jet : jets) { // number of charged jets with D0 - registry.fill(HIST("h_jet_counter"), 0.5); + registry.fill(HIST(histnames::ExJet), getValFromBin(BinExpJetCntr::ChargedJets)); // obtaining jet 3-vector TVector3 jetVector(jet.px(), jet.py(), jet.pz()); // Loop over D0 candidates associated to the jet - for (const auto& d0Candidate : jet.candidates_as()) { + for (const auto& d0Candidate : jet.template candidates_as()) { // obtaining jet 3-vector TVector3 d0Vector(d0Candidate.px(), d0Candidate.py(), d0Candidate.pz()); - // calculating fraction of the jet momentum carried by the D0 along the direction of the jet axis + // calculating fraction of the jet momentum carried by the D0 along the + // direction of the jet axis double zParallel = (jetVector * d0Vector) / (jetVector * jetVector); // calculating angular distance in eta-phi plane double axisDistance = jetutilities::deltaR(jet, d0Candidate); - jetCalculateAngularity(jet, tracks); + float angularity = jetCalculateAngularityEXP(jet, tracks); // filling histograms - registry.fill(HIST("h_d0_jet_projection"), zParallel); - registry.fill(HIST("h_d0_jet_distance_vs_projection"), axisDistance, zParallel); - registry.fill(HIST("h_d0_jet_distance"), axisDistance); - registry.fill(HIST("h_d0_jet_pt"), jet.pt()); - registry.fill(HIST("h_d0_jet_eta"), jet.eta()); - registry.fill(HIST("h_d0_jet_phi"), jet.phi()); - registry.fill(HIST("h_d0_mass"), d0Candidate.m()); - registry.fill(HIST("h_d0_eta"), d0Candidate.eta()); - registry.fill(HIST("h_d0_phi"), d0Candidate.phi()); - registry.fill(HIST("h_d0_ang"), angularity); // add more axis + registry.fill(HIST(histnames::ExJetProj), zParallel); + registry.fill(HIST(histnames::ExJetDistProj), axisDistance, zParallel); + registry.fill(HIST(histnames::ExJetDist), axisDistance); + registry.fill(HIST(histnames::ExJetPt), jet.pt()); + registry.fill(HIST(histnames::ExJetEta), jet.eta()); + registry.fill(HIST(histnames::ExJetPhi), jet.phi()); + registry.fill(HIST(histnames::ExJetAng), angularity); + registry.fill(HIST(histnames::ExHflPt), d0Candidate.pt()); + registry.fill(HIST(histnames::ExHflMass), d0Candidate.m()); + registry.fill(HIST(histnames::ExHflEta), d0Candidate.eta()); + registry.fill(HIST(histnames::ExHflPhi), d0Candidate.phi()); // add more axis // filling table - ObjJetTable(axisDistance, - jet.pt(), jet.eta(), jet.phi(), jet.tracks_as().size(), angularity, - d0Candidate.pt(), d0Candidate.eta(), d0Candidate.phi(), d0Candidate.m(), d0Candidate.y(), d0Candidate.mlScores()[0], d0Candidate.mlScores()[1], d0Candidate.mlScores()[2]); + objJetTable(axisDistance, + jet.pt(), + jet.eta(), + jet.phi(), + jet.template tracks_as().size(), + angularity, + zParallel, + d0Candidate.pt(), + d0Candidate.eta(), + d0Candidate.phi(), + d0Candidate.m(), + d0Candidate.y(), + d0Candidate.mlScores()[0], + d0Candidate.mlScores()[1], + d0Candidate.mlScores()[2]); - break; // get out of candidates' loop after first HF particle is found in jet + break; // get out of candidates' loop after first HF particle is found + // in jet } // end of D0 candidates loop } // end of jets loop } // end of process function - PROCESS_SWITCH(JetD0AngSubstructure, processDataChargedSubstructure, "charged HF jet substructure", false); + + template + void analyseMonteCarloEfficiency(MCDJetsPerMCCollissionPreslice const& jetmcdpreslice, + MCPJetsPerMCCollissionPreslice const& jetmcppreslice, + aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetTableMCD const& mcdjets, + JetTableMCP const& mcpjets, + CandidatesMCD const& /*mcdCandidates*/, + CandidatesMCP const& /*mcpCandidates*/, + aod::JetTracks const& tracks, + aod::JetParticles const& particles) + { + for (const auto& mccollision : mccollisions) { + + registry.fill(HIST(histnames::McEffCol), getValFromBin(BinMCColCntr::All)); + // skip collisions outside of |z| < vertexZCut + if (std::abs(mccollision.posZ()) > vertexZCut) { + continue; + } + registry.fill(HIST(histnames::McEffCol), getValFromBin(BinMCColCntr::ZCut)); + + // reconstructed collisions associated to same mccollision + const auto collisionsPerMCCollision = collisions.sliceBy(collisionsPerMCCollisionPreslice, mccollision.globalIndex()); + for (const auto& collision : collisionsPerMCCollision) { + + registry.fill(HIST(histnames::McEffCol), getValFromBin(BinMCColCntr::Matched)); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || + !(std::abs(collision.posZ()) < vertexZCut)) { + continue; + } + registry.fill(HIST(histnames::McEffCol), getValFromBin(BinMCColCntr::MatchedSel8ZCut)); + + // d0 detector level jets associated to the current same collision + const auto d0mcdJetsPerCollision = mcdjets.sliceBy(jetmcdpreslice, collision.globalIndex()); + for (const auto& mcdjet : d0mcdJetsPerCollision) { + + registry.fill( + HIST(histnames::McEffJet), getValFromBin(BinMCJetCntr::DetectorLevelJetInMCCollision)); + + // obtain leading HF candidate in jet + auto mcdd0cand = mcdjet.template candidates_first_as(); + + if (mcdjet.has_matchedJetCand()) { + registry.fill( + HIST(histnames::McEffJet), getValFromBin(BinMCJetCntr::DetectorLevelJetWithMatchedCandidate)); + } + + // reflection information for storage: D0 = +1, D0bar = -1, neither = + // 0 + int matchedFrom = 0; + int decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; + int selectedAs = 0; + + if (mcdd0cand.flagMcMatchRec() == decayChannel) { // matched to D0 on truth level + matchedFrom = 1; + } else if (mcdd0cand.flagMcMatchRec() == -decayChannel) { // matched to D0bar on truth level + matchedFrom = -1; + } + // bitwise AND operation: Checks whether BIT(i) is set, regardless of + // other bits + if (mcdd0cand.candidateSelFlag() & BIT(0)) { // CandidateSelFlag == BIT(0) -> selected as D0 + selectedAs = 1; + } else if (mcdd0cand.candidateSelFlag() & BIT(1)) { // CandidateSelFlag == BIT(1) -> selected as D0bar + selectedAs = -1; + } + + TVector3 mcdjetvector(mcdjet.px(), mcdjet.py(), mcdjet.pz()); + TVector3 mcdcandvector(mcdd0cand.px(), mcdd0cand.py(), mcdd0cand.pz()); + + float mcdzparallel = (mcdjetvector * mcdcandvector) / (mcdjetvector * mcdjetvector); + + float angularity = jetCalculateAngularityMCD(mcdjet, tracks); + registry.fill(HIST(histnames::McEffDetJetPt), mcdjet.pt()); + registry.fill(HIST(histnames::McEffDetJetEta), mcdjet.eta()); + registry.fill(HIST(histnames::McEffDetJetPhi), mcdjet.phi()); + registry.fill(HIST(histnames::McEffDetJetAng), angularity); + // Particle Histgrams + registry.fill(HIST(histnames::McEffDetHflPt), mcdd0cand.pt()); + registry.fill(HIST(histnames::McEffDetHflMass), mcdd0cand.m()); + registry.fill(HIST(histnames::McEffDetHflEta), mcdd0cand.eta()); + registry.fill(HIST(histnames::McEffDetHflPhi), mcdd0cand.phi()); + + mcdJetTable( + jetutilities::deltaR(mcdjet, mcdd0cand), + mcdjet.pt(), + mcdjet.eta(), + mcdjet.phi(), + mcdjet.template tracks_as().size(), // detector level jet + angularity, + mcdzparallel, + mcdd0cand.pt(), + mcdd0cand.eta(), mcdd0cand.phi(), + mcdd0cand.m(), mcdd0cand.y(), + (mcdd0cand.originMcRec() == RecoDecay::OriginType::Prompt), // detector level D0 candidate + mcdjet.has_matchedJetCand(), + mcdd0cand.mlScores()[0], + mcdd0cand.mlScores()[1], + mcdd0cand.mlScores()[2], // // Machine Learning PID scores: background, prompt, non-prompt + + matchedFrom, + selectedAs); // D0 = +1, D0bar = -1, neither = 0 + } + } // end of reconstructed collisions loop (detector level mc collisions + // matching with real collisions) + + // d0 particle level jets associated to same mccollision + const auto d0mcpJetsPerMCCollision = mcpjets.sliceBy(jetmcppreslice, mccollision.globalIndex()); + for (const auto& mcpjet : d0mcpJetsPerMCCollision) { + + registry.fill(HIST(histnames::McEffJet), getValFromBin(BinMCJetCntr::ParticleLevelJetInMCCollision)); + + // obtain leading HF particle in jet + auto mcpd0cand = mcpjet.template candidates_first_as(); + + if (mcpjet.has_matchedJetCand()) { + registry.fill(HIST(histnames::McEffJet), getValFromBin(BinMCJetCntr::ParticleLevelJetWithMatchedCandidate)); + } + TVector3 mcpjetvector(mcpjet.px(), mcpjet.py(), mcpjet.pz()); + TVector3 mcpcandvector(mcpd0cand.px(), mcpd0cand.py(), mcpd0cand.pz()); + + float mcpzparallel = (mcpjetvector * mcpcandvector) / (mcpjetvector * mcpjetvector); + + float angularity = jetCalculateAngularityMCP(mcpjet, particles); + + registry.fill(HIST(histnames::McEffParJetPt), mcpjet.pt()); + registry.fill(HIST(histnames::McEffParJetEta), mcpjet.eta()); + registry.fill(HIST(histnames::McEffParJetPhi), mcpjet.phi()); + registry.fill(HIST(histnames::McEffParJetAng), angularity); + // Particle Histgrams + registry.fill(HIST(histnames::McEffParHflPt), mcpd0cand.pt()); + + registry.fill(HIST(histnames::McEffParHflEta), mcpd0cand.eta()); + registry.fill(HIST(histnames::McEffParHflPhi), mcpd0cand.phi()); + // store data in MC detector level table (calculate angular distance in + // eta-phi plane on the fly) + mcpJetTable(jetutilities::deltaR(mcpjet, mcpd0cand), + mcpjet.pt(), + mcpjet.eta(), + mcpjet.phi(), + mcpjet.template tracks_as().size(), // particle level jet + angularity, + mcpzparallel, + mcpd0cand.pt(), + mcpd0cand.eta(), + mcpd0cand.phi(), + // mcpd0cand.m(), + mcpd0cand.y(), + (mcpd0cand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level D0 + mcpjet.has_matchedJetCand()); + } // End of particle level jets loop, related to detector level collisions + // and jets. + } + } + + template + void analyseMonteCarlo(MCPJetsPerMCCollissionPreslice jetmcpreslice, + aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetTableMCD const& /*mcdjets*/, + JetTableMCP const& mcpjets, + CandidatesMCD const& /*mcdCandidates*/, + CandidatesMCP const& /*mcpCandidates*/, + aod::JetTracks const& jettracks, + aod::JetParticles const& jetparticles) + { + for (const auto& mccollision : mccollisions) { + registry.fill(HIST(histnames::McCol), getValFromBin(BinMCColCntr::All)); + // skip collisions outside of |z| < vertexZCut + if (std::abs(mccollision.posZ()) > vertexZCut) { + continue; + } + registry.fill(HIST(histnames::McCol), getValFromBin(BinMCColCntr::ZCut)); + + // hf particle level jets associated to same mccollision + const JetD0MCPTable mcpJetsPerMCCollision = mcpjets.sliceBy(jetmcpreslice, mccollision.globalIndex()); + for (const auto& mcpjet : mcpJetsPerMCCollision) { + + registry.fill(HIST(histnames::McJet), getValFromBin(BinMCJetCntr::ParticleLevelJetInMCCollision)); + + // obtain leading HF particle in jet + auto mcpcand = mcpjet.template candidates_first_as(); + + TVector3 mcpjetvector(mcpjet.px(), mcpjet.py(), mcpjet.pz()); + TVector3 mcpcandvector(mcpcand.px(), mcpcand.py(), mcpcand.pz()); + float mcpzparallel = (mcpjetvector * mcpcandvector) / (mcpjetvector * mcpjetvector); + + if (mcpjet.has_matchedJetCand()) { + registry.fill(HIST(histnames::McJet), getValFromBin(BinMCJetCntr::ParticleLevelJetWithMatchedCandidate)); + + // loop over detector level matched to current particle level + for (const auto& mcdjet : mcpjet.template matchedJetCand_as()) { + registry.fill(HIST(histnames::McJet), getValFromBin(BinMCJetCntr::DetectorLevelJetWithMatchedCandidate)); + + // apply collision sel8 selection on detector level jet's collision + const auto& collision = collisions.iteratorAt(mcdjet.collisionId()); + registry.fill(HIST(histnames::McCol), getValFromBin(BinMCColCntr::Matched)); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { + continue; + } + registry.fill(HIST(histnames::McCol), getValFromBin(BinMCColCntr::MatchedSel8ZCut)); + + // obtain leading HF candidate in jet + auto mcdcand = mcdjet.template candidates_first_as(); + + // reflection information for storage: HF = +1, HFbar = -1, neither + // = 0 + int matchedFrom = 0; + int decayChannel = 0; + if (jethfutilities::isD0Table()) { + decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; + } else if (jethfutilities::isLcTable()) { + decayChannel = o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; + } + int selectedAs = 0; + + if (mcdcand.flagMcMatchRec() == decayChannel) { // matched to HF on truth level + matchedFrom = 1; + } else if (mcdcand.flagMcMatchRec() == -decayChannel) { // matched to HFbar on truth level + matchedFrom = -1; + } + // bitwise AND operation: Checks whether BIT(i) is set, regardless + // of other bits + if (mcdcand.candidateSelFlag() & BIT(0)) { // CandidateSelFlag == BIT(0) -> selected as HF + selectedAs = 1; + } else if (mcdcand.candidateSelFlag() & BIT(1)) { // CandidateSelFlag == BIT(1) -> selected as + // HFbar + selectedAs = -1; + } + + TVector3 mcdjetvector(mcdjet.px(), mcdjet.py(), mcdjet.pz()); + TVector3 mcdcandvector(mcdcand.px(), mcdcand.py(), mcdcand.pz()); + + float mcdzparallel = (mcdjetvector * mcdcandvector) / (mcdjetvector * mcdjetvector); + + float mcpAngularity = jetCalculateAngularityMCP(mcpjet, jetparticles); + float mcdAngularity = jetCalculateAngularityMCD(mcdjet, jettracks); + + // filling histograms + // registry.fill(HIST(histnames::h_exp_d0_jet_projection), + // zParallel); + // registry.fill(HIST(histnames::h_exp_d0_jet_distance_vs_projection), + // axisDistance, zParallel); + // registry.fill(HIST(histnames::h_exp_d0_jet_distance), + // axisDistance); registry.fill(HIST(histnames::h_exp_d0_jet_pt), + // jet.pt()); registry.fill(HIST(histnames::h_exp_d0_jet_eta), + // jet.eta()); registry.fill(HIST(histnames::h_exp_d0_jet_phi), + // jet.phi()); registry.fill(HIST(histnames::h_exp_d0_jet_ang), + // angularity); Jet Histograms + + registry.fill(HIST(histnames::McDetJetPt), mcdjet.pt()); + registry.fill(HIST(histnames::McDetJetEta), mcdjet.eta()); + registry.fill(HIST(histnames::McDetJetPhi), mcdjet.phi()); + registry.fill(HIST(histnames::McDetJetAng), mcdAngularity); + // Particle Histgrams + registry.fill(HIST(histnames::McDetHflPt), mcdcand.pt()); + registry.fill(HIST(histnames::McDetHflMass), mcdcand.m()); + registry.fill(HIST(histnames::McDetHflEta), mcdcand.eta()); + registry.fill(HIST(histnames::McDetHflPhi), mcdcand.phi()); // add more axis + + // store matched particle and detector level data in one single + // table (calculate angular distance in eta-phi plane on the fly) + matchJetTable(jetutilities::deltaR(mcpjet, mcpcand), + mcpjet.pt(), + mcpjet.eta(), + mcpjet.phi(), + mcpjet.template tracks_as().size(), // particle level jet + mcpAngularity, + mcpzparallel, + mcpcand.pt(), + mcpcand.eta(), + mcpcand.phi(), + mcpcand.y(), + (mcpcand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level HF + jetutilities::deltaR(mcdjet, mcdcand), + mcdjet.pt(), + mcdjet.eta(), + mcdjet.phi(), + mcdjet.template tracks_as().size(), // detector level jet + mcdAngularity, + mcdzparallel, + mcdcand.pt(), + mcdcand.eta(), + mcdcand.phi(), + mcdcand.m(), + mcdcand.y(), + (mcdcand.originMcRec() == RecoDecay::OriginType::Prompt), // detector level HF + mcdcand.mlScores()[0], + mcdcand.mlScores()[1], + mcdcand.mlScores()[2], // Machine Learning PID scores: background, prompt, non-prompt + matchedFrom, + selectedAs); // HF = +1, HFbar = -1, neither = 0 + } + } else { + // store matched particle and detector level data in one single table + // (calculate angular distance in eta-phi plane on the fly) + float mcpAngularity = jetCalculateAngularityMCP(mcpjet, jetparticles); + // float mcpAngularity = 0.; + matchJetTable(jetutilities::deltaR(mcpjet, mcpcand), + mcpjet.pt(), + mcpjet.eta(), + mcpjet.phi(), + mcpjet.template tracks_as().size(), // particle level jet + mcpAngularity, + mcpzparallel, + mcpcand.pt(), + mcpcand.eta(), + mcpcand.phi(), + mcpcand.y(), + (mcpcand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level HF + -2, + -2, + -2, + -2, + -2, + -2, // detector level jet + -2, + -2, + -2, + -2, + -2, + -2, + -2, // detector level HF + -2, + -2, + -2, // Machine Learning PID scores: background, prompt, non-prompt + -2, + -2); // HF = +1, HFbar = -1, neither = 0 + } + } // end of mcpjets loop + } // end of mccollisions loop + }; + + void processataChargedSubstructureD0(aod::JetCollision const& collision, + JetChargedTableD0 const& jets, + aod::CandidatesD0Data const& candidates, + aod::JetTracks const& tracks) + { + analyseDataChargedSubstructure(collision, jets, candidates, tracks); + } + + PROCESS_SWITCH(JetD0AngSubstructure, processataChargedSubstructureD0, "charged HF jet substructure", false); + + void processMonteCarloEfficiencyD0(aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetD0MCDTable const& mcdjets, + JetD0MCPTable const& mcpjets, + aod::CandidatesD0MCD const& mcdCandidates, + aod::CandidatesD0MCP const& mcpCandidates, + aod::JetTracks const& jettracks, + aod::JetParticles const& jetparticles) + { + analyseMonteCarloEfficiency, + Preslice, + JetD0MCDTable, + JetD0MCPTable, + aod::CandidatesD0MCD, + aod::CandidatesD0MCP>(d0MCDJetsPerEXPCollisionPreslice, + d0MCPJetsPerMCCollisionPreslice, + mccollisions, + collisions, + mcdjets, + mcpjets, + mcdCandidates, + mcpCandidates, + jettracks, + jetparticles); + } + + PROCESS_SWITCH(JetD0AngSubstructure, processMonteCarloEfficiencyD0, "non-matched and matched MC D0 and jets", false); + + void processMonteCarloD0(aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetD0MCDTable const& mcdjets, + JetD0MCPTable const& mcpjets, + aod::CandidatesD0MCD const& mcdCandidates, + aod::CandidatesD0MCP const& mcpCandidates, + aod::JetTracks const& jettracks, + aod::JetParticles const& jetparticles) + { + analyseMonteCarlo, + JetD0MCDTable, + JetD0MCPTable, + aod::CandidatesD0MCD, + aod::CandidatesD0MCP>(d0MCPJetsPerMCCollisionPreslice, + mccollisions, + collisions, + mcdjets, + mcpjets, + mcdCandidates, + mcpCandidates, + jettracks, + jetparticles); + } + + PROCESS_SWITCH(JetD0AngSubstructure, processMonteCarloD0, "Store all simulated D0 jets information with matched candidate (if any found)", false); }; // Workflow definition -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-d0-ang-substructure"})}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From bc1d3142313a0a08f2fc7da93d8d3580165cddbb Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 19 May 2026 13:10:26 +0200 Subject: [PATCH 227/449] [PWGLF] Remove jet area cut and use uniform area for UE estimate (#16285) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 77 ++++++------------------- 1 file changed, 18 insertions(+), 59 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index c03452e1684..8b863f01b08 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -132,7 +132,7 @@ struct JetMatching { struct AntinucleiInJets { - // Random engine + // Random engine (Mersenne Twister) std::mt19937 rng; std::uniform_int_distribution generateRandomNr{0, 1}; @@ -171,8 +171,7 @@ struct AntinucleiInJets { Configurable ptLeadingMin{"ptLeadingMin", 5.0, "pt Leading Min"}; Configurable rJet{"rJet", 0.4, "Jet resolution parameter R"}; Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; - Configurable applyAreaCut{"applyAreaCut", true, "apply area cut"}; - Configurable maxNormalizedJetArea{"maxNormalizedJetArea", 1.0, "area cut"}; + Configurable applyAreaCut{"applyAreaCut", false, "apply area cut A > f * pi R^2"}; Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; Configurable nSyst{"nSyst", 50, "number of systematic variations"}; Configurable nSubsamples{"nSubsamples", 50, "number of subsamples"}; @@ -1296,15 +1295,15 @@ struct AntinucleiInJets { continue; // Apply area cut if required - double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) - continue; - if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) + if (applyAreaCut && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; + // Fill histograms with jet effective area / piR^2 for normalization + registryData.fill(HIST("jetEffectiveAreaOverPiR2"), jet.area() / (PI * rJet * rJet)); + registryData.fill(HIST("jetArea"), jet.area()); + // Perpendicular cones - double coneRadius = std::sqrt(jet.area() / PI); TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); @@ -1312,10 +1311,6 @@ struct AntinucleiInJets { continue; } - // Fill histogram with jet effective area / piR^2 - registryData.fill(HIST("jetEffectiveAreaOverPiR2"), jet.area() / (PI * rJet * rJet)); - registryData.fill(HIST("jetArea"), jet.area()); - // Get jet constituents std::vector jetConstituents = jet.constituents(); @@ -1427,14 +1422,8 @@ struct AntinucleiInJets { double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Determine the maximum allowed distance from UE axes for particle selection - double maxConeRadius = coneRadius; - if (applyAreaCut) { - maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; - } - // Reject tracks that lie outside the maxConeRadius from both UE axes - if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) + if (deltaRUe1 > rJet && deltaRUe2 > rJet) continue; // Define variables @@ -1590,8 +1579,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + if (applyAreaCut && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; } @@ -1672,7 +1660,6 @@ struct AntinucleiInJets { // Jet properties and perpendicular cone std::vector jetConstituents = jet.constituents(); TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -1704,7 +1691,7 @@ struct AntinucleiInJets { double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) + if (deltaRUe1 > rJet && deltaRUe2 > rJet) continue; ptPerp = ptPerp + track.pt(); @@ -2136,10 +2123,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) - continue; - if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) + if (applyAreaCut && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -2181,7 +2165,6 @@ struct AntinucleiInJets { // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -2199,14 +2182,8 @@ struct AntinucleiInJets { double deltaPhiUe2 = getDeltaPhi(protonVec.Phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Determine the maximum allowed distance from UE axes for particle selection - double maxConeRadius = coneRadius; - if (applyAreaCut) { - maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; - } - // Reject tracks that lie outside the maxConeRadius from both UE axes - if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) + if (deltaRUe1 > rJet && deltaRUe2 > rJet) continue; // Fill normalization histogram @@ -2393,10 +2370,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) - continue; - if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) + if (applyAreaCut && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -2404,7 +2378,6 @@ struct AntinucleiInJets { registryMC.fill(HIST("recJets"), 0.5); // Set up two perpendicular cone axes for underlying event estimation - double coneRadius = std::sqrt(jet.area() / PI); TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); @@ -2550,14 +2523,8 @@ struct AntinucleiInJets { double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Determine the maximum allowed distance from UE axes for particle selection - double maxConeRadius = coneRadius; - if (applyAreaCut) { - maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; - } - // Reject tracks that lie outside the maxConeRadius from both UE axes - if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) + if (deltaRUe1 > rJet && deltaRUe2 > rJet) continue; // Particle identification using the ITS cluster size @@ -3753,8 +3720,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + if (applyAreaCut && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -3769,7 +3735,6 @@ struct AntinucleiInJets { // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -3791,14 +3756,8 @@ struct AntinucleiInJets { double deltaPhiUe2 = getDeltaPhi(chParticle.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Determine the maximum allowed distance from UE axes for particle selection - double maxConeRadius = coneRadius; - if (applyAreaCut) { - maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; - } - // Reject tracks that lie outside the maxConeRadius from both UE axes - if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) + if (deltaRUe1 > rJet && deltaRUe2 > rJet) continue; // Fill histograms for UE @@ -4121,7 +4080,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - if (applyAreaCut && (jetRec.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + if (applyAreaCut && (jetRec.area() < cfgAreaFrac * PI * rJet * rJet)) continue; // Clear jet-pair container @@ -4134,7 +4093,7 @@ struct AntinucleiInJets { continue; // Apply area cut if required - if (applyAreaCut && (jetGen.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + if (applyAreaCut && (jetGen.area() < cfgAreaFrac * PI * rJet * rJet)) continue; double deltaEta = jetGen.eta() - jetRec.eta(); From 1833f3197655258bac6a3247e0117e3ac28d2c87 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Tue, 19 May 2026 13:11:09 +0200 Subject: [PATCH 228/449] [PWGLF] Change histo filling in MC process (#16301) --- .../GlobalEventProperties/flattenictyPikp.cxx | 126 ++++++++---------- 1 file changed, 54 insertions(+), 72 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx index 32f362e9616..6070921bbe1 100644 --- a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -84,9 +84,10 @@ using namespace o2::constants::math; using namespace o2::aod::rctsel; auto static constexpr CminCharge = 3.f; -static constexpr float CnullInt = 0; +static constexpr int CnullInt = 0; static constexpr float Cnull = 0.0f; -static constexpr float ConeInt = 1; +static constexpr int ConeInt = 1; +static constexpr int CtwoInt = 2; static constexpr float Cone = 1.0f; // FV0 specific constants @@ -756,26 +757,11 @@ struct FlattenictyPikp { registryMC.add({"Events/ResponseGen", ";N_{ch,FV0};1-#rho_{FV0};", {kTHnSparseF, {multAxis, flatAxis}}}); registryMC.add("Events/h1flatencityFV0MCGen", "", {kTH1F, {flatAxis}}); registryMC.add("Events/hFlatMCGen", "Events/hFlatMCGen", {kTH1F, {flatAxis}}); - registryMC.add("Events/hFlatMCRec", "Events/hFlatMCRec", {kTH1F, {flatAxis}}); - // Event counter - auto h = registryMC.add("Events/hEvtGenRec", "Generated and Reconstructed MC Collisions", kTH1F, {{3, 0.5, 3.5}}); - h->GetXaxis()->SetBinLabel(1, "Gen coll"); - h->GetXaxis()->SetBinLabel(2, "Rec coll"); - h->GetXaxis()->SetBinLabel(3, "INEL>0"); registryMC.add("Events/hEvtMcGen", "Events/hEvtMcGen", {kTH1F, {{4, 0.f, 4.f}}}); registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(1, "all"); registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(2, "z-vtx"); registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(3, "INELgt0"); registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(4, "INELgt0TVX"); - registryMC.add("Events/hEvtMCRec", "Events/hEvtMCRec", {kTH1F, {{3, 0.f, 3.f}}}); - registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(1, "all"); - registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(2, "evt sel"); - registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(3, "INELgt0"); - registryMC.add("Events/hEvtMcGenColls", "Number of events; Cut; #Events Passed Cut", {kTH1F, {{4, 0.5, 4.5}}}); - registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(1, "Gen. coll"); - registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(2, "At least 1 reco"); - registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(3, "Reco. coll."); - registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(4, "Reco. good coll."); // registryMC.add("Events/hNchGenVsCent", "Gen Nch vs Cent; mult; Gen Nch (|#eta|<0.8)", {kTH2F, {nChAxis, multAxis}}); registryMC.add("Events/hVtxZRec", "MC Rec vertex z position", kTH1F, {vtxzAxis}); @@ -2357,7 +2343,7 @@ struct FlattenictyPikp { { LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), collisions.size()); auto multMC = -1.; - if (evtSelOpt.useMultMCmidrap || multEst == 2) { // use generated Nch in ∣eta∣ < 0.8 + if (evtSelOpt.useMultMCmidrap || multEst == CtwoInt) { // use generated Nch in ∣eta∣ < 0.8 multMC = countPart(particles); } else { multMC = getMultMC(mcCollision); // using McCentFT0Ms @@ -2366,45 +2352,66 @@ struct FlattenictyPikp { registryMC.fill(HIST("Events/hFlatMCGen"), flatMC); // Loop on rec collisions - // Obtain here: Denominator of tracking efficiency; Numerator event and signal loss - // - bool gtZeroColl = false; - auto multRecGt1 = -999; - auto flatRec = -999; + // Obtain here: Numerator of tracking efficiency; Secondary contamination correction for (const auto& collision : collisions) { - if (!isGoodEvent(collision)) { - continue; + if (trkSelOpt.cfgRejectTrkAtTPCSector || applyCalibGain || applyCalibVtx) { + auto bc = collision.bc_as(); + int currentRun = bc.runNumber(); + if (runNumber != currentRun) { + initCCDB(bc); + runNumber = currentRun; + } } - registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0"), multRecGt1, flatRec); // Evt split den + registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0"), getMult(collision), fillFlat(collision)); // Evt split den if (evtSelOpt.cfgRemoveSplitVertex && collision.globalIndex() != mcCollision.bestCollisionIndex()) { continue; } - registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0wRecEvt"), multRecGt1, flatRec); // Evt split num, w/ Nrec > 0 - gtZeroColl = true; - multRecGt1 = getMult(collision); - flatRec = fillFlat(collision); - } + registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0wRecEvt"), getMult(collision), fillFlat(collision)); // Evt split num, w/ Nrec > 0 + + for (const auto& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + if (particle.pt() < trkSelOpt.cfgTrkPtMin) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCGenRecEvt(particle, multMC, flatMC); + fillMCGenRecEvt(particle, multMC, flatMC); + fillMCGenRecEvt(particle, multMC, flatMC); + }); + } + if (!isGoodEvent(collision)) { + continue; + } + const float multRecGt1 = getMult(collision); + const float flatRec = fillFlat(collision); - if (gtZeroColl) { + registryMC.fill(HIST("Events/hVtxZRec"), collision.posZ()); registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0wRecEvtSel"), multRecGt1, flatRec); // Evt split num, w/ Nrec > 0 + Evt. sel registryMC.fill(HIST("Events/hNchGenVsCent"), multMC, multRecGt1); registryMC.fill(HIST("Events/hNchVsFlatGenINELgt0wRecEvtSel"), multMC, flatMC); // Evt loss num, w/ Nrec > 0 + Evt. sel - } - for (const auto& particle : particles) { - if (!isChrgParticle(particle.pdgCode())) { - continue; - } - if (!particle.isPhysicalPrimary()) { - continue; - } - if (std::abs(particle.eta()) > trkSelOpt.cfgTrkEtaMax) { - continue; - } - if (particle.pt() < trkSelOpt.cfgTrkPtMin) { - continue; - } - if (gtZeroColl) { + // Obtain here: Denominator of tracking efficiency; Numerator event and signal loss + for (const auto& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + if (particle.pt() < trkSelOpt.cfgTrkPtMin) { + continue; + } static_for<0, 1>([&](auto pidSgn) { fillMCGenRecEvt(particle, multMC, flatMC); fillMCGenRecEvt(particle, multMC, flatMC); @@ -2417,33 +2424,8 @@ struct FlattenictyPikp { registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTeffGenPrimRecEvt), multRecGt1, flatRec, particle.pt()); // Tracking eff. den } }); - } else { - static_for<0, 1>([&](auto pidSgn) { - fillMCGenRecEvt(particle, multMC, flatMC); - fillMCGenRecEvt(particle, multMC, flatMC); - fillMCGenRecEvt(particle, multMC, flatMC); - }); } - } - // Loop on rec collisions - // Obtain here: Numerator of tracking efficiency; Secondary contamination correction - for (const auto& collision : collisions) { - if (trkSelOpt.cfgRejectTrkAtTPCSector || applyCalibGain || applyCalibVtx) { - auto bc = collision.bc_as(); - int currentRun = bc.runNumber(); - if (runNumber != currentRun) { - initCCDB(bc); - runNumber = currentRun; - } - } - if (!isGoodEvent(collision)) { - continue; - } - registryMC.fill(HIST("Events/hVtxZRec"), collision.posZ()); - if (evtSelOpt.cfgRemoveSplitVertex && collision.globalIndex() != mcCollision.bestCollisionIndex()) { - continue; - } // Rec tracks; track selection w/ DCA open (for secondaries), w/ DCA close (for efficiency) // Obtain here: DCAxy for sec contamination, MC closure const auto& groupedTrks = tracks.sliceBy(perCollTrk, collision.globalIndex()); From 9e5ca6c7b74f0961a5c538352f31f588416ad6ce Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 19 May 2026 15:32:30 +0200 Subject: [PATCH 229/449] [PWGJE] Add precompiled headers for HF jetSubstructure output tasks (#16305) --- PWGJE/Tasks/CMakeLists.txt | 29 ++++++++++++++++++++++ PWGJE/Tasks/jetSubstructureHFOutputPCH.cxx | 10 ++++++++ 2 files changed, 39 insertions(+) create mode 100644 PWGJE/Tasks/jetSubstructureHFOutputPCH.cxx diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index a1b103a528c..0475580147f 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -28,6 +28,26 @@ target_precompile_headers(JetSubstructureHFPCH PRIVATE ) endif() +add_library(JetSubstructureHFOutputPCH OBJECT jetSubstructureHFOutputPCH.cxx) +target_link_libraries(JetSubstructureHFOutputPCH + PUBLIC O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore) +if(NOT DEFINED ENV{USE_RECC}) +target_precompile_headers(JetSubstructureHFOutputPCH PRIVATE + [["PWGHF/DataModel/DerivedTables.h"]] + [["PWGJE/DataModel/Jet.h"]] + [["PWGJE/DataModel/JetSubstructure.h"]] + [["PWGJE/DataModel/JetSubtraction.h"]] + [["PWGJE/Tasks/jetSubstructureHFOutput.h"]] + + + + + + + +) +endif() + o2physics_add_dpl_workflow(emc-cellmonitor SOURCES emcCellMonitor.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore @@ -143,38 +163,47 @@ if(FastJet_FOUND) o2physics_add_dpl_workflow(jet-substructure-d0-output SOURCES jetSubstructureD0Output.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dplus-output SOURCES jetSubstructureDplusOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-ds-output SOURCES jetSubstructureDsOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dstar-output SOURCES jetSubstructureDstarOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-lc-output SOURCES jetSubstructureLcOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-b0-output SOURCES jetSubstructureB0Output.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-bplus-output SOURCES jetSubstructureBplusOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-xictoxipipi-output SOURCES jetSubstructureXicToXiPiPiOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dielectron-output SOURCES jetSubstructureDielectronOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFOutputPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-fragmentation SOURCES jetFragmentation.cxx diff --git a/PWGJE/Tasks/jetSubstructureHFOutputPCH.cxx b/PWGJE/Tasks/jetSubstructureHFOutputPCH.cxx new file mode 100644 index 00000000000..384b1987f80 --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureHFOutputPCH.cxx @@ -0,0 +1,10 @@ +// Copyright 2019-2026 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. From 6c537789bb5067238d906fc5c38d9e808b1efd81 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 19 May 2026 19:25:47 +0200 Subject: [PATCH 230/449] [PWGLF] Fix bug (#16309) --- PWGLF/TableProducer/Common/mcCentrality.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/PWGLF/TableProducer/Common/mcCentrality.cxx b/PWGLF/TableProducer/Common/mcCentrality.cxx index a55ac09ef44..3e017c5808b 100644 --- a/PWGLF/TableProducer/Common/mcCentrality.cxx +++ b/PWGLF/TableProducer/Common/mcCentrality.cxx @@ -144,7 +144,6 @@ struct McCentrality { LOG(fatal) << "Could not open histogram " << name << " from TList"; } } - hist->SetDirectory(0); return hist; }; if (fillFt0M) { From a304f1d00c1d823eedcbad4dd55298a24a3027d2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Tue, 19 May 2026 20:05:01 +0200 Subject: [PATCH 231/449] [PWGLF] Add process function for data in minimum bias events (#16310) --- .../Strangeness/strangenessInJetsIons.cxx | 196 +++++++++++++++++- 1 file changed, 190 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index a89040cc729..9d5b341c884 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -106,6 +106,7 @@ struct StrangenessInJetsIons { // Define histogram registries HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryDataMB{"registryDataMB", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -549,6 +550,45 @@ struct StrangenessInJetsIons { registryMC.add("h3dAntiLambdaFeeddownFromXi0", "h3dAntiLambdaFeeddownFromXi0", kTH3D, {multAxis, ptAxis, ptAxis}); } } + + // Histograms for real data in MB events + if (doprocessDataMB) { + + // Event counters + registryDataMB.add("number_of_events_data", "number of events in data", HistType::kTH1D, {{20, 0, 20, "Event Cuts"}}); + registryDataMB.add("number_of_events_vsmultiplicity", "number of events in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(1, "All collisions"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(2, "Zorro selection"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(3, "sel8"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(4, "posZ cut"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(7, "No empty events"); + registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(8, "At least one jet"); + + // Histograms for analysis of strange hadrons + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryDataMB.add("Lambda_in_MB", "Lambda_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryDataMB.add("AntiLambda_in_MB", "AntiLambda_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryDataMB.add("K0s_in_MB", "K0s_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + } + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryDataMB.add("XiPos_in_MB", "XiPos_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryDataMB.add("XiNeg_in_MB", "XiNeg_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryDataMB.add("OmegaPos_in_MB", "OmegaPos_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryDataMB.add("OmegaNeg_in_MB", "OmegaNeg_in_MB", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + } + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryDataMB.add("Pion_in_MB", "Pion_in_MB", HistType::kTHnSparseF, {multAxis, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); + } + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryDataMB.add("Kaon_in_MB", "Kaon_in_MB", HistType::kTHnSparseF, {multAxis, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); + } + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryDataMB.add("Proton_in_MB", "Proton_in_MB", HistType::kTHnSparseF, {multAxis, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); + } + } } // Delta phi calculation @@ -1635,7 +1675,7 @@ struct StrangenessInJetsIons { bool isV0 = isK0S || isLambda || isAntiLambda; if (!isV0) continue; - for (int i = 0; i < int(fjTracks.size()); ++i) { + for (long unsigned int i = 0; i < fjTracks.size(); ++i) { if (isV0DaughterTrack(fjTracks[i], v0)) { // LOG(info) << "[AddV0sForJetReconstructionData] V0 daughter track found in fjTracks."; isTrackReplaced[i] = true; @@ -1645,7 +1685,7 @@ struct StrangenessInJetsIons { std::vector cleanFjInput; cleanFjInput.reserve(fjInput.size()); - for (int i = 0; i < int(fjInput.size()); ++i) { + for (long unsigned int i = 0; i < fjInput.size(); ++i) { if (!isTrackReplaced[i]) cleanFjInput.push_back(fjInput[i]); } @@ -1733,7 +1773,7 @@ struct StrangenessInJetsIons { bool isV0 = isK0S || isLambda || isAntiLambda; if (!isV0) continue; - for (int i = 0; i < int(fjTracks.size()); ++i) { + for (long unsigned int i = 0; i < fjTracks.size(); ++i) { if (isV0DaughterTrack(fjTracks[i], v0)) { // LOG(info) << "[AddV0sForJetReconstructionMCD] V0 daughter track found in fjTracks."; isTrackReplaced[i] = true; @@ -1743,7 +1783,7 @@ struct StrangenessInJetsIons { std::vector cleanFjInput; cleanFjInput.reserve(fjInput.size()); - for (int i = 0; i < int(fjInput.size()); ++i) { + for (long unsigned int i = 0; i < fjInput.size(); ++i) { if (!isTrackReplaced[i]) cleanFjInput.push_back(fjInput[i]); } @@ -1789,7 +1829,7 @@ struct StrangenessInJetsIons { // LOG(info) << "[AddV0sForJetReconstructionMCP] Add V0 as input for jet finder."; // Remove V0 daughter particles if already in the input list for the jet finder - for (int i = 0; i < int(fjParticleObj.size()); ++i) { + for (long unsigned int i = 0; i < fjParticleObj.size(); ++i) { const auto& mcPart = fjParticleObj[i]; if (!mcPart.has_mothers()) continue; @@ -1805,7 +1845,7 @@ struct StrangenessInJetsIons { std::vector cleanFjInput; cleanFjInput.reserve(fjInput.size()); - for (int i = 0; i < int(fjInput.size()); ++i) { + for (long unsigned int i = 0; i < fjInput.size(); ++i) { if (!isTrackReplaced[i]) cleanFjInput.push_back(fjInput[i]); } @@ -3181,6 +3221,150 @@ struct StrangenessInJetsIons { } } PROCESS_SWITCH(StrangenessInJetsIons, processMCmodels, "Process MC generated events (with models)", false); + + // --- Process Minimum Bias events --- + // Process data MB + void processDataMB(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, + aod::CascDataExt const& Cascades, DaughterTracks const& tracks, + aod::BCsWithTimestamps const&) + { + // Vertex position vector + TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); + + // Fill event counter before event selection + registryDataMB.fill(HIST("number_of_events_data"), 0.5); + + // Get the bunch crossing (BC) information associated with the collision + auto bc = collision.template bc_as(); + + // Initialize CCDB objects using the BC info + initCCDB(bc); + + // If skimmed processing is enabled, skip this event unless it passes Zorro selection + if (cfgSkimmedProcessing && !zorro.isSelected(collision.template bc_as().globalBC())) { + return; + } + + // Fill event counter after zorro selection + registryDataMB.fill(HIST("number_of_events_data"), 1.5); + + // Event selection + if (!collision.sel8()) + return; + + // Fill event counter after sel8 selection + registryDataMB.fill(HIST("number_of_events_data"), 2.5); + + // Require vertex position within the allowed z range + if (std::fabs(collision.posZ()) > zVtx) + return; + + // Fill event counter after z vertex selection + registryDataMB.fill(HIST("number_of_events_data"), 3.5); + + // Reject collisions associated to the same found BC + if (requireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + + // Fill event counter after selection kNoSameBunchPileup + registryDataMB.fill(HIST("number_of_events_data"), 4.5); + + // Compatible z_vtx from FT0 and from PV + if (requireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + + // Fill event counter after selection kIsGoodZvtxFT0vsPV + registryDataMB.fill(HIST("number_of_events_data"), 5.5); + + // Event multiplicity + float centrality; + if (centrEstimator == 0) { + centrality = collision.centFT0C(); + } else { + centrality = collision.centFT0M(); + } + registryDataMB.fill(HIST("number_of_events_vsmultiplicity"), centrality); + + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { // V0s + for (const auto& v0 : fullV0s) { + + // Get V0 daughters + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + TVector3 v0dir(v0.px(), v0.py(), v0.pz()); + + // K0s + if (passedK0ShortSelection(v0, pos, neg, vtxPos)) { + registryDataMB.fill(HIST("K0s_in_MB"), centrality, v0.pt(), v0.mK0Short()); + } + // Lambda + if (passedLambdaSelection(v0, pos, neg, vtxPos)) { + registryDataMB.fill(HIST("Lambda_in_MB"), centrality, v0.pt(), v0.mLambda()); + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg, vtxPos)) { + registryDataMB.fill(HIST("AntiLambda_in_MB"), centrality, v0.pt(), v0.mAntiLambda()); + } + } + } + + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { // Cascades + for (const auto& casc : Cascades) { + // Get cascade daughters + const auto& bach = casc.bachelor_as(); + const auto& pos = casc.posTrack_as(); + const auto& neg = casc.negTrack_as(); + TVector3 cascadeDir(casc.px(), casc.py(), casc.pz()); + + // Xi+ + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { + registryDataMB.fill(HIST("XiPos_in_MB"), centrality, casc.pt(), casc.mXi()); + } + // Xi- + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { + registryDataMB.fill(HIST("XiNeg_in_MB"), centrality, casc.pt(), casc.mXi()); + } + // Omega+ + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { + registryDataMB.fill(HIST("OmegaPos_in_MB"), centrality, casc.pt(), casc.mOmega()); + } + // Omega- + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { + registryDataMB.fill(HIST("OmegaNeg_in_MB"), centrality, casc.pt(), casc.mOmega()); + } + } + } + if (particleOfInterestDict[ParticleOfInterest::kPions] || + particleOfInterestDict[ParticleOfInterest::kKaons] || + particleOfInterestDict[ParticleOfInterest::kProtons]) { + for (const auto& trk : tracks) { + + if (!passedSingleTrackSelection(trk)) { + continue; + } + + float nsigmaTPC = 0.f; + float nsigmaTOF = 0.f; + + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + nsigmaTPC = trk.tpcNSigmaPi(); + nsigmaTOF = trk.tofNSigmaPi(); + registryDataMB.fill(HIST("Pion_in_MB"), centrality, trk.pt() * trk.sign(), nsigmaTPC, nsigmaTOF, trk.dcaXY()); + } + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + nsigmaTPC = trk.tpcNSigmaKa(); + nsigmaTOF = trk.tofNSigmaKa(); + registryDataMB.fill(HIST("Kaon_in_MB"), centrality, trk.pt() * trk.sign(), nsigmaTPC, nsigmaTOF, trk.dcaXY()); + } + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + nsigmaTPC = trk.tpcNSigmaPr(); + nsigmaTOF = trk.tofNSigmaPr(); + registryDataMB.fill(HIST("Proton_in_MB"), centrality, trk.pt() * trk.sign(), nsigmaTPC, nsigmaTOF, trk.dcaXY()); + } + } + } + } + PROCESS_SWITCH(StrangenessInJetsIons, processDataMB, "Process data in minimum bias events", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 535282a113df452c83a090608395e356e0d916ef Mon Sep 17 00:00:00 2001 From: Andrea Giovanni Riffero Date: Tue, 19 May 2026 20:22:57 +0200 Subject: [PATCH 232/449] [PWGUD] Add RCT flag checks in UPCCandidateProducer (#16255) Co-authored-by: ALICE Action Bot --- PWGUD/TableProducer/UPCCandidateProducer.cxx | 67 ++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index d58c98ac587..c2606e52f3c 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -19,6 +19,7 @@ #include "PWGUD/DataModel/UDTables.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +59,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; struct UpcCandProducer { bool fDoMC{false}; @@ -91,6 +94,9 @@ struct UpcCandProducer { std::vector fwdSelectors; std::vector barrelSelectors; + // RCT flag checker + RCTFlagsChecker myRCTChecker; + // skimmer flags // choose a source of signal MC events Configurable fSignalGenID{"signalGenID", 1, "Signal generator ID"}; @@ -125,9 +131,16 @@ struct UpcCandProducer { Configurable fRequireNoTimeFrameBorder{"requireNoTimeFrameBorder", true, "Require kNoTimeFrameBorder selection bit"}; Configurable fRequireNoITSROFrameBorder{"requireNoITSROFrameBorder", true, "Require kNoITSROFrameBorder selection bit"}; + Configurable rctLabel{"rctLabel", "muon", "RCT label to use, options: CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo, muon = FV0 + MID + MCH, muon_glo = muon + MFT, none = do not use RCT flags"}; + Configurable checkZDC{"checkZDC", false, "Consider ZDC quality"}; + Configurable useLAasBad{"useLAasBad", false, "Consider Lim acc flag as Bad"}; + bool useRCTflags = true; + // QA histograms HistogramRegistry histRegistry{"HistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + using CollisionsSels = o2::soa::Join; + using BCsWithBcSels = o2::soa::Join; using ForwardTracks = o2::soa::Join; @@ -146,6 +159,34 @@ struct UpcCandProducer { upcCuts = (UPCCutparHolder)inputCuts; + // initialize RCT flag checker + if (rctLabel.value != "none" && rctLabel.value != "muon" && rctLabel.value != "muon_glo") { + myRCTChecker.init(rctLabel.value, checkZDC.value, useLAasBad.value); + } else if (rctLabel.value == "none") { + useRCTflags = false; + myRCTChecker.init("CBT_muon"); + } else if (rctLabel.value == "muon") { + if (checkZDC.value && useLAasBad.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kZDCBad, kMCHLimAccMCRepr, kMIDLimAccMCRepr}); + } else if (checkZDC.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kZDCBad}); + } else if (useLAasBad.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kMCHLimAccMCRepr, kMIDLimAccMCRepr}); + } else { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad}); + } + } else if (rctLabel.value == "muon_glo") { + if (checkZDC.value && useLAasBad.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kMFTBad, kZDCBad, kMCHLimAccMCRepr, kMIDLimAccMCRepr, kMFTLimAccMCRepr}); + } else if (checkZDC.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kMFTBad, kZDCBad}); + } else if (useLAasBad.value) { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kMFTBad, kMCHLimAccMCRepr, kMIDLimAccMCRepr, kMFTLimAccMCRepr}); + } else { + myRCTChecker.init({kFV0Bad, kMCHBad, kMIDBad, kMFTBad}); + } + } + const AxisSpec axisTrgCounters{10, 0.5, 10.5, ""}; histRegistry.add("hCountersTrg", "", kTH1F, {axisTrgCounters}); histRegistry.get(HIST("hCountersTrg"))->GetXaxis()->SetBinLabel(1, "TCE"); @@ -179,6 +220,11 @@ struct UpcCandProducer { histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelTPCChi2 + 1, "TPCChi2"); histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelDCAXY + 1, "DCAXY"); histRegistry.get(HIST("BarrelsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kBarrelSelDCAZ + 1, "DCAZ"); + + histRegistry.add("RCTSelCounter", "RCTSelCounter", kTH1F, {{3, 0.5, 3.5}}); + histRegistry.get(HIST("RCTSelCounter"))->GetXaxis()->SetBinLabel(1, "Before RCT sel"); + histRegistry.get(HIST("RCTSelCounter"))->GetXaxis()->SetBinLabel(2, "After RCT sel"); + histRegistry.get(HIST("RCTSelCounter"))->GetXaxis()->SetBinLabel(3, "RCT rejected"); } template @@ -682,6 +728,13 @@ struct UpcCandProducer { uint64_t trackBC = 0; if (trk.has_collision()) { const auto& col = trk.collision(); + auto bcRCT = col.bc_as(); + histRegistry.get(HIST("RCTSelCounter"))->Fill(1); + if (!myRCTChecker(bcRCT) && useRCTflags) { + histRegistry.get(HIST("RCTSelCounter"))->Fill(3); + continue; + } + histRegistry.get(HIST("RCTSelCounter"))->Fill(2); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); hasTrackBC = true; @@ -725,6 +778,13 @@ struct UpcCandProducer { if (!trk.has_collision()) continue; const auto& col = trk.collision(); + auto bcRCT = col.bc_as(); + histRegistry.get(HIST("RCTSelCounter"))->Fill(1); + if (!myRCTChecker(bcRCT) && useRCTflags) { + histRegistry.get(HIST("RCTSelCounter"))->Fill(3); + continue; + } + histRegistry.get(HIST("RCTSelCounter"))->Fill(2); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); hasTrackBC = true; @@ -765,6 +825,13 @@ struct UpcCandProducer { if (!trk.has_collision()) continue; const auto& col = trk.collision(); + auto bcRCT = col.bc_as(); + histRegistry.get(HIST("RCTSelCounter"))->Fill(1); + if (!myRCTChecker(bcRCT) && useRCTflags) { + histRegistry.get(HIST("RCTSelCounter"))->Fill(3); + continue; + } + histRegistry.get(HIST("RCTSelCounter"))->Fill(2); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); const auto& bc = col.bc_as(); From 1713a772bf91ba7fded06c6f20508cac1b47bddc Mon Sep 17 00:00:00 2001 From: nepeivodaRS <94179174+nepeivodaRS@users.noreply.github.com> Date: Tue, 19 May 2026 21:43:31 +0200 Subject: [PATCH 233/449] [PWGLF] cascades in pp: generated border cuts and PDG QA (#16311) --- PWGLF/DataModel/cascqaanalysis.h | 2 +- .../Strangeness/cascqaanalysis.cxx | 44 ++++++++++++++----- .../Tasks/Strangeness/cascpostprocessing.cxx | 13 ++++++ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/PWGLF/DataModel/cascqaanalysis.h b/PWGLF/DataModel/cascqaanalysis.h index 93081d09fca..3442c074305 100644 --- a/PWGLF/DataModel/cascqaanalysis.h +++ b/PWGLF/DataModel/cascqaanalysis.h @@ -87,7 +87,7 @@ DECLARE_SOA_COLUMN(BachHasTOF, bachhastof, int); DECLARE_SOA_COLUMN(PosPt, pospt, float); DECLARE_SOA_COLUMN(NegPt, negpt, float); DECLARE_SOA_COLUMN(BachPt, bachpt, float); -DECLARE_SOA_COLUMN(McPdgCode, mcPdgCode, int); //! -1 unknown +DECLARE_SOA_COLUMN(McPdgCode, mcPdgCode, int); //! 0 unknown/no MC association DECLARE_SOA_COLUMN(IsPrimary, isPrimary, int); //! -1 unknown, 0 not primary, 1 primary DECLARE_SOA_COLUMN(BachBaryonCosPA, bachBaryonCosPA, float); //! avoid bach-baryon correlated inv mass structure in analysis DECLARE_SOA_COLUMN(BachBaryonDCAxyToPV, bachBaryonDCAxyToPV, float); //! avoid bach-baryon correlated inv mass structure in analysis diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index 6ca9c40082b..8ec9142efc3 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -68,6 +68,7 @@ using namespace o2::aod::rctsel; using TrkPidInfo = soa::Join; using DauTracks = soa::Join; using LabeledCascades = soa::Join; +using BCsWithBcSels = soa::Join; struct Cascqaanalysis { @@ -119,6 +120,7 @@ struct Cascqaanalysis { Configurable isTriggerTVX{"isTriggerTVX", 1, "TVX trigger"}; Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", 1, "TF border cut"}; Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", 1, "ITS ROF border cut"}; + Configurable applyBcBorderCutsOnGen{"applyBcBorderCutsOnGen", false, "Apply enabled BC-level TF and ITS ROF border cuts on generated-level MC collisions"}; Configurable isNoCollInTimeRangeNarrow{"isNoCollInTimeRangeNarrow", 1, "No collisions in +-2us window"}; Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; @@ -221,7 +223,7 @@ struct Cascqaanalysis { void init(InitContext const&) { TString hCandidateCounterLabels[4] = {"All candidates", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; - TString hNEventsMCLabels[6] = {"All", "z vrtx", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; + TString hNEventsMCLabels[7] = {"All", "z vrtx", "BC TF/ITS ROF border", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; TString hNEventsLabels[14] = {"All", "kIsTriggerTVX", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "isVertexTOFmatched", "kNoCollInTimeRangeNarrow", "z vrtx", "RCTFlagsChecker", "INEL", "INEL>0", "INEL>1"}; registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{14, 0.f, 14.f}}}); @@ -239,7 +241,7 @@ struct Cascqaanalysis { // Rec. lvl registry.add("fakeEvents", "fakeEvents", {HistType::kTH1F, {{1, -0.5f, 0.5f}}}); // Gen. lvl - registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1D, {{6, 0.0f, 6.0f}}}); + registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1D, {{7, 0.0f, 7.0f}}}); for (int n = 1; n <= registry.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { registry.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); } @@ -481,6 +483,21 @@ struct Cascqaanalysis { return true; } + template + bool acceptGeneratedEventBcBorderCuts(TBC const& bc) + { + if (!applyBcBorderCutsOnGen) { + return true; + } + if (isNoTimeFrameBorder && !bc.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (isNoITSROFrameBorder && !bc.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + return true; + } + void processData(soa::Join::iterator const& collision, @@ -546,7 +563,7 @@ struct Cascqaanalysis { posdau.tpcNClsFound(), negdau.tpcNClsFound(), bachelor.tpcNClsFound(), posdau.tpcNClsCrossedRows(), negdau.tpcNClsCrossedRows(), bachelor.tpcNClsCrossedRows(), posdau.hasTOF(), negdau.hasTOF(), bachelor.hasTOF(), - posdau.pt(), negdau.pt(), bachelor.pt(), -1, -1, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag, 1e3, 1e3); + posdau.pt(), negdau.pt(), bachelor.pt(), 0, -1, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag, 1e3, 1e3); } } } @@ -627,16 +644,16 @@ struct Cascqaanalysis { registry.fill(HIST("hCandidateCounter"), 1.5); // passed topo cuts nCandSel++; // Check mc association - float lPDG = 1e3; + int mcPdgCode = 0; float genPt = 1e3; float genY = 1e3; float isPrimary = -1; if (casc.has_mcParticle()) { registry.fill(HIST("hCandidateCounter"), 2.5); // has associated MC particle auto cascmc = casc.mcParticle(); + mcPdgCode = cascmc.pdgCode(); if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus || std::abs(cascmc.pdgCode()) == PDG_t::kOmegaMinus) { registry.fill(HIST("hCandidateCounter"), 3.5); // associated with Xi or Omega - lPDG = cascmc.pdgCode(); isPrimary = cascmc.isPhysicalPrimary() ? 1 : 0; genPt = cascmc.pt(); genY = cascmc.y(); @@ -667,7 +684,7 @@ struct Cascqaanalysis { posdau.tpcNClsFound(), negdau.tpcNClsFound(), bachelor.tpcNClsFound(), posdau.tpcNClsCrossedRows(), negdau.tpcNClsCrossedRows(), bachelor.tpcNClsCrossedRows(), posdau.hasTOF(), negdau.hasTOF(), bachelor.hasTOF(), - posdau.pt(), negdau.pt(), bachelor.pt(), lPDG, isPrimary, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag, genPt, genY); + posdau.pt(), negdau.pt(), bachelor.pt(), mcPdgCode, isPrimary, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag, genPt, genY); } } } @@ -681,6 +698,7 @@ struct Cascqaanalysis { void processMCgen(soa::Join::iterator const& mcCollision, // mcCollision.centFV0A() to be added aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions, + BCsWithBcSels const&, DauTracks const&) { // All generated collisions @@ -690,25 +708,29 @@ struct Cascqaanalysis { if (std::fabs(mcCollision.posZ()) > cutzvertex) { return; } - registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); registry.fill(HIST("hNEventsMC"), 1.5); + if (!acceptGeneratedEventBcBorderCuts(mcCollision.bc_as())) { + return; + } + registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); + registry.fill(HIST("hNEventsMC"), 2.5); // Define the type of generated MC collision EventTypeBin evType = kINEL; uint8_t flagsGen = 0; flagsGen |= o2::aod::myMCcascades::EvFlags::EvINEL; - registry.fill(HIST("hNEventsMC"), 2.5); + registry.fill(HIST("hNEventsMC"), 3.5); // Generated collision is INEL>0 if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt0; evType = kINELgt0; - registry.fill(HIST("hNEventsMC"), 3.5); + registry.fill(HIST("hNEventsMC"), 4.5); } // Generated collision is INEL>1 if (pwglf::isINELgtNmc(mcParticles, 1, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt1; evType = kINELgt1; - registry.fill(HIST("hNEventsMC"), 4.5); + registry.fill(HIST("hNEventsMC"), 5.5); } registry.fill(HIST("hCentFT0M_genMC"), mcCollision.centFT0M(), evType); @@ -783,7 +805,7 @@ struct Cascqaanalysis { uint8_t flagsAssoc = 0; if (evtReconstructedAndINEL) { flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINEL; - registry.fill(HIST("hNEventsMC"), 5.5); + registry.fill(HIST("hNEventsMC"), 6.5); } if (evtReconstructedAndINELgt0) { flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINELgt0; diff --git a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx index 94dafc57939..29ac791051d 100644 --- a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx +++ b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx @@ -106,6 +106,7 @@ struct LfCascpostprocessing { AxisSpec ptAxisTopoVar = {50, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisPID = {50, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis etaAxis{"etaAxis", {40, -2.0f, 2.0f}, "#eta"}; + AxisSpec pdgCodeAxis = {10001, -5000.5f, 5000.5f, "MC PDG code (0 = no MC assoc.)"}; ConfigurableAxis centFT0MAxis{"centFT0MAxis", {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 101, 105.5}, @@ -238,6 +239,9 @@ struct LfCascpostprocessing { registry.add("hCascPlusMassvsPtBG", "hCascPlusMassvsPtBG", {HistType::kTH2F, {ptAxis, massAxis}}); registry.add("hCascMinusMassvsPtBG_FT0M", "hCascMinusMassvsPtBG_FT0M", {HistType::kTH3F, {ptAxis, massAxis, centFT0MAxis}}); registry.add("hCascPlusMassvsPtBG_FT0M", "hCascPlusMassvsPtBG_FT0M", {HistType::kTH3F, {ptAxis, massAxis, centFT0MAxis}}); + registry.add("hMisidentifiedCascPdgCode", "hMisidentifiedCascPdgCode", {HistType::kTH1F, {pdgCodeAxis}}); + registry.add("hMisidentifiedCascMinusPdgCode", "hMisidentifiedCascMinusPdgCode", {HistType::kTH1F, {pdgCodeAxis}}); + registry.add("hMisidentifiedCascPlusPdgCode", "hMisidentifiedCascPlusPdgCode", {HistType::kTH1F, {pdgCodeAxis}}); registry.add("hPtXiPlusTrue", "hPtXiPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); registry.add("hPtXiMinusTrue", "hPtXiMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); registry.add("hPtOmegaPlusTrue", "hPtOmegaPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); @@ -514,6 +518,15 @@ struct LfCascpostprocessing { // registry.fill(HIST("hNegITSHits"), candidate.negitshits()); // registry.fill(HIST("hBachITSHits"), candidate.bachitshits()); + if (isMC && !isCorrectlyRec) { + registry.fill(HIST("hMisidentifiedCascPdgCode"), candidate.mcPdgCode()); + if (candidate.sign() < 0) { + registry.fill(HIST("hMisidentifiedCascMinusPdgCode"), candidate.mcPdgCode()); + } else if (candidate.sign() > 0) { + registry.fill(HIST("hMisidentifiedCascPlusPdgCode"), candidate.mcPdgCode()); + } + } + if (candidate.sign() < 0) { if (isMC) { if (isCorrectlyRec) { From 8d711c90ef21bed61baedd593a12f63e286fa6f8 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Tue, 19 May 2026 22:09:50 +0200 Subject: [PATCH 234/449] [PWGCF] FemtoUniverse Cascade Task -- added track-track efficiency (#16312) Co-authored-by: Shirajum Monira --- .../Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index e7da5f6ad9c..897e2ac749a 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -91,7 +91,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; Configurable confTrkPDGCodePartTwo{"confTrkPDGCodePartTwo", 2212, "Particle 1 (Track) - PDG code"}; Configurable confChargePart1{"confChargePart1", 1, "sign of track particle 1"}; - Configurable confChargePart2{"confChargePart2", -1, "sign of track particle 2"}; + Configurable confChargePart2{"confChargePart2", 1, "sign of track particle 2"}; Configurable confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of track particle"}; Configurable confLPtPart1{"confLPtPart1", 0.5f, "lower limit for pt of track particle"}; Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "combined TPC and TOF Sigma for track particle for momentum > Confmom"}; @@ -400,6 +400,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); LOGF(info, "Loaded efficiency histograms for Cascade-Cascade."); + } else if (doprocessSameEventTrack || doprocessSameEventTrackBitmask || doprocessMixedEventTrack || doprocessMixedEventTrackBitmask) { + pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + pEffHistp2 = (trackparticleconfigs.confChargePart2 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now } } else if (!ccdbEffLoader.confCCDBEfficiency.value.empty()) { ccdb->setURL("http://alice-ccdb.cern.ch"); @@ -415,6 +418,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/Cascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/AntiCascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)); pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/Cascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/AntiCascade", ccdbEffLoader.confCCDBNoLaterThanCasc.value)); LOGF(info, "Loaded efficiency histograms for Cascade-Cascade from CCDB."); + } else if (doprocessSameEventTrack || doprocessSameEventTrackBitmask || doprocessMixedEventTrack || doprocessMixedEventTrackBitmask) { + pEffHistp1 = (trackparticleconfigs.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrPlus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrMinus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)); /// works only for protons + pEffHistp2 = (trackparticleconfigs.confChargePart2 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrPlus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)) : std::unique_ptr(ccdb->getForTimeStamp(ccdbEffLoader.confCCDBEfficiency.value + "/PrMinus", ccdbEffLoader.confCCDBNoLaterThanTrack.value)); /// works only for protons } } } From ad263a761fd19e529aedcdbc6aaa251c2016334e Mon Sep 17 00:00:00 2001 From: bhattdurgesh921-sys Date: Wed, 20 May 2026 02:29:00 +0530 Subject: [PATCH 235/449] [PWGLF] histograms for quality assurance (#16304) --- .../Tasks/Resonances/lambda1520analysispo.cxx | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx b/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx index 350c7dd9501..435a104dbdb 100644 --- a/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysispo.cxx @@ -12,7 +12,7 @@ /// \file lambda1520Analysispo.cxx /// \brief Task for Lambda(1520) resonance reconstruction via proton-kaon invariant mass analysis for pO system /// -/// \author Yash Patley , Durgesh Bhatt +/// \author Durgesh Bhatt #include "PWGLF/DataModel/LFResonanceTables.h" @@ -56,7 +56,7 @@ static constexpr int PdgOmegaMinus{3334}; } // namespace lambda_analysis // FIX name/struct: use UpperCamelCase for struct names -struct Lambda1520Analysispo { +struct lambda1520analysispo { SliceCache sliceCache; // Preslice helpers @@ -224,8 +224,10 @@ struct Lambda1520Analysispo { allHistograms.add("QAafter/Proton/tpcNSigmaPionContamVsPt", "Proton track: TPC nSigma pion contamination check", kTH2F, {axisPtForPID, axisTPCNSigma}); allHistograms.add("QAafter/Proton/tpcNSigmaKaonContamVsPt", "Proton track: TPC nSigma kaon contamination check", kTH2F, {axisPtForPID, axisTPCNSigma}); allHistograms.add("QAafter/Proton/tpcNSigmaVsMomentum", "Proton TPC nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Proton/tpcNSigmaVsCentrality", "Proton TPC nSigma vs centrality", kTH2F, {axisCentralityPercent, axisTPCNSigma}); allHistograms.add("QAafter/Proton/tofNSigmaVsPt", "Proton TOF nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTOFNSigma}); allHistograms.add("QAafter/Proton/tofNSigmaVsMomentum", "Proton TOF nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Proton/tofNSigmaVsCentrality", "Proton TOF nSigma vs centrality", kTH2F, {axisCentralityPercent, axisTOFNSigma}); allHistograms.add("QAafter/Proton/tofNSigmaPionContamVsMomentum", "Proton track: TOF nSigma pion contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); allHistograms.add("QAafter/Proton/tofNSigmaKaonContamVsMomentum", "Proton track: TOF nSigma kaon contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); allHistograms.add("QAafter/Proton/tofNSigmaVsTPCNSigma", "Proton TOF nSigma vs TPC nSigma (after cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); @@ -240,8 +242,10 @@ struct Lambda1520Analysispo { allHistograms.add("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum", "Kaon track: TPC nSigma proton contamination check", kTH2F, {axisMomentumForPID, axisTPCNSigma}); allHistograms.add("QAafter/Kaon/tpcNSigmaVsPt", "Kaon TPC nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTPCNSigma}); allHistograms.add("QAafter/Kaon/tpcNSigmaVsMomentum", "Kaon TPC nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTPCNSigma}); + allHistograms.add("QAafter/Kaon/tpcNSigmaVsCentrality", "Kaon TPC nSigma vs centrality", kTH2F, {axisCentralityPercent, axisTPCNSigma}); allHistograms.add("QAafter/Kaon/tofNSigmaVsPt", "Kaon TOF nSigma vs pT (after cuts)", kTH2F, {axisPtForPID, axisTOFNSigma}); allHistograms.add("QAafter/Kaon/tofNSigmaVsMomentum", "Kaon TOF nSigma vs total momentum (after cuts)", kTH2F, {axisMomentumForPID, axisTOFNSigma}); + allHistograms.add("QAafter/Kaon/tofNSigmaVsCentrality", "Kaon TOF nSigma vs centrality", kTH2F, {axisCentralityPercent, axisTOFNSigma}); allHistograms.add("QAafter/Kaon/tofNSigmaPionContamVsMomentum", "Kaon track: TOF nSigma pion contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); allHistograms.add("QAafter/Kaon/tofNSigmaProtonContamVsMomentum", "Kaon track: TOF nSigma proton contamination check", kTH2F, {axisMomentumForPID, axisTOFNSigma}); allHistograms.add("QAafter/Kaon/tofNSigmaVsTPCNSigma", "Kaon TOF nSigma vs TPC nSigma (after cuts)", kTH2F, {axisTPCNSigma, axisTOFNSigma}); @@ -610,6 +614,7 @@ struct Lambda1520Analysispo { allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaPionContamVsPt"), protonTotalMomentum, protonTrack.tpcNSigmaPi()); allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaKaonContamVsPt"), protonTotalMomentum, protonTrack.tpcNSigmaKa()); allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsMomentum"), protonTotalMomentum, tpcNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsCentrality"), tpcNSigProton, centralityPercent); allHistograms.fill(HIST("QAafter/Proton/tpcNSigmaVsPt"), ptProton, tpcNSigProton); allHistograms.fill(HIST("QAafter/Proton/tpcCrossedRowsVsPt"), ptProton, protonTrack.tpcNClsCrossedRows()); allHistograms.fill(HIST("QAafter/Proton/tpcClustersFoundVsPt"), ptProton, protonTrack.tpcNClsFound()); @@ -617,6 +622,7 @@ struct Lambda1520Analysispo { if (!useTPCOnlyPID && protonTrack.hasTOF()) { auto tofNSigProton = protonTrack.tofNSigmaPr(); allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsMomentum"), protonTotalMomentum, tofNSigProton); + allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsCentrality"), tofNSigProton, centralityPercent); allHistograms.fill(HIST("QAafter/Proton/tofNSigmaVsPt"), ptProton, tofNSigProton); allHistograms.fill(HIST("QAafter/Proton/tofNSigmaPionContamVsMomentum"), protonTotalMomentum, protonTrack.tofNSigmaPi()); allHistograms.fill(HIST("QAafter/Proton/tofNSigmaKaonContamVsMomentum"), protonTotalMomentum, protonTrack.tofNSigmaKa()); @@ -633,6 +639,7 @@ struct Lambda1520Analysispo { allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaPionContamVsPt"), kaonTotalMomentum, kaonTrack.tpcNSigmaPi()); allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaProtonContamVsMomentum"), kaonTotalMomentum, kaonTrack.tpcNSigmaPr()); allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsMomentum"), kaonTotalMomentum, tpcNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsCentrality"), tpcNSigKaon, centralityPercent); allHistograms.fill(HIST("QAafter/Kaon/tpcNSigmaVsPt"), ptKaon, tpcNSigKaon); allHistograms.fill(HIST("QAafter/Kaon/tpcCrossedRowsVsPt"), ptKaon, kaonTrack.tpcNClsCrossedRows()); allHistograms.fill(HIST("QAafter/Kaon/tpcClustersFoundVsPt"), ptKaon, kaonTrack.tpcNClsFound()); @@ -641,6 +648,7 @@ struct Lambda1520Analysispo { auto tofNSigKaon = kaonTrack.tofNSigmaKa(); allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsMomentum"), kaonTotalMomentum, tofNSigKaon); allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsPt"), ptKaon, tofNSigKaon); + allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsCentrality"), tofNSigKaon, centralityPercent); allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaPionContamVsMomentum"), kaonTotalMomentum, kaonTrack.tofNSigmaPi()); allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaProtonContamVsMomentum"), kaonTotalMomentum, kaonTrack.tofNSigmaPr()); allHistograms.fill(HIST("QAafter/Kaon/tofNSigmaVsTPCNSigma"), tpcNSigKaon, tofNSigKaon); @@ -830,7 +838,7 @@ struct Lambda1520Analysispo { allHistograms.fill(HIST("Event/primaryVertexZ"), collision.posZ()); fillInvariantMassHistograms(tracks, tracks, collision.cent()); } - PROCESS_SWITCH(Lambda1520Analysispo, processData, + PROCESS_SWITCH(lambda1520analysispo, processData, "Process real collision data (same-event analysis)", true); // ============================================================ @@ -935,7 +943,7 @@ struct Lambda1520Analysispo { parentMass, parentParticle.pt(), centralityPercent); } } - PROCESS_SWITCH(Lambda1520Analysispo, processMC, + PROCESS_SWITCH(lambda1520analysispo, processMC, "Process Monte Carlo simulated events", false); // ============================================================ @@ -1042,7 +1050,7 @@ struct Lambda1520Analysispo { } } } - PROCESS_SWITCH(Lambda1520Analysispo, processMCGen, + PROCESS_SWITCH(lambda1520analysispo, processMCGen, "Generator-level MC signal loss study (mT scaling)", false); // ── Event-mixing binning types ─────────────────────────────────────────── @@ -1075,7 +1083,7 @@ struct Lambda1520Analysispo { fillInvariantMassHistograms(tracks1, tracks2, col1.cent()); } } - PROCESS_SWITCH(Lambda1520Analysispo, processMix, + PROCESS_SWITCH(lambda1520analysispo, processMix, "Event mixing for background estimation (standard format)", true); @@ -1105,7 +1113,7 @@ struct Lambda1520Analysispo { fillInvariantMassHistograms(tracks, tracks, collision.cent(), occupancyValue); } - PROCESS_SWITCH(Lambda1520Analysispo, processDatadf, + PROCESS_SWITCH(lambda1520analysispo, processDatadf, "Process real data in merged derived-data (DF) format", false); // ============================================================ @@ -1143,7 +1151,7 @@ struct Lambda1520Analysispo { occupancyValue); } } - PROCESS_SWITCH(Lambda1520Analysispo, processMixDF, + PROCESS_SWITCH(lambda1520analysispo, processMixDF, "Event mixing for DF-format data", false); // ============================================================ @@ -1177,12 +1185,12 @@ struct Lambda1520Analysispo { fillInvariantMassHistograms(tracks1, tracks2, col1.cent()); } } - PROCESS_SWITCH(Lambda1520Analysispo, processMixepDF, + PROCESS_SWITCH(lambda1520analysispo, processMixepDF, "Event-plane dependent event mixing for DF-format data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 3c1efe9c1faf00cd2e146528d8bbfa647f05d253 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Wed, 20 May 2026 00:13:23 +0200 Subject: [PATCH 236/449] [PWGDQ] extend the input features in MLResponse class (#16228) --- PWGDQ/Core/MuonMatchingMlResponse.h | 450 +++++++++++------- .../TableProducer/tableMakerMC_withAssoc.cxx | 8 +- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 2 +- PWGDQ/Tasks/mftMchMatcher.cxx | 2 +- PWGDQ/Tasks/qaMatching.cxx | 10 +- 5 files changed, 275 insertions(+), 197 deletions(-) diff --git a/PWGDQ/Core/MuonMatchingMlResponse.h b/PWGDQ/Core/MuonMatchingMlResponse.h index ee2f419a5f5..90e0da301e4 100644 --- a/PWGDQ/Core/MuonMatchingMlResponse.h +++ b/PWGDQ/Core/MuonMatchingMlResponse.h @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -35,96 +36,83 @@ // Check if the index of mCachedIndices (index associated to a FEATURE) // matches the entry in EnumInputFeatures associated to this FEATURE // if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from track -#define CHECK_AND_FILL_MUON_TRACK(FEATURE, GETTER) \ +// by calling the corresponding GETTER expression +#define CHECK_AND_FILL_FEATURE(FEATURE, GETTER) \ case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = muon.GETTER(); \ + inputFeature = (GETTER); \ break; \ } // Check if the index of mCachedIndices (index associated to a FEATURE) // matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from track -#define CHECK_AND_FILL_MUONGLOB_TRACK(FEATURE, GETTER) \ - case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = muonglob.GETTER(); \ - break; \ - } - -// Check if the index of mCachedIndices (index associated to a FEATURE) -// matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from track -#define CHECK_AND_FILL_MFT_TRACK(FEATURE, GETTER) \ - case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = mft.GETTER(); \ - break; \ - } - -// Check if the index of mCachedIndices (index associated to a FEATURE) -// matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from track -#define CHECK_AND_FILL_MUON_COV(FEATURE, GETTER) \ - case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = muoncov.GETTER(); \ - break; \ - } - -// Check if the index of mCachedIndices (index associated to a FEATURE) -// matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from track -#define CHECK_AND_FILL_MFT_COV(FEATURE, GETTER) \ - case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = mftcov.GETTER(); \ - break; \ +// if so, and if OBJECT.GETTER() is a valid function invocation, +// the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER function +#define CHECK_AND_FILL_FEATURE_OPTIONAL_NO_EXPR(FEATURE, OBJECT, GETTER) \ + case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ + if constexpr (requires(decltype(OBJECT) t) { { t.GETTER() } -> std::convertible_to; }) { \ + inputFeature = (OBJECT.GETTER()); \ + } else { \ + inputFeature = 0; \ + } \ + break; \ } // Check if the index of mCachedIndices (index associated to a FEATURE) // matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER1 and GETTER2 from track. -#define CHECK_AND_FILL_MFTMUON_DIFF(FEATURE, GETTER1, GETTER2) \ - case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ - inputFeature = (mft.GETTER2() - muon.GETTER1()); \ - break; \ +// if so, and if OBJECT.FUNC() is a valid function invocation, +// the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER expression +#define CHECK_AND_FILL_FEATURE_OPTIONAL_WITH_EXPR(FEATURE, OBJECT, FUNC, GETTER) \ + case static_cast(InputFeaturesMFTMuonMatch::FEATURE): { \ + if constexpr (requires(decltype(OBJECT) t) { { t.FUNC() } -> std::convertible_to; }) { \ + inputFeature = (GETTER); \ + } else { \ + inputFeature = 0; \ + } \ + break; \ } -// Check if the index of mCachedIndices (index associated to a FEATURE) -// matches the entry in EnumInputFeatures associated to this FEATURE -// if so, the inputFeatures vector is filled with the FEATURE's value -// by calling the corresponding GETTER=FEATURE from collision -#define CHECK_AND_FILL_MFTMUON_COLLISION(GETTER) \ - case static_cast(InputFeaturesMFTMuonMatch::GETTER): { \ - inputFeature = collision.GETTER(); \ - break; \ - } +#define __EXPAND(x) x +#define __GET_MACRO(_1, _2, _3, _4, name, ...) name +#define CHECK_AND_FILL_FEATURE_OPTIONAL(...) __EXPAND(__GET_MACRO(__VA_ARGS__, CHECK_AND_FILL_FEATURE_OPTIONAL_WITH_EXPR, CHECK_AND_FILL_FEATURE_OPTIONAL_NO_EXPR)(__VA_ARGS__)) namespace o2::analysis { // possible input features for ML enum class InputFeaturesMFTMuonMatch : uint8_t { zMatching, + // MFT track parameters xMFT, yMFT, qOverptMFT, tglMFT, phiMFT, + ptMFT, + etaMFT, + timeMFT, + timeResMFT, + clusterSizesAndTrackFlagsMFT, + trackTypeMFT, dcaXY, dcaZ, chi2MFT, nClustersMFT, + // MCH track parameters xMCH, yMCH, qOverptMCH, tglMCH, phiMCH, + ptMCH, + etaMCH, + timeMCH, + timeResMCH, nClustersMCH, chi2MCH, pdca, Rabs, + // MFT covariances cXXMFT, cXYMFT, cYYMFT, @@ -140,6 +128,7 @@ enum class InputFeaturesMFTMuonMatch : uint8_t { c1PtPhiMFT, c1PtTglMFT, c1Pt21Pt2MFT, + // MCH covariances cXXMCH, cXYMCH, cYYMCH, @@ -155,17 +144,32 @@ enum class InputFeaturesMFTMuonMatch : uint8_t { c1PtPhiMCH, c1PtTglMCH, c1Pt21Pt2MCH, + // track residuals deltaX, deltaY, deltaPhi, + deltaTgl, deltaEta, deltaPt, + deltaR, + deltaDirection, + sameSign, + pullX, + pullY, + pullPhi, + pullTgl, + pullEta, + pullPt, + pullR, + deltaPtRel, + // primary vertex parameters posX, posY, posZ, numContrib, trackOccupancyInTimeRange, ft0cOccupancyInTimeRange, + multMFT, multFT0A, multFT0C, multNTracksPV, @@ -177,10 +181,47 @@ enum class InputFeaturesMFTMuonMatch : uint8_t { centFT0M, centFT0A, centFT0C, + // global forward track parameters chi2MCHMFT, - chi2GlobMUON + chi2GlobMUON, + dcaX, + dcaY, + isAmbig }; +template +float getDeltaR(T1 const& mftprop, T2 const& mchprop) +{ + return std::sqrt((mchprop.getX() - mftprop.getX()) * (mchprop.getX() - mftprop.getX()) + (mchprop.getY() - mftprop.getY()) * (mchprop.getY() - mftprop.getY())); +} + +template +float getPullR(T1 const& mftprop, T2 const& mchprop) +{ + double deltaR = getDeltaR(mftprop, mchprop); + double err2X = mftprop.getCovariances()(0, 0) + mchprop.getCovariances()(0, 0); + double err2Y = mftprop.getCovariances()(1, 1) + mchprop.getCovariances()(1, 1); + double errR = std::sqrt(err2X + err2Y); + return deltaR / errR; +} + +template +float getDeltaDirection(T1 const& mftprop, T2 const& mchprop) +{ + double cos2 = std::cos(mchprop.getPhi()) * std::cos(mftprop.getPhi()); + double sin2 = std::sin(mchprop.getPhi()) * std::sin(mftprop.getPhi()); + double tgl2 = mchprop.getTgl() * mftprop.getTgl(); + double cosDelta = (cos2 + sin2 + tgl2) / (std::sqrt(mchprop.getTgl() * mchprop.getTgl() + 1) * std::sqrt(mftprop.getTgl() * mftprop.getTgl() + 1)); + return static_cast(std::acos(std::clamp(cosDelta, -1.0, 1.0))); +} + +float getPull(float mftVal, float mftErr2, float mchVal, float mchErr2) +{ + float delta = mchVal - mftVal; + float err = std::sqrt(mchErr2 + mftErr2); + return (err > 0 ? delta / err : delta); +} + template class MlResponseMFTMuonMatch : public MlResponse { @@ -190,113 +231,118 @@ class MlResponseMFTMuonMatch : public MlResponse /// Default destructor virtual ~MlResponseMFTMuonMatch() = default; - template - float returnFeature(uint8_t idx, T1 const& muon, T2 const& mft, C1 const& muoncov, C2 const& mftcov, U const& collision) - { - float inputFeature = 0.; - switch (idx) { - CHECK_AND_FILL_MFT_TRACK(zMatching, z); - CHECK_AND_FILL_MFT_TRACK(xMFT, x); - CHECK_AND_FILL_MFT_TRACK(yMFT, y); - CHECK_AND_FILL_MFT_TRACK(qOverptMFT, signed1Pt); - CHECK_AND_FILL_MFT_TRACK(tglMFT, tgl); - CHECK_AND_FILL_MFT_TRACK(phiMFT, phi); - CHECK_AND_FILL_MFT_TRACK(chi2MFT, chi2); - CHECK_AND_FILL_MFT_TRACK(nClustersMFT, nClusters); - CHECK_AND_FILL_MUON_TRACK(dcaXY, fwddcaXY); - CHECK_AND_FILL_MUON_TRACK(dcaZ, fwddcaz); - CHECK_AND_FILL_MUON_TRACK(xMCH, x); - CHECK_AND_FILL_MUON_TRACK(yMCH, y); - CHECK_AND_FILL_MUON_TRACK(qOverptMCH, signed1Pt); - CHECK_AND_FILL_MUON_TRACK(tglMCH, tgl); - CHECK_AND_FILL_MUON_TRACK(phiMCH, phi); - CHECK_AND_FILL_MUON_TRACK(nClustersMCH, nClusters); - CHECK_AND_FILL_MUON_TRACK(chi2MCH, chi2); - CHECK_AND_FILL_MUON_TRACK(pdca, pDca); - CHECK_AND_FILL_MFT_COV(cXXMFT, cXX); - CHECK_AND_FILL_MFT_COV(cXYMFT, cXY); - CHECK_AND_FILL_MFT_COV(cYYMFT, cYY); - CHECK_AND_FILL_MFT_COV(cPhiYMFT, cPhiY); - CHECK_AND_FILL_MFT_COV(cPhiXMFT, cPhiX); - CHECK_AND_FILL_MFT_COV(cPhiPhiMFT, cPhiPhi); - CHECK_AND_FILL_MFT_COV(cTglYMFT, cTglY); - CHECK_AND_FILL_MFT_COV(cTglXMFT, cTglX); - CHECK_AND_FILL_MFT_COV(cTglPhiMFT, cTglPhi); - CHECK_AND_FILL_MFT_COV(cTglTglMFT, cTglTgl); - CHECK_AND_FILL_MFT_COV(c1PtYMFT, c1PtY); - CHECK_AND_FILL_MFT_COV(c1PtXMFT, c1PtX); - CHECK_AND_FILL_MFT_COV(c1PtPhiMFT, c1PtPhi); - CHECK_AND_FILL_MFT_COV(c1PtTglMFT, c1PtTgl); - CHECK_AND_FILL_MFT_COV(c1Pt21Pt2MFT, c1Pt21Pt2); - CHECK_AND_FILL_MUON_COV(cXXMCH, cXX); - CHECK_AND_FILL_MUON_COV(cXYMCH, cXY); - CHECK_AND_FILL_MUON_COV(cYYMCH, cYY); - CHECK_AND_FILL_MUON_COV(cPhiYMCH, cPhiY); - CHECK_AND_FILL_MUON_COV(cPhiXMCH, cPhiX); - CHECK_AND_FILL_MUON_COV(cPhiPhiMCH, cPhiPhi); - CHECK_AND_FILL_MUON_COV(cTglYMCH, cTglY); - CHECK_AND_FILL_MUON_COV(cTglXMCH, cTglX); - CHECK_AND_FILL_MUON_COV(cTglPhiMCH, cTglPhi); - CHECK_AND_FILL_MUON_COV(cTglTglMCH, cTglTgl); - CHECK_AND_FILL_MUON_COV(c1PtYMCH, c1PtY); - CHECK_AND_FILL_MUON_COV(c1PtXMCH, c1PtX); - CHECK_AND_FILL_MUON_COV(c1PtPhiMCH, c1PtPhi); - CHECK_AND_FILL_MUON_COV(c1PtTglMCH, c1PtTgl); - CHECK_AND_FILL_MUON_COV(c1Pt21Pt2MCH, c1Pt21Pt2); - CHECK_AND_FILL_MFTMUON_COLLISION(posX); - CHECK_AND_FILL_MFTMUON_COLLISION(posY); - CHECK_AND_FILL_MFTMUON_COLLISION(posZ); - CHECK_AND_FILL_MFTMUON_COLLISION(numContrib); - CHECK_AND_FILL_MFTMUON_COLLISION(trackOccupancyInTimeRange); - CHECK_AND_FILL_MFTMUON_COLLISION(ft0cOccupancyInTimeRange); - CHECK_AND_FILL_MFTMUON_COLLISION(multFT0A); - CHECK_AND_FILL_MFTMUON_COLLISION(multFT0C); - CHECK_AND_FILL_MFTMUON_COLLISION(multNTracksPV); - CHECK_AND_FILL_MFTMUON_COLLISION(multNTracksPVeta1); - CHECK_AND_FILL_MFTMUON_COLLISION(multNTracksPVetaHalf); - CHECK_AND_FILL_MFTMUON_COLLISION(isInelGt0); - CHECK_AND_FILL_MFTMUON_COLLISION(isInelGt1); - CHECK_AND_FILL_MFTMUON_COLLISION(multFT0M); - CHECK_AND_FILL_MFTMUON_COLLISION(centFT0M); - CHECK_AND_FILL_MFTMUON_COLLISION(centFT0A); - CHECK_AND_FILL_MFTMUON_COLLISION(centFT0C); - CHECK_AND_FILL_MUON_TRACK(chi2MCHMFT, chi2MatchMCHMFT); - } - return inputFeature; - } - - template - float returnFeatureGlob(uint8_t idx, T1 const& muonglob, T2 const& muon, T3 const& mft, U const& collision) - { - float inputFeature = 0.; - switch (idx) { - CHECK_AND_FILL_MFT_TRACK(xMFT, getX); - CHECK_AND_FILL_MFT_TRACK(yMFT, getY); - CHECK_AND_FILL_MFT_TRACK(qOverptMFT, getInvQPt); - CHECK_AND_FILL_MFT_TRACK(tglMFT, getTanl); - CHECK_AND_FILL_MFT_TRACK(phiMFT, getPhi); - CHECK_AND_FILL_MFT_TRACK(chi2MFT, getTrackChi2); - CHECK_AND_FILL_MUON_TRACK(xMCH, getX); - CHECK_AND_FILL_MUON_TRACK(yMCH, getY); - CHECK_AND_FILL_MUON_TRACK(qOverptMCH, getInvQPt); - CHECK_AND_FILL_MUON_TRACK(tglMCH, getTanl); - CHECK_AND_FILL_MUON_TRACK(phiMCH, getPhi); - CHECK_AND_FILL_MUON_TRACK(chi2MCH, getTrackChi2); - CHECK_AND_FILL_MUONGLOB_TRACK(chi2MCHMFT, chi2MatchMCHMFT); - CHECK_AND_FILL_MUONGLOB_TRACK(chi2GlobMUON, chi2); - CHECK_AND_FILL_MUONGLOB_TRACK(Rabs, rAtAbsorberEnd); - // Below are dummy files to remove warning of unused parameters - CHECK_AND_FILL_MFTMUON_COLLISION(posZ); - } - return inputFeature; - } - - template - float returnFeatureTest(uint8_t idx, T1 const& muon) + template + float returnFeature(uint8_t idx, T1 const& muon, T2 const& mft, T3 const& mch, T4 const& mftprop, T5 const& mchprop, U const& collision) { float inputFeature = 0.; switch (idx) { - CHECK_AND_FILL_MUON_TRACK(chi2MCHMFT, chi2MatchMCHMFT); + // matching parameters + CHECK_AND_FILL_FEATURE(zMatching, mftprop.getZ()); + // MFT track parameters + CHECK_AND_FILL_FEATURE(xMFT, mftprop.getX()); + CHECK_AND_FILL_FEATURE(yMFT, mftprop.getY()); + CHECK_AND_FILL_FEATURE(qOverptMFT, mftprop.getInvQPt()); + CHECK_AND_FILL_FEATURE(tglMFT, mftprop.getTanl()); + CHECK_AND_FILL_FEATURE(phiMFT, mftprop.getPhi()); + CHECK_AND_FILL_FEATURE(chi2MFT, mft.chi2()); + CHECK_AND_FILL_FEATURE(nClustersMFT, mft.nClusters()); + /*dummy value*/ CHECK_AND_FILL_FEATURE(dcaXY, 0); + /*dummy value*/ CHECK_AND_FILL_FEATURE(dcaZ, 0); + CHECK_AND_FILL_FEATURE(ptMFT, mftprop.getPt()); + CHECK_AND_FILL_FEATURE(etaMFT, mftprop.getEta()); + CHECK_AND_FILL_FEATURE(timeMFT, mft.trackTime()); + CHECK_AND_FILL_FEATURE(timeResMFT, mft.trackTimeRes()); + CHECK_AND_FILL_FEATURE(clusterSizesAndTrackFlagsMFT, mft.mftClusterSizesAndTrackFlags()); + CHECK_AND_FILL_FEATURE(trackTypeMFT, (mft.isCA() ? 1 : 0)); + // MCH track parameters + CHECK_AND_FILL_FEATURE(xMCH, mchprop.getX()); + CHECK_AND_FILL_FEATURE(yMCH, mchprop.getY()); + CHECK_AND_FILL_FEATURE(qOverptMCH, mchprop.getInvQPt()); + CHECK_AND_FILL_FEATURE(tglMCH, mchprop.getTanl()); + CHECK_AND_FILL_FEATURE(phiMCH, mchprop.getPhi()); + CHECK_AND_FILL_FEATURE(ptMCH, mchprop.getPt()); + CHECK_AND_FILL_FEATURE(etaMCH, mchprop.getEta()); + CHECK_AND_FILL_FEATURE(timeMCH, mch.trackTime()); + CHECK_AND_FILL_FEATURE(timeResMCH, mch.trackTimeRes()); + CHECK_AND_FILL_FEATURE(nClustersMCH, mch.nClusters()); + CHECK_AND_FILL_FEATURE(chi2MCH, mch.chi2()); + CHECK_AND_FILL_FEATURE(pdca, muon.pDca()); + CHECK_AND_FILL_FEATURE(Rabs, muon.rAtAbsorberEnd()); + // MFT covariances + CHECK_AND_FILL_FEATURE(cXXMFT, mftprop.getCovariances()(0, 0)); + CHECK_AND_FILL_FEATURE(cXYMFT, mftprop.getCovariances()(0, 1)); + CHECK_AND_FILL_FEATURE(cYYMFT, mftprop.getCovariances()(1, 1)); + CHECK_AND_FILL_FEATURE(cPhiXMFT, mftprop.getCovariances()(0, 2)); + CHECK_AND_FILL_FEATURE(cPhiYMFT, mftprop.getCovariances()(1, 2)); + CHECK_AND_FILL_FEATURE(cPhiPhiMFT, mftprop.getCovariances()(2, 2)); + CHECK_AND_FILL_FEATURE(cTglXMFT, mftprop.getCovariances()(0, 3)); + CHECK_AND_FILL_FEATURE(cTglYMFT, mftprop.getCovariances()(1, 3)); + CHECK_AND_FILL_FEATURE(cTglPhiMFT, mftprop.getCovariances()(2, 3)); + CHECK_AND_FILL_FEATURE(cTglTglMFT, mftprop.getCovariances()(3, 3)); + CHECK_AND_FILL_FEATURE(c1PtXMFT, mftprop.getCovariances()(0, 4)); + CHECK_AND_FILL_FEATURE(c1PtYMFT, mftprop.getCovariances()(1, 4)); + CHECK_AND_FILL_FEATURE(c1PtPhiMFT, mftprop.getCovariances()(2, 4)); + CHECK_AND_FILL_FEATURE(c1PtTglMFT, mftprop.getCovariances()(3, 4)); + CHECK_AND_FILL_FEATURE(c1Pt21Pt2MFT, mftprop.getCovariances()(4, 4)); + // MCH covariances + CHECK_AND_FILL_FEATURE(cXXMCH, mchprop.getCovariances()(0, 0)); + CHECK_AND_FILL_FEATURE(cXYMCH, mchprop.getCovariances()(0, 1)); + CHECK_AND_FILL_FEATURE(cYYMCH, mchprop.getCovariances()(1, 1)); + CHECK_AND_FILL_FEATURE(cPhiXMCH, mchprop.getCovariances()(0, 2)); + CHECK_AND_FILL_FEATURE(cPhiYMCH, mchprop.getCovariances()(1, 2)); + CHECK_AND_FILL_FEATURE(cPhiPhiMCH, mchprop.getCovariances()(2, 2)); + CHECK_AND_FILL_FEATURE(cTglXMCH, mchprop.getCovariances()(0, 3)); + CHECK_AND_FILL_FEATURE(cTglYMCH, mchprop.getCovariances()(1, 3)); + CHECK_AND_FILL_FEATURE(cTglPhiMCH, mchprop.getCovariances()(2, 3)); + CHECK_AND_FILL_FEATURE(cTglTglMCH, mchprop.getCovariances()(3, 3)); + CHECK_AND_FILL_FEATURE(c1PtXMCH, mchprop.getCovariances()(0, 4)); + CHECK_AND_FILL_FEATURE(c1PtYMCH, mchprop.getCovariances()(1, 4)); + CHECK_AND_FILL_FEATURE(c1PtPhiMCH, mchprop.getCovariances()(2, 4)); + CHECK_AND_FILL_FEATURE(c1PtTglMCH, mchprop.getCovariances()(3, 4)); + CHECK_AND_FILL_FEATURE(c1Pt21Pt2MCH, mchprop.getCovariances()(4, 4)); + // Track residuals + CHECK_AND_FILL_FEATURE(deltaX, mchprop.getX() - mftprop.getX()); + CHECK_AND_FILL_FEATURE(deltaY, mchprop.getY() - mftprop.getY()); + CHECK_AND_FILL_FEATURE(deltaPhi, mchprop.getPhi() - mftprop.getPhi()); + CHECK_AND_FILL_FEATURE(deltaTgl, mchprop.getTgl() - mftprop.getTgl()); + CHECK_AND_FILL_FEATURE(deltaEta, mchprop.getEta() - mftprop.getEta()); + CHECK_AND_FILL_FEATURE(deltaPt, mchprop.getPt() - mftprop.getPt()); + CHECK_AND_FILL_FEATURE(deltaR, getDeltaR(mftprop, mchprop)); + CHECK_AND_FILL_FEATURE(deltaDirection, getDeltaDirection(mftprop, mchprop)); + CHECK_AND_FILL_FEATURE(deltaPtRel, (mchprop.getPt() - mftprop.getPt()) / (mchprop.getPt() + mftprop.getPt())); + CHECK_AND_FILL_FEATURE(sameSign, (mch.sign() == mft.sign()) ? 1 : 0); + CHECK_AND_FILL_FEATURE(pullX, getPull(mftprop.getX(), mftprop.getCovariances()(0, 0), mchprop.getX(), mchprop.getCovariances()(0, 0))); + CHECK_AND_FILL_FEATURE(pullY, getPull(mftprop.getY(), mftprop.getCovariances()(1, 1), mchprop.getY(), mchprop.getCovariances()(1, 1))); + CHECK_AND_FILL_FEATURE(pullPhi, getPull(mftprop.getPhi(), mftprop.getCovariances()(2, 2), mchprop.getPhi(), mchprop.getCovariances()(2, 2))); + CHECK_AND_FILL_FEATURE(pullTgl, getPull(mftprop.getTgl(), mftprop.getCovariances()(3, 3), mchprop.getTgl(), mchprop.getCovariances()(3, 3))); + /*dummy value*/ CHECK_AND_FILL_FEATURE(pullEta, 0); + /*dummy value*/ CHECK_AND_FILL_FEATURE(pullPt, 0); + CHECK_AND_FILL_FEATURE(pullR, getPullR(mftprop, mchprop)); + // primary vertex parameters + CHECK_AND_FILL_FEATURE(posX, collision.posX()); + CHECK_AND_FILL_FEATURE(posY, collision.posY()); + CHECK_AND_FILL_FEATURE(posZ, collision.posZ()); + CHECK_AND_FILL_FEATURE_OPTIONAL(numContrib, collision, numContrib); + CHECK_AND_FILL_FEATURE_OPTIONAL(trackOccupancyInTimeRange, collision, trackOccupancyInTimeRange); + CHECK_AND_FILL_FEATURE_OPTIONAL(ft0cOccupancyInTimeRange, collision, ft0cOccupancyInTimeRange); + CHECK_AND_FILL_FEATURE_OPTIONAL(multMFT, collision, mftNtracks); + CHECK_AND_FILL_FEATURE_OPTIONAL(multFT0A, collision, multFT0A); + CHECK_AND_FILL_FEATURE_OPTIONAL(multFT0C, collision, multFT0C); + CHECK_AND_FILL_FEATURE_OPTIONAL(multNTracksPV, collision, multNTracksPV); + CHECK_AND_FILL_FEATURE_OPTIONAL(multNTracksPVeta1, collision, multNTracksPVeta1); + CHECK_AND_FILL_FEATURE_OPTIONAL(multNTracksPVetaHalf, collision, multNTracksPVetaHalf); + CHECK_AND_FILL_FEATURE_OPTIONAL(isInelGt0, collision, isInelGt0); + CHECK_AND_FILL_FEATURE_OPTIONAL(isInelGt1, collision, isInelGt1); + CHECK_AND_FILL_FEATURE_OPTIONAL(multFT0M, collision, multFT0M); + CHECK_AND_FILL_FEATURE_OPTIONAL(centFT0M, collision, centFT0M); + CHECK_AND_FILL_FEATURE_OPTIONAL(centFT0A, collision, centFT0A); + CHECK_AND_FILL_FEATURE_OPTIONAL(centFT0C, collision, centFT0C); + // global forward track parameters + CHECK_AND_FILL_FEATURE(chi2MCHMFT, muon.chi2MatchMCHMFT()); + CHECK_AND_FILL_FEATURE(chi2GlobMUON, muon.chi2()); + CHECK_AND_FILL_FEATURE_OPTIONAL(dcaX, muon, fwdDcaX); + CHECK_AND_FILL_FEATURE_OPTIONAL(dcaY, muon, fwdDcaX); + CHECK_AND_FILL_FEATURE_OPTIONAL(isAmbig, muon, compatibleCollIds, (muon.compatibleCollIds().size() == 1) ? 0 : 1); } return inputFeature; } @@ -304,34 +350,12 @@ class MlResponseMFTMuonMatch : public MlResponse /// Method to get the input features vector needed for ML inference /// \param track is the single track, \param collision is the collision /// \return inputFeatures vector - template - std::vector getInputFeatures(T1 const& muon, T2 const& mft, C1 const& muoncov, C2 const& mftcov, U const& collision) - { - std::vector inputFeatures; - for (const auto& idx : MlResponse::mCachedIndices) { - float inputFeature = returnFeature(idx, muon, mft, muoncov, mftcov, collision); - inputFeatures.emplace_back(inputFeature); - } - return inputFeatures; - } - - template - std::vector getInputFeaturesTest(T1 const& muon) - { - std::vector inputFeatures; - for (const auto& idx : MlResponse::mCachedIndices) { - float inputFeature = returnFeatureTest(idx, muon); - inputFeatures.emplace_back(inputFeature); - } - return inputFeatures; - } - - template - std::vector getInputFeaturesGlob(T1 const& muonglob, T2 const& muon, T3 const& mft, U const& collision) + template + std::vector getInputFeatures(T1 const& muon, T2 const& mft, T3 const& mch, T4 const& mftprop, T5 const& mchprop, U const& collision) { std::vector inputFeatures; for (const auto& idx : MlResponse::mCachedIndices) { - float inputFeature = returnFeatureGlob(idx, muonglob, muon, mft, collision); + float inputFeature = returnFeature(idx, muon, mft, mch, mftprop, mchprop, collision); inputFeatures.emplace_back(inputFeature); } return inputFeatures; @@ -361,25 +385,39 @@ class MlResponseMFTMuonMatch : public MlResponse void setAvailableInputFeatures() { MlResponse::mAvailableInputFeatures = { + // matching parameters FILL_MAP_MFTMUON_MATCH(zMatching), + // MFT track parameters FILL_MAP_MFTMUON_MATCH(xMFT), FILL_MAP_MFTMUON_MATCH(yMFT), FILL_MAP_MFTMUON_MATCH(qOverptMFT), FILL_MAP_MFTMUON_MATCH(tglMFT), FILL_MAP_MFTMUON_MATCH(phiMFT), + FILL_MAP_MFTMUON_MATCH(ptMFT), + FILL_MAP_MFTMUON_MATCH(etaMFT), + FILL_MAP_MFTMUON_MATCH(timeMFT), + FILL_MAP_MFTMUON_MATCH(timeResMFT), FILL_MAP_MFTMUON_MATCH(dcaXY), FILL_MAP_MFTMUON_MATCH(dcaZ), FILL_MAP_MFTMUON_MATCH(chi2MFT), + FILL_MAP_MFTMUON_MATCH(clusterSizesAndTrackFlagsMFT), + FILL_MAP_MFTMUON_MATCH(trackTypeMFT), FILL_MAP_MFTMUON_MATCH(nClustersMFT), + // MCH track parameters FILL_MAP_MFTMUON_MATCH(xMCH), FILL_MAP_MFTMUON_MATCH(yMCH), FILL_MAP_MFTMUON_MATCH(qOverptMCH), FILL_MAP_MFTMUON_MATCH(tglMCH), FILL_MAP_MFTMUON_MATCH(phiMCH), FILL_MAP_MFTMUON_MATCH(nClustersMCH), + FILL_MAP_MFTMUON_MATCH(ptMCH), + FILL_MAP_MFTMUON_MATCH(etaMCH), + FILL_MAP_MFTMUON_MATCH(timeMCH), + FILL_MAP_MFTMUON_MATCH(timeResMCH), FILL_MAP_MFTMUON_MATCH(chi2MCH), FILL_MAP_MFTMUON_MATCH(pdca), FILL_MAP_MFTMUON_MATCH(Rabs), + // MFT covariances FILL_MAP_MFTMUON_MATCH(cXXMFT), FILL_MAP_MFTMUON_MATCH(cXYMFT), FILL_MAP_MFTMUON_MATCH(cYYMFT), @@ -395,6 +433,7 @@ class MlResponseMFTMuonMatch : public MlResponse FILL_MAP_MFTMUON_MATCH(c1PtPhiMFT), FILL_MAP_MFTMUON_MATCH(c1PtTglMFT), FILL_MAP_MFTMUON_MATCH(c1Pt21Pt2MFT), + // MCH covariances FILL_MAP_MFTMUON_MATCH(cXXMCH), FILL_MAP_MFTMUON_MATCH(cXYMCH), FILL_MAP_MFTMUON_MATCH(cYYMCH), @@ -410,8 +449,49 @@ class MlResponseMFTMuonMatch : public MlResponse FILL_MAP_MFTMUON_MATCH(c1PtPhiMCH), FILL_MAP_MFTMUON_MATCH(c1PtTglMCH), FILL_MAP_MFTMUON_MATCH(c1Pt21Pt2MCH), + // track residuals + FILL_MAP_MFTMUON_MATCH(deltaX), + FILL_MAP_MFTMUON_MATCH(deltaY), + FILL_MAP_MFTMUON_MATCH(deltaPhi), + FILL_MAP_MFTMUON_MATCH(deltaTgl), + FILL_MAP_MFTMUON_MATCH(deltaEta), + FILL_MAP_MFTMUON_MATCH(deltaPt), + FILL_MAP_MFTMUON_MATCH(deltaR), + FILL_MAP_MFTMUON_MATCH(deltaDirection), + FILL_MAP_MFTMUON_MATCH(sameSign), + FILL_MAP_MFTMUON_MATCH(pullX), + FILL_MAP_MFTMUON_MATCH(pullY), + FILL_MAP_MFTMUON_MATCH(pullPhi), + FILL_MAP_MFTMUON_MATCH(pullTgl), + FILL_MAP_MFTMUON_MATCH(pullEta), + FILL_MAP_MFTMUON_MATCH(pullPt), + FILL_MAP_MFTMUON_MATCH(pullR), + FILL_MAP_MFTMUON_MATCH(deltaPtRel), + // primary vertex parameters + FILL_MAP_MFTMUON_MATCH(posX), + FILL_MAP_MFTMUON_MATCH(posY), + FILL_MAP_MFTMUON_MATCH(posZ), + FILL_MAP_MFTMUON_MATCH(numContrib), + FILL_MAP_MFTMUON_MATCH(trackOccupancyInTimeRange), + FILL_MAP_MFTMUON_MATCH(ft0cOccupancyInTimeRange), + FILL_MAP_MFTMUON_MATCH(multMFT), + FILL_MAP_MFTMUON_MATCH(multFT0A), + FILL_MAP_MFTMUON_MATCH(multFT0C), + FILL_MAP_MFTMUON_MATCH(multNTracksPV), + FILL_MAP_MFTMUON_MATCH(multNTracksPVeta1), + FILL_MAP_MFTMUON_MATCH(multNTracksPVetaHalf), + FILL_MAP_MFTMUON_MATCH(isInelGt0), + FILL_MAP_MFTMUON_MATCH(isInelGt1), + FILL_MAP_MFTMUON_MATCH(multFT0M), + FILL_MAP_MFTMUON_MATCH(centFT0M), + FILL_MAP_MFTMUON_MATCH(centFT0A), + FILL_MAP_MFTMUON_MATCH(centFT0C), + // global forward track parameters FILL_MAP_MFTMUON_MATCH(chi2MCHMFT), - FILL_MAP_MFTMUON_MATCH(chi2GlobMUON)}; + FILL_MAP_MFTMUON_MATCH(chi2GlobMUON), + FILL_MAP_MFTMUON_MATCH(dcaX), + FILL_MAP_MFTMUON_MATCH(dcaY), + FILL_MAP_MFTMUON_MATCH(isAmbig)}; } uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features diff --git a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx index 39cee24788c..ab35ad8b31f 100644 --- a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx @@ -1041,12 +1041,6 @@ struct TableMakerMC { if (static_cast(muon.trackType()) < 2) { auto muonID = muon.matchMCHTrackId(); auto chi2 = muon.chi2MatchMCHMFT(); - if (fConfigVariousOptions.fUseML.value) { - std::vector output; - std::vector inputML = matchingMlResponse.getInputFeaturesTest(muon); - matchingMlResponse.isSelectedMl(inputML, 0, output); - chi2 = output[0]; - } if (mCandidates.find(muonID) == mCandidates.end()) { mCandidates[muonID] = {chi2, muon.globalIndex()}; } else { @@ -1078,7 +1072,7 @@ struct TableMakerMC { muonprop = VarManager::PropagateMuon(muontrack, collision, VarManager::kToMatching); } std::vector output; - std::vector inputML = matchingMlResponse.getInputFeaturesGlob(muon, muonprop, mftprop, collision); + std::vector inputML = matchingMlResponse.getInputFeatures(muon, mfttrack, muontrack, mftprop, muonprop, collision); matchingMlResponse.isSelectedMl(inputML, 0, output); float score = output[0]; if (mCandidates.find(muonID) == mCandidates.end()) { diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 1ae278c9301..87010bdb21a 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -1494,7 +1494,7 @@ struct TableMaker { muonprop = VarManager::PropagateMuon(muontrack, collision, VarManager::kToMatching); } std::vector output; - std::vector inputML = matchingMlResponse.getInputFeaturesGlob(muon, muonprop, mftprop, collision); + std::vector inputML = matchingMlResponse.getInputFeatures(muon, mfttrack, muontrack, mftprop, muonprop, collision); matchingMlResponse.isSelectedMl(inputML, 0, output); float score = output[0]; if (mCandidates.find(muonID) == mCandidates.end()) { diff --git a/PWGDQ/Tasks/mftMchMatcher.cxx b/PWGDQ/Tasks/mftMchMatcher.cxx index 2c299f0e42c..5c8f668e5e8 100644 --- a/PWGDQ/Tasks/mftMchMatcher.cxx +++ b/PWGDQ/Tasks/mftMchMatcher.cxx @@ -549,7 +549,7 @@ struct mftMchMatcher { auto const& mchTrack = muonTrack.template matchMCHTrack_as(); auto const& mftTrack = muonTrack.template matchMFTTrack_as(); - if (!muonTrack.has_mcParticle() || !mftTrack.has_mcParticle()) { + if (!mchTrack.has_mcParticle() || !mftTrack.has_mcParticle()) { // if either the MCH or the MFT tracks are fakes (not associated to any MC particles) // we consider the match as fake return (isBestMatch ? kMatchTypeFakeLeading : kMatchTypeFakeNonLeading); diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index bf0e7beb53a..4ca6f69ecd4 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -17,7 +17,11 @@ #include "PWGDQ/Core/VarManager.h" #include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Tools/ML/MlResponse.h" #include @@ -155,9 +159,9 @@ DECLARE_SOA_TABLE(QaMatchingCandidates, "AOD", "QAMCAND", qamatching::PzAtVtx); } // namespace o2::aod -using MyEvents = soa::Join; +using MyEvents = soa::Join; using MyMuons = soa::Join; -using MyMuonsMC = soa::Join; +using MyMuonsMC = soa::Join; using MyMFTs = aod::MFTTracks; using MyMFTCovariances = aod::MFTTracksCov; using MyMFTsMC = soa::Join; @@ -2734,7 +2738,7 @@ struct QaMatching { // run the ML model std::vector output; - std::vector inputML = mlResponse.getInputFeaturesGlob(muonTrack, mchTrackProp, mftTrackProp, collision); + std::vector inputML = mlResponse.getInputFeatures(muonTrack, mftTrack, mchTrack, mftTrackProp, mchTrackProp, collision); mlResponse.isSelectedMl(inputML, 0, output); float matchScore = output[0]; float matchChi2Prod = muonTrack.chi2MatchMCHMFT() / MatchingDegreesOfFreedom; From 6e0c72eb9d71c946d721daa60dfac73881b35354 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Wed, 20 May 2026 14:55:44 +0800 Subject: [PATCH 237/449] [PWGCF] jEPFlowAnalysis.cxx: defining q2 selection function, adding multiplicity dependent selection, adding q2 dependent denominator histograms (#16300) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 52 +++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 7e515140b8b..cd6f6a44190 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -112,8 +112,9 @@ struct JEPFlowAnalysis { Configurable cfgVertexZ{"cfgVertexZ", 10.0, "Maximum vertex Z selection"}; Configurable cfgq2analysis{"cfgq2analysis", false, "ese analysis flag"}; - Configurable cfgq2high{"cfgq2high", 10.0, "high q2 selection"}; - Configurable cfgq2low{"cfgq2low", 0.0, "low q2 selection"}; + Configurable> cfgMultq2SelBin{"cfgMultq2SelBin", {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 100}, ""}; + Configurable> cfgMultq2high{"cfgMultq2high", {}, ""}; + Configurable> cfgMultq2low{"cfgMultq2low", {}, ""}; Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; Configurable cfgRefAName{"cfgRefAName", "TPCPos", "The name of detector for reference A"}; @@ -153,6 +154,29 @@ struct JEPFlowAnalysis { THn* effMap = nullptr; + bool q2sel(float q2, bool isHigh) + { + auto it = std::upper_bound(cfgMultq2SelBin->begin(), cfgMultq2SelBin->end(), cent); + int idx = std::distance(cfgMultq2SelBin->begin(), it) - 1; + + if (idx < 0) { + idx = 0; + } + if (isHigh) { + if (idx >= static_cast(cfgMultq2high->size())) { + idx = cfgMultq2high->size() - 1; + } + float sel = cfgMultq2high->at(idx); + return q2 > sel; + } else { + if (idx >= static_cast(cfgMultq2low->size())) { + idx = cfgMultq2low->size() - 1; + } + float sel = cfgMultq2low->at(idx); + return q2 < sel; + } + } + template int getdetId(const T& name) { @@ -310,6 +334,18 @@ struct JEPFlowAnalysis { epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); + if (cfgq2analysis) { + if (q2sel(q2Mag, true)) { + epFlowHistograms.fill(HIST("EpResQvecDetRefAxx_q2high"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxx_q2high"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxx_q2high"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); + } else if (q2sel(q2Mag, false)) { + epFlowHistograms.fill(HIST("EpResQvecDetRefAxx_q2low"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxx_q2low"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxx_q2low"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); + } + } + for (const auto& track : tracks) { if (cfgTrkSelFlag && trackSel(track)) continue; @@ -328,9 +364,9 @@ struct JEPFlowAnalysis { epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), track.eta(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); if (cfgq2analysis) { - if (q2Mag > cfgq2high) { + if (q2sel(q2Mag, true)) { epFlowHistograms.fill(HIST("SPvnxx_q2high"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); - } else if (q2Mag < cfgq2low) { + } else if (q2sel(q2Mag, false)) { epFlowHistograms.fill(HIST("SPvnxx_q2low"), i + 2, cent, track.pt(), track.eta(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); } } @@ -397,6 +433,14 @@ struct JEPFlowAnalysis { epFlowHistograms.add("EpResQvecDetRefBxy", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); epFlowHistograms.add("EpResQvecRefARefBxx", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); epFlowHistograms.add("EpResQvecRefARefBxy", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + if (cfgq2analysis) { + epFlowHistograms.add("EpResQvecDetRefAxx_q2high", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + epFlowHistograms.add("EpResQvecDetRefBxx_q2high", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + epFlowHistograms.add("EpResQvecRefARefBxx_q2high", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + epFlowHistograms.add("EpResQvecDetRefAxx_q2low", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + epFlowHistograms.add("EpResQvecDetRefBxx_q2low", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + epFlowHistograms.add("EpResQvecRefARefBxx_q2low", "", {HistType::kTH3F, {axisMod, axisCent, axisQvec}}); + } epFlowHistograms.add("SPvnxx", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); epFlowHistograms.add("SPvnxy", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisEta, axisQvec}}); From ca861f38784ecfab69d35ed1c619a5c809a864ba Mon Sep 17 00:00:00 2001 From: Ravindra Singh <56298081+singhra1994@users.noreply.github.com> Date: Wed, 20 May 2026 10:17:08 +0200 Subject: [PATCH 238/449] [PWGHF] Added function to correlate CharmHadron with V0 (#16316) Co-authored-by: ALICE Action Bot --- PWGHF/HFC/DataModel/CorrelationTables.h | 10 + .../TableProducer/correlatorLcScHadrons.cxx | 633 +++++++++++++----- 2 files changed, 465 insertions(+), 178 deletions(-) diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index c366a3e4186..9b2f725515a 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -224,6 +224,9 @@ DECLARE_SOA_COLUMN(PiNsigmTPC, piNsigmTPC, float); //! A DECLARE_SOA_COLUMN(PrNsigmTOF, prNsigmTOF, float); //! Associated Particle TOF nSigma Proton DECLARE_SOA_COLUMN(KaNsigmTOF, kaNsigmTOF, float); //! Associated Particle TOF nSigma Kaon DECLARE_SOA_COLUMN(PiNsigmTOF, piNsigmTOF, float); //! Associated Particle TOF nSigma Pion +DECLARE_SOA_COLUMN(MCandHadron, mCandHadron, float); //! Invariant mass of Lc/Sc+Hadron combined system +DECLARE_SOA_COLUMN(PtCombined, ptCombined, float); //! Transverse momentum of combined Lc+Hadron system +DECLARE_SOA_COLUMN(MV0, mV0, float); //! Invariant mass of V0 } // namespace hf_correlation_lc_hadron DECLARE_SOA_TABLE(PtLcFromScHPair, "AOD", "PTLCSCHPAIR", //! Sc-->Lc pT for paired Sc-proton @@ -252,6 +255,13 @@ DECLARE_SOA_TABLE(LcHadronPair, "AOD", "LCHPAIR", //! Lc-Hadrons pairs Informati aod::hf_correlation_lc_hadron::PoolBin, aod::hf_correlation_lc_hadron::IsAutoCorrelated, aod::hf_correlation_lc_hadron::Cent); +DECLARE_SOA_TABLE(CandHadronInvMass, "AOD", "CANDHIMASS", //! Lc-Hadron mass + aod::hf_correlation_lc_hadron::MCandHadron, + aod::hf_correlation_lc_hadron::PtCombined); +DECLARE_SOA_TABLE(PairedV0InvMass, "AOD", "PAIRV0IMASS", //! invarient mass of v0 which paired with charm candidates + aod::hf_correlation_lc_hadron::MV0); +DECLARE_SOA_TABLE(V0InvMass, "AOD", "V0IMASS", //! invarient mass of v0 + aod::hf_correlation_lc_hadron::MV0); DECLARE_SOA_TABLE(LcHadronRecoInfo, "AOD", "LCHRECOINFO", //! Lc-Hadrons pairs Reconstructed Informations aod::hf_correlation_lc_hadron::MLc, diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index 953e9e110dc..c29493df4a0 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -329,39 +329,44 @@ struct HfCorrelatorLcScHadrons { Produces entryTrkPID; Produces entryPairCandCharge; Produces entryCandCharge; + Produces entryLcHadronInvMass; + Produces entryPairedV0InvMass; + Produces entryV0InvMass; - Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; - Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; - Configurable applyEfficiency{"applyEfficiency", 1, "Flag for applying Lc efficiency weights"}; - Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; - Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; - Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; - Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCAxy of tracks"}; - Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCAz of tracks"}; - Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; - Configurable ptCandMax{"ptCandMax", 50., "max. cand. pT"}; - Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; - Configurable ptTrackMax{"ptTrackMax", 50., "max. track pT"}; - Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; - Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; - Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; - Configurable> binsPtLc{"binsPtLc", std::vector{o2::analysis::hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots"}; - Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle"}; - Configurable> binsPtEfficiencyLc{"binsPtEfficiencyLc", std::vector{o2::analysis::hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; - Configurable> efficiencyLc{"efficiencyLc", {1., 1., 1., 1., 1., 1.}, "efficiency values for Lc"}; - Configurable storeAutoCorrelationFlag{"storeAutoCorrelationFlag", false, "Store flag that indicates if the track is paired to its Lc mother instead of skipping it"}; - Configurable correlateLcWithLeadingParticle{"correlateLcWithLeadingParticle", false, "Switch for correlation of Lc baryons with leading particle only"}; - Configurable pidTrkApplied{"pidTrkApplied", false, "Apply PID selection for associated tracks"}; - Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Proton, o2::track::PID::Pion, o2::track::PID::Kaon}, "Trk sel: Particles species for PID, proton, pion, kaon"}; - Configurable> pidTPCMax{"pidTPCMax", std::vector{3., 0., 0.}, "maximum nSigma TPC"}; - Configurable> pidTOFMax{"pidTOFMax", std::vector{3., 0., 0.}, "maximum nSigma TOF"}; - Configurable tofPIDThreshold{"tofPIDThreshold", 0.75, "minimum pT after which TOF PID is applicable"}; - Configurable fillTrkPID{"fillTrkPID", false, "fill PID information for associated tracks"}; - Configurable forceTOF{"forceTOF", false, "fill PID information for associated tracks"}; - Configurable calTrkEff{"calTrkEff", false, "fill histograms to calculate efficiency"}; - Configurable isRecTrkPhyPrimary{"isRecTrkPhyPrimary", true, "Calculate the efficiency of reconstructed primary physical tracks"}; - Configurable calEffEventWithCand{"calEffEventWithCand", true, "Calculate the efficiency of Lc candidate"}; - Configurable eventFractionToAnalyze{"eventFractionToAnalyze", -1, "Fraction of events to analyze (use only for ME offline on very large samples)"}; + struct : ConfigurableGroup { + Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; + Configurable applyEfficiency{"applyEfficiency", 1, "Flag for applying Lc efficiency weights"}; + Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; + Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCAxy of tracks"}; + Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCAz of tracks"}; + Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; + Configurable ptCandMax{"ptCandMax", 50., "max. cand. pT"}; + Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; + Configurable ptTrackMax{"ptTrackMax", 50., "max. track pT"}; + Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; + Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; + Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; + Configurable> binsPtLc{"binsPtLc", std::vector{o2::analysis::hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots"}; + Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle"}; + Configurable> binsPtEfficiencyLc{"binsPtEfficiencyLc", std::vector{o2::analysis::hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; + Configurable> efficiencyLc{"efficiencyLc", {1., 1., 1., 1., 1., 1.}, "efficiency values for Lc"}; + Configurable storeAutoCorrelationFlag{"storeAutoCorrelationFlag", false, "Store flag that indicates if the track is paired to its Lc mother instead of skipping it"}; + Configurable correlateLcWithLeadingParticle{"correlateLcWithLeadingParticle", false, "Switch for correlation of Lc baryons with leading particle only"}; + Configurable pidTrkApplied{"pidTrkApplied", false, "Apply PID selection for associated tracks"}; + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Proton, o2::track::PID::Pion, o2::track::PID::Kaon}, "Trk sel: Particles species for PID, proton, pion, kaon"}; + Configurable> pidTPCMax{"pidTPCMax", std::vector{3., 0., 0.}, "maximum nSigma TPC"}; + Configurable> pidTOFMax{"pidTOFMax", std::vector{3., 0., 0.}, "maximum nSigma TOF"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.75, "minimum pT after which TOF PID is applicable"}; + Configurable fillTrkPID{"fillTrkPID", false, "fill PID information for associated tracks"}; + Configurable forceTOF{"forceTOF", false, "fill PID information for associated tracks"}; + Configurable calTrkEff{"calTrkEff", false, "fill histograms to calculate efficiency"}; + Configurable isRecTrkPhyPrimary{"isRecTrkPhyPrimary", true, "Calculate the efficiency of reconstructed primary physical tracks"}; + Configurable calEffEventWithCand{"calEffEventWithCand", true, "Calculate the efficiency of Lc candidate"}; + Configurable eventFractionToAnalyze{"eventFractionToAnalyze", -1, "Fraction of events to analyze (use only for ME offline on very large samples)"}; + } cfgCharmCand; struct : ConfigurableGroup { Configurable cfgDaughPrPtMax{"cfgDaughPrPtMax", 5., "max. pT Daughter Proton"}; @@ -373,6 +378,7 @@ struct HfCorrelatorLcScHadrons { Configurable cfgDaughPIDCutsTOFPi{"cfgDaughPIDCutsTOFPi", 2., "max. TOFnSigma Pion"}; Configurable cfgHypMassWindow{"cfgHypMassWindow", 0.1, "single lambda mass selection"}; Configurable cfgIsCorrCollMatchV0{"cfgIsCorrCollMatchV0", true, "check if daughter and mother collision are same"}; + Configurable cfgCalDataDrivenEffPr{"cfgCalDataDrivenEffPr", false, "calculate data driven efficiency of proton using Lambda"}; } cfgV0; SliceCache cache; @@ -418,8 +424,8 @@ struct HfCorrelatorLcScHadrons { // Filters for ME Filter collisionFilter = aod::hf_selection_lc_collision::lcSel == true; - Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); - Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= cfgCharmCand.selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= cfgCharmCand.selectionFlagLc); + Filter trackFilter = (nabs(aod::track::eta) < cfgCharmCand.etaTrackMax) && (nabs(aod::track::pt) > cfgCharmCand.ptTrackMin) && (nabs(aod::track::dcaXY) < cfgCharmCand.dcaXYTrackMax) && (nabs(aod::track::dcaZ) < cfgCharmCand.dcaZTrackMax); Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; Preslice perCollisionID = aod::track::collisionId; @@ -446,8 +452,8 @@ struct HfCorrelatorLcScHadrons { AxisSpec axisCandMass = {binsCandMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; AxisSpec const axisEta = {binsEta, "#it{eta}"}; AxisSpec const axisPhi = {binsPhi, "#it{#varphi}"}; - AxisSpec axisPtLc = {static_cast>(binsPtLc), "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec axisPtHadron = {static_cast>(binsPtHadron), "#it{p}_{T} Hadron (GeV/#it{c})"}; + AxisSpec axisPtLc = {static_cast>(cfgCharmCand.binsPtLc), "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPtHadron = {static_cast>(cfgCharmCand.binsPtHadron), "#it{p}_{T} Hadron (GeV/#it{c})"}; AxisSpec axisPtTrack = {500, 0, 50, "#it{p}_{T} Hadron (GeV/#it{c})"}; AxisSpec const axisMultiplicity = {binsMultiplicity, "Multiplicity"}; AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; @@ -520,6 +526,12 @@ struct HfCorrelatorLcScHadrons { registry.add("hTPCnSigmaPr", "hTPCnSigmaPr", {HistType::kTH2F, {{axisPtHadron}, {axisNSigma}}}); registry.add("hTOFnSigmaPrPiKRej", "hTOFnSigmaPrPiKRej", {HistType::kTH2F, {{axisPtHadron}, {axisNSigma}}}); registry.add("hTPCnSigmaPrPiKRej", "hTPCnSigmaPrPiKRej", {HistType::kTH2F, {{axisPtHadron}, {axisNSigma}}}); + registry.add("hLcHadronInvMassVsPt", "Lc+Hadron invariant mass vs combined pT;m_{Lc+h} (GeV/c^2);p_{T,combined} (GeV/c)", {HistType::kTH2F, {{500, 2.0, 4.5}, {100, 0., 50.}}}); + registry.add("hLcLambdaInvMassVsPt", "Lc+Lambda invariant mass vs combined pT;m_{Lc+Lambda} (GeV/c^2);p_{T,combined} (GeV/c)", {HistType::kTH2F, {{500, 2.0, 5.0}, {100, 0., 50.}}}); + registry.add("hLcHadronInvMass", "Lc+Hadron invariant mass;m_{Lc+h} (GeV/c^2);entries", {HistType::kTH1F, {{500, 2.0, 4.5}}}); + registry.add("hLcLambdaInvMass", "Lc+Lambda invariant mass;m_{Lc+Lambda} (GeV/c^2);entries", {HistType::kTH1F, {{500, 2.5, 5.0}}}); + registry.add("hLcHadronPtCombined", "Combined pT (Lc+Hadron);p_{T,combined} (GeV/c);entries", {HistType::kTH1F, {{100, 0., 50.}}}); + registry.add("hLcLambdaPtCombined", "Combined pT (Lc+Lambda);p_{T,combined} (GeV/c);entries", {HistType::kTH1F, {{100, 0., 50.}}}); // Lambda V0 histograms registry.add("hEventLambdaV0", "Lambda, events", {HistType::kTH1F, {{2, 0, 2}}}); @@ -538,8 +550,8 @@ struct HfCorrelatorLcScHadrons { template void fillMlOutput(MlProbType const& mlProb, std::vector& outputMl) { - for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { - outputMl[iclass] = mlProb[classMl->at(iclass)]; + for (unsigned int iclass = 0; iclass < cfgCharmCand.classMl->size(); iclass++) { + outputMl[iclass] = mlProb[cfgCharmCand.classMl->at(iclass)]; } }; @@ -573,7 +585,7 @@ struct HfCorrelatorLcScHadrons { if (std::abs(pid) == kPiPlus && (std::abs(track.tpcNSigmaPi()) > cfgV0.cfgDaughPIDCutsTPCPi || std::abs(track.tofNSigmaPi()) > cfgV0.cfgDaughPIDCutsTOFPi)) { return false; } - if (std::abs(track.eta()) > etaTrackMax) { + if (std::abs(track.eta()) > cfgCharmCand.etaTrackMax) { return false; } if (std::abs(pid) == kProton && track.pt() > cfgV0.cfgDaughPrPtMax) { @@ -592,93 +604,323 @@ struct HfCorrelatorLcScHadrons { return true; } - template - void fillV0Histograms(V0 const& v0s, TrackType const&) + template + float calculateInvMass(T1 const& particle1, T2 const& particle2, float mass1, float mass2) { - for (const auto& v0 : v0s) { - auto posTrackV0 = v0.template posTrack_as(); - auto negTrackV0 = v0.template negTrack_as(); - if (cfgV0.cfgIsCorrCollMatchV0 && ((v0.collisionId() != posTrackV0.collisionId()) || (v0.collisionId() != negTrackV0.collisionId()))) { - continue; - } + ROOT::Math::PtEtaPhiMVector vec1(particle1.pt(), particle1.eta(), particle1.phi(), mass1); + ROOT::Math::PtEtaPhiMVector vec2(particle2.pt(), particle2.eta(), particle2.phi(), mass2); + ROOT::Math::PtEtaPhiMVector combined = vec1 + vec2; + return combined.mass(); + } - if (std::abs(o2::constants::physics::MassLambda - v0.mLambda()) < cfgV0.cfgHypMassWindow) { - entryHadron(v0.mLambda(), posTrackV0.eta(), posTrackV0.pt() * posTrackV0.sign(), 0, 0, v0.pt()); - entryTrkPID(posTrackV0.tpcNSigmaPr(), posTrackV0.tpcNSigmaKa(), posTrackV0.tpcNSigmaPi(), posTrackV0.tofNSigmaPr(), posTrackV0.tofNSigmaKa(), posTrackV0.tofNSigmaPi()); + // Helper function to calculate combined pT + template + float calculateCombinedPt(T1 const& particle1, T2 const& particle2) + { + ROOT::Math::PtEtaPhiMVector vec1(particle1.pt(), particle1.eta(), particle1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vec2(particle2.pt(), particle2.eta(), particle2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector combined = vec1 + vec2; + return combined.pt(); + } - if (isSelectedV0Daughter(posTrackV0, kProton) && isSelectedV0Daughter(negTrackV0, kPiPlus)) { - registry.fill(HIST("hV0Lambda"), v0.mLambda(), v0.pt(), posTrackV0.pt()); - registry.fill(HIST("hV0LambdaRefl"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + template + void fillV0HistogramsWithLc(CollisionType const& collision, V0 const& v0s, TrackType const& tracks, CandsLcType const& candidates, aod::McParticles const* mcParticles = nullptr) + { + if (cfgV0.cfgCalDataDrivenEffPr) { + for (const auto& v0 : v0s) { + auto posTrackV0 = v0.template posTrack_as(); + auto negTrackV0 = v0.template negTrack_as(); + if (cfgV0.cfgIsCorrCollMatchV0 && ((v0.collisionId() != posTrackV0.collisionId()) || (v0.collisionId() != negTrackV0.collisionId()))) { + continue; + } - registry.fill(HIST("hTPCnSigmaPr"), posTrackV0.pt(), posTrackV0.tpcNSigmaPr()); - if (posTrackV0.hasTOF()) { - registry.fill(HIST("hTOFnSigmaPr"), posTrackV0.pt(), posTrackV0.tofNSigmaPr()); - } + if (std::abs(o2::constants::physics::MassLambda - v0.mLambda()) < cfgV0.cfgHypMassWindow) { + entryHadron(v0.mLambda(), posTrackV0.eta(), posTrackV0.pt() * posTrackV0.sign(), 0, 0, v0.pt()); + entryTrkPID(posTrackV0.tpcNSigmaPr(), posTrackV0.tpcNSigmaKa(), posTrackV0.tpcNSigmaPi(), posTrackV0.tofNSigmaPr(), posTrackV0.tofNSigmaKa(), posTrackV0.tofNSigmaPi()); - if (passPIDSelection(posTrackV0, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { - registry.fill(HIST("hV0LambdaPiKRej"), v0.mLambda(), v0.pt(), posTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflPiKRej"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + if (isSelectedV0Daughter(posTrackV0, kProton) && isSelectedV0Daughter(negTrackV0, kPiPlus)) { + registry.fill(HIST("hV0Lambda"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + registry.fill(HIST("hV0LambdaRefl"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hTPCnSigmaPrPiKRej"), posTrackV0.pt(), posTrackV0.tpcNSigmaPr()); + registry.fill(HIST("hTPCnSigmaPr"), posTrackV0.pt(), posTrackV0.tpcNSigmaPr()); if (posTrackV0.hasTOF()) { - registry.fill(HIST("hTOFnSigmaPrPiKRej"), posTrackV0.pt(), posTrackV0.tofNSigmaPr()); + registry.fill(HIST("hTOFnSigmaPr"), posTrackV0.pt(), posTrackV0.tofNSigmaPr()); } - } - } - } - if (std::abs(o2::constants::physics::MassLambda - v0.mAntiLambda()) < cfgV0.cfgHypMassWindow) { - entryHadron(v0.mAntiLambda(), negTrackV0.eta(), negTrackV0.pt() * negTrackV0.sign(), 0, 0, v0.pt()); - entryTrkPID(negTrackV0.tpcNSigmaPr(), negTrackV0.tpcNSigmaKa(), negTrackV0.tpcNSigmaPi(), negTrackV0.tofNSigmaPr(), negTrackV0.tofNSigmaKa(), negTrackV0.tofNSigmaPi()); - if (isSelectedV0Daughter(negTrackV0, kProton) && isSelectedV0Daughter(posTrackV0, kPiPlus)) { - registry.fill(HIST("hV0Lambda"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hV0LambdaRefl"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + if (passPIDSelection(posTrackV0, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { + registry.fill(HIST("hV0LambdaPiKRej"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflPiKRej"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hTPCnSigmaPr"), negTrackV0.pt(), negTrackV0.tpcNSigmaPr()); - if (negTrackV0.hasTOF()) { - registry.fill(HIST("hTOFnSigmaPr"), negTrackV0.pt(), negTrackV0.tofNSigmaPr()); + registry.fill(HIST("hTPCnSigmaPrPiKRej"), posTrackV0.pt(), posTrackV0.tpcNSigmaPr()); + if (posTrackV0.hasTOF()) { + registry.fill(HIST("hTOFnSigmaPrPiKRej"), posTrackV0.pt(), posTrackV0.tofNSigmaPr()); + } + } } - if (passPIDSelection(negTrackV0, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { - registry.fill(HIST("hV0LambdaPiKRej"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflPiKRej"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + } + if (std::abs(o2::constants::physics::MassLambda - v0.mAntiLambda()) < cfgV0.cfgHypMassWindow) { + entryHadron(v0.mAntiLambda(), negTrackV0.eta(), negTrackV0.pt() * negTrackV0.sign(), 0, 0, v0.pt()); + entryTrkPID(negTrackV0.tpcNSigmaPr(), negTrackV0.tpcNSigmaKa(), negTrackV0.tpcNSigmaPi(), negTrackV0.tofNSigmaPr(), negTrackV0.tofNSigmaKa(), negTrackV0.tofNSigmaPi()); - registry.fill(HIST("hTPCnSigmaPrPiKRej"), negTrackV0.pt(), negTrackV0.tpcNSigmaPr()); + if (isSelectedV0Daughter(negTrackV0, kProton) && isSelectedV0Daughter(posTrackV0, kPiPlus)) { + registry.fill(HIST("hV0Lambda"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + registry.fill(HIST("hV0LambdaRefl"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + + registry.fill(HIST("hTPCnSigmaPr"), negTrackV0.pt(), negTrackV0.tpcNSigmaPr()); if (negTrackV0.hasTOF()) { - registry.fill(HIST("hTOFnSigmaPrPiKRej"), negTrackV0.pt(), negTrackV0.tofNSigmaPr()); + registry.fill(HIST("hTOFnSigmaPr"), negTrackV0.pt(), negTrackV0.tofNSigmaPr()); + } + if (passPIDSelection(negTrackV0, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { + registry.fill(HIST("hV0LambdaPiKRej"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflPiKRej"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + + registry.fill(HIST("hTPCnSigmaPrPiKRej"), negTrackV0.pt(), negTrackV0.tpcNSigmaPr()); + if (negTrackV0.hasTOF()) { + registry.fill(HIST("hTOFnSigmaPrPiKRej"), negTrackV0.pt(), negTrackV0.tofNSigmaPr()); + } + } + } + } + if constexpr (IsMcRec) { + if (!v0.has_mcParticle() || !posTrackV0.has_mcParticle() || !negTrackV0.has_mcParticle()) { + continue; + } + auto v0Mc = v0.mcParticle(); + auto posTrack = posTrackV0.mcParticle(); + auto negTrack = negTrackV0.mcParticle(); + + if (std::abs(v0Mc.pdgCode()) == kLambda0) { + if (std::abs(posTrack.pdgCode()) == kProton) { + registry.fill(HIST("hV0LambdaMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + + if (passPIDSelection(posTrackV0, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { + registry.fill(HIST("hV0LambdaPiKRejMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflPiKRejMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + } + } + if (std::abs(negTrack.pdgCode()) == kProton) { + registry.fill(HIST("hV0LambdaMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + + if (passPIDSelection(negTrackV0, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { + registry.fill(HIST("hV0LambdaPiKRejMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + registry.fill(HIST("hV0LambdaReflPiKRejMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + } } } } } + } + + int nTracks = 0; + float efficiencyWeightCand = 1.; + int64_t timeStamp = 0; + bool skipMixedEventTableFilling = false; + float const multiplicityFT0M = collision.multFT0M(); + int gCollisionId = collision.globalIndex(); + if (candidates.size() == 0) { + return; + } + + if (cfgCharmCand.eventFractionToAnalyze > 0) { + if (rnd->Uniform(0, 1) > cfgCharmCand.eventFractionToAnalyze) { + skipMixedEventTableFilling = true; + } + } + + if constexpr (!IsMcRec) { + timeStamp = collision.template bc_as().timestamp(); + } + + poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), multiplicityFT0M)); + + // Count good tracks + if (collision.numContrib() > 1) { + for (const auto& track : tracks) { + if (std::abs(track.eta()) > cfgCharmCand.etaTrackMax || std::abs(track.dcaXY()) > cfgCharmCand.dcaXYTrackMax || std::abs(track.dcaZ()) > cfgCharmCand.dcaZTrackMax) { + continue; + } + nTracks++; + } + } + + registry.fill(HIST("hMultiplicityPreSelection"), nTracks); + if (nTracks < cfgCharmCand.multMin || nTracks > cfgCharmCand.multMax) { + return; + } + registry.fill(HIST("hMultiplicity"), nTracks); + + int countCand = 1; + + // Lc-Lambda correlation (same event) + for (const auto& candidate : candidates) { + double yCand = HfHelper::yLc(candidate); + double ptCand = candidate.pt(); + double etaCand = candidate.eta(); + double phiCand = RecoDecay::constrainAngle(candidate.phi(), -PIHalf); + + if ((std::abs(yCand) > cfgCharmCand.yCandMax) || ptCand < cfgCharmCand.ptCandMin || ptCand > cfgCharmCand.ptCandMax) { + continue; + } + + registry.fill(HIST("hY"), yCand); + registry.fill(HIST("hPtCand"), ptCand); + registry.fill(HIST("hEta"), etaCand); + registry.fill(HIST("hPhi"), phiCand); + registry.fill(HIST("hCandBin"), poolBin); + + bool selLcPKPi = candidate.isSelLcToPKPi() >= cfgCharmCand.selectionFlagLc; + bool selLcPiKP = candidate.isSelLcToPiKP() >= cfgCharmCand.selectionFlagLc; + + if (!selLcPKPi && !selLcPiKP) { + continue; + } + + if (cfgCharmCand.applyEfficiency) { + efficiencyWeightCand = 1. / cfgCharmCand.efficiencyLc->at(o2::analysis::findBin(cfgCharmCand.binsPtEfficiencyLc, ptCand)); + } + if constexpr (IsMcRec) { - if (!v0.has_mcParticle() || !posTrackV0.has_mcParticle() || !negTrackV0.has_mcParticle()) { + isPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; + isNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + isSignal = std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; + + if (isSignal) { + registry.fill(HIST("hPtCandSig"), ptCand); + registry.fill(HIST("hEtaSig"), etaCand); + registry.fill(HIST("hPhiSig"), phiCand); + registry.fill(HIST("hYSig"), yCand); + } + } + + float massCandPKPi = -999.0; + float massCandPiKP = -999.0; + + if (selLcPKPi) { + massCandPKPi = HfHelper::invMassLcToPKPi(candidate); + const auto& probs = candidate.mlProbLcToPKPi(); + fillMlOutput(probs, outputMlPKPi); + + registry.fill(HIST("hMassLcVsPt"), massCandPKPi, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); + registry.fill(HIST("hMassLcData"), massCandPKPi, efficiencyWeightCand); + registry.fill(HIST("hSelectionStatusLcToPKPi"), selLcPKPi); + if (isPrompt) { + registry.fill(HIST("hPtCandSigPrompt"), ptCand); + registry.fill(HIST("hPtVsMultiplicityMcRecPrompt"), ptCand, multiplicityFT0M); + } else if (isNonPrompt) { + registry.fill(HIST("hPtCandSigNonPrompt"), ptCand); + registry.fill(HIST("hPtVsMultiplicityMcRecNonPrompt"), ptCand, multiplicityFT0M); + } + + entryCandRecoInfo(massCandPKPi, ptCand, outputMlPKPi[0], outputMlPKPi[1], poolBin); + entryCandCandGenInfo(isPrompt); + if (!skipMixedEventTableFilling) { + entryCand(candidate.phi(), etaCand, ptCand, massCandPKPi, poolBin, gCollisionId, timeStamp); + entryCandCharge(chargeCand); + } + } + if (selLcPiKP) { + massCandPiKP = HfHelper::invMassLcToPiKP(candidate); + const auto& probs = candidate.mlProbLcToPiKP(); + fillMlOutput(probs, outputMlPiKP); + registry.fill(HIST("hMassLcVsPt"), massCandPiKP, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); + registry.fill(HIST("hMassLcData"), massCandPiKP, efficiencyWeightCand); + registry.fill(HIST("hSelectionStatusLcToPiKP"), selLcPiKP); + if (isPrompt) { + registry.fill(HIST("hPtCandSigPrompt"), ptCand); + registry.fill(HIST("hPtVsMultiplicityMcRecPrompt"), ptCand, multiplicityFT0M); + } else if (isNonPrompt) { + registry.fill(HIST("hPtCandSigNonPrompt"), ptCand); + registry.fill(HIST("hPtVsMultiplicityMcRecNonPrompt"), ptCand, multiplicityFT0M); + } + entryCandRecoInfo(massCandPiKP, ptCand, outputMlPiKP[0], outputMlPiKP[1], poolBin); + entryCandCandGenInfo(isPrompt); + if (!skipMixedEventTableFilling) { + entryCand(candidate.phi(), etaCand, ptCand, massCandPiKP, poolBin, gCollisionId, timeStamp); + entryCandCharge(chargeCand); + } + } + + auto trackPos1 = candidate.template prong0_as(); + // auto trackPos2 = candidate.template prong2_as(); + chargeCand = trackPos1.sign(); + + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("hPtProng2"), candidate.ptProng2()); + + registry.fill(HIST("hCandBin"), poolBin); + + // Correlate Lc with all Lambda V0 in the same event + for (const auto& v0 : v0s) { + + const int v0Lambda = 1; + const int v0AntiLambda = -1; + + auto posTrackV0 = v0.template posTrack_as(); + auto negTrackV0 = v0.template negTrack_as(); + + if ((candidate.prong0Id() == posTrackV0.globalIndex()) || (candidate.prong1Id() == posTrackV0.globalIndex()) || (candidate.prong2Id() == posTrackV0.globalIndex() || (candidate.prong0Id() == negTrackV0.globalIndex()) || (candidate.prong1Id() == negTrackV0.globalIndex()) || (candidate.prong2Id() == negTrackV0.globalIndex()))) { + if (!cfgCharmCand.storeAutoCorrelationFlag) { + continue; + } + correlationStatus = true; + } + + if (cfgV0.cfgIsCorrCollMatchV0 && ((v0.collisionId() != posTrackV0.collisionId()) || (v0.collisionId() != negTrackV0.collisionId()))) { continue; } - auto v0Mc = v0.mcParticle(); - auto posTrack = posTrackV0.mcParticle(); - auto negTrack = negTrackV0.mcParticle(); - - if (std::abs(v0Mc.pdgCode()) == kLambda0) { - if (std::abs(posTrack.pdgCode()) == kProton) { - registry.fill(HIST("hV0LambdaMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - - if (passPIDSelection(posTrackV0, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { - registry.fill(HIST("hV0LambdaPiKRejMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflPiKRejMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); + + // Process Lambda (proton-pion) + if (std::abs(o2::constants::physics::MassLambda - v0.mLambda()) < cfgV0.cfgHypMassWindow) { + if (isSelectedV0Daughter(posTrackV0, kProton) && isSelectedV0Daughter(negTrackV0, kPiPlus)) { + + if (selLcPKPi) { + fillCorrelationTable(cfgCharmCand.fillTrkPID, v0, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, 0, massCandPKPi, *mcParticles); + } + if (selLcPiKP) { + fillCorrelationTable(cfgCharmCand.fillTrkPID, v0, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, 0, massCandPiKP, *mcParticles); + } + + if (countCand == 1) { + if (!skipMixedEventTableFilling) { + entryHadron(v0.phi(), v0.eta(), v0.pt() * v0Lambda, poolBin, gCollisionId, timeStamp); + entryV0InvMass(v0.mLambda()); + registry.fill(HIST("hTracksBin"), poolBin); + } } } - if (std::abs(negTrack.pdgCode()) == kProton) { - registry.fill(HIST("hV0LambdaMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + } - if (passPIDSelection(negTrackV0, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { - registry.fill(HIST("hV0LambdaPiKRejMcRec"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); - registry.fill(HIST("hV0LambdaReflPiKRejMcRec"), v0.mLambda(), v0.pt(), posTrackV0.pt()); + // Process anti-Lambda (anti-proton-pion) + if (std::abs(o2::constants::physics::MassLambda - v0.mAntiLambda()) < cfgV0.cfgHypMassWindow) { + if (isSelectedV0Daughter(negTrackV0, kProton) && isSelectedV0Daughter(posTrackV0, kPiPlus)) { + + if (selLcPKPi) { + fillCorrelationTable(cfgCharmCand.fillTrkPID, v0, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, 0, massCandPKPi, *mcParticles); + } + if (selLcPiKP) { + fillCorrelationTable(cfgCharmCand.fillTrkPID, v0, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, 0, massCandPiKP, *mcParticles); + } + if (countCand == 1) { + if (!skipMixedEventTableFilling) { + entryHadron(v0.phi(), v0.eta(), v0.pt() * v0AntiLambda, poolBin, gCollisionId, timeStamp); + entryV0InvMass(v0.mAntiLambda()); + registry.fill(HIST("hTracksBin"), poolBin); + } } } } - } - } + + } // end v0 loop + + countCand++; + } // end outer Lc loop + registry.fill(HIST("hZvtx"), collision.posZ()); + registry.fill(HIST("hMultFT0M"), multiplicityFT0M); } template @@ -695,14 +937,14 @@ struct HfCorrelatorLcScHadrons { } auto gentracks = mcParticles.sliceBy(perTrueCollision, mctrk.mcCollisionId()); for (const auto& track : gentracks) { - if (std::abs(track.eta()) > etaTrackMax || track.pt() < ptTrackMin || track.pt() > ptTrackMax) { + if (std::abs(track.eta()) > cfgCharmCand.etaTrackMax || track.pt() < cfgCharmCand.ptTrackMin || track.pt() > cfgCharmCand.ptTrackMax) { continue; } if ((std::abs(track.pdgCode()) != kElectron) && (std::abs(track.pdgCode()) != kMuonMinus) && (std::abs(track.pdgCode()) != kPiPlus) && (std::abs(track.pdgCode()) != kKPlus) && (std::abs(track.pdgCode()) != kProton)) { continue; } - if (pidTrkApplied && (std::abs(track.pdgCode()) != kProton)) { + if (cfgCharmCand.pidTrkApplied && (std::abs(track.pdgCode()) != kProton)) { continue; // proton PID } @@ -719,43 +961,76 @@ struct HfCorrelatorLcScHadrons { registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (std::abs(chargeTrack))); } } - template - void fillCorrelationTable(bool trkPidFill, TrackType const& track, CandType const& candidate, + template + void fillCorrelationTable(bool trkPidFill, AssocType const& assoc, CandType const& candidate, const std::vector& outMl, int binPool, int8_t correlStatus, - double yCand, int signCand, float ptLcFromSc, McPart const& mcParticles) + double yCand, int signCand, float ptLcFromSc, double massCand, McPart const& mcParticles) { bool isPhysicalPrimary = false; int trackOrigin = -1; float const cent = 100.0; // will be updated later + double massCandHadron = -999.0; + double ptCombined = -999.0; + double yAssoc = -999.0; + int signAssoc = 0; + + if constexpr (LambdaPart == 1) { + massCandHadron = calculateInvMass(candidate, assoc, massCand, assoc.mLambda()); + entryPairedV0InvMass(assoc.mLambda()); + signAssoc = 1; + yAssoc = assoc.yLambda(); + } else if constexpr (LambdaPart == -1) { + massCandHadron = calculateInvMass(candidate, assoc, massCand, assoc.mAntiLambda()); + entryPairedV0InvMass(assoc.mAntiLambda()); + signAssoc = -1; // Note: Ensure signAssoc vs assoc.signAssoc is consistent + yAssoc = assoc.yLambda(); + } else { + // The final 'else' does not need the 'constexpr' keyword; + // it is automatically part of the constexpr logic. + massCandHadron = calculateInvMass(candidate, assoc, massCand, MassProton); + signAssoc = assoc.sign(); + yAssoc = assoc.rapidity(MassProton); + } + + ptCombined = calculateCombinedPt(candidate, assoc); + + registry.fill(HIST("hLcHadronInvMassVsPt"), massCandHadron, ptCombined); + registry.fill(HIST("hLcHadronInvMass"), massCandHadron); + registry.fill(HIST("hLcHadronPtCombined"), ptCombined); - entryCandHadronPair(getDeltaPhi(track.phi(), candidate.phi()), - track.eta() - candidate.eta(), + entryCandHadronPair(getDeltaPhi(assoc.phi(), candidate.phi()), + assoc.eta() - candidate.eta(), candidate.pt(), - track.pt() * track.sign(), + assoc.pt() * signAssoc, binPool, correlStatus, cent); - entryCandHadronPairY(track.rapidity(MassProton) - yCand); + entryCandHadronPairY(yAssoc - yCand); entryCandHadronMlInfo(outMl[0], outMl[1]); entryPtLcFromScPair(ptLcFromSc); - entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); + if constexpr (LambdaPart == 0) { + entryTrackRecoInfo(assoc.dcaXY(), assoc.dcaZ(), assoc.tpcNClsCrossedRows()); + } + entryCandHadronRecoInfo(massCand, false); + entryLcHadronInvMass(massCandHadron, ptCombined); entryPairCandCharge(signCand); - if (trkPidFill) { - entryCandHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); + if constexpr (LambdaPart == 0) { + if (trkPidFill) + entryCandHadronPairTrkPID(assoc.tpcNSigmaPr(), assoc.tpcNSigmaKa(), assoc.tpcNSigmaPi(), assoc.tofNSigmaPr(), assoc.tofNSigmaKa(), assoc.tofNSigmaPi()); } if constexpr (IsMcRec) { - if (track.has_mcParticle()) { - auto mcParticle = track.template mcParticle_as(); + if (assoc.has_mcParticle()) { + auto mcParticle = assoc.template mcParticle_as(); isPhysicalPrimary = mcParticle.isPhysicalPrimary(); trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); entryCandHadronGenInfo(isPrompt, isPhysicalPrimary, trackOrigin); } else { entryCandHadronGenInfo(isPrompt, false, 0); - registry.fill(HIST("hFakeTracksMcRec"), track.pt()); + registry.fill(HIST("hFakeTracksMcRec"), assoc.pt()); } - registry.fill(HIST("hPtParticleAssocVsCandMcRec"), track.pt(), candidate.pt()); + registry.fill(HIST("hPtParticleAssocVsCandMcRec"), assoc.pt(), candidate.pt()); if (isPhysicalPrimary) { - registry.fill(HIST("hPtPrimaryParticleAssocVsCandMcRec"), track.pt(), candidate.pt()); + registry.fill(HIST("hPtPrimaryParticleAssocVsCandMcRec"), assoc.pt(), candidate.pt()); } } } @@ -776,8 +1051,8 @@ struct HfCorrelatorLcScHadrons { return; } - if (eventFractionToAnalyze > 0) { - if (rnd->Uniform(0, 1) > eventFractionToAnalyze) { + if (cfgCharmCand.eventFractionToAnalyze > 0) { + if (rnd->Uniform(0, 1) > cfgCharmCand.eventFractionToAnalyze) { skipMixedEventTableFilling = true; } } @@ -787,14 +1062,14 @@ struct HfCorrelatorLcScHadrons { } poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), multiplicityFT0M)); - if (correlateLcWithLeadingParticle) { - leadingIndex = findLeadingParticle(tracks, etaTrackMax.value); + if (cfgCharmCand.correlateLcWithLeadingParticle) { + leadingIndex = findLeadingParticle(tracks, cfgCharmCand.etaTrackMax.value); } // Count good tracks if (collision.numContrib() > 1) { for (const auto& track : tracks) { - if (std::abs(track.eta()) > etaTrackMax || std::abs(track.dcaXY()) > dcaXYTrackMax || std::abs(track.dcaZ()) > dcaZTrackMax) { + if (std::abs(track.eta()) > cfgCharmCand.etaTrackMax || std::abs(track.dcaXY()) > cfgCharmCand.dcaXYTrackMax || std::abs(track.dcaZ()) > cfgCharmCand.dcaZTrackMax) { continue; } nTracks++; @@ -802,7 +1077,7 @@ struct HfCorrelatorLcScHadrons { } registry.fill(HIST("hMultiplicityPreSelection"), nTracks); - if (nTracks < multMin || nTracks > multMax) { + if (nTracks < cfgCharmCand.multMin || nTracks > cfgCharmCand.multMax) { return; } registry.fill(HIST("hMultiplicity"), nTracks); @@ -813,7 +1088,7 @@ struct HfCorrelatorLcScHadrons { double efficiencyWeightCand = 1.; double yCand = -999.0; double etaCand = -999.0; - double ptScProng0 = -999.0; + double ptScProng0 = 0.0; double ptSoftPi = -999.0; double massPKPiLcFromSc = -999.0; double massPiKPLcFromSc = -999.0; @@ -831,7 +1106,7 @@ struct HfCorrelatorLcScHadrons { ptCand = candidate.pt(); phiCand = RecoDecay::constrainAngle(candidate.phi(), -PIHalf); - if ((std::abs(yCand) > yCandMax) || ptCand < ptCandMin || ptCand > ptCandMax) { + if ((std::abs(yCand) > cfgCharmCand.yCandMax) || ptCand < cfgCharmCand.ptCandMin || ptCand > cfgCharmCand.ptCandMax) { continue; } @@ -841,8 +1116,8 @@ struct HfCorrelatorLcScHadrons { registry.fill(HIST("hPhi"), phiCand); registry.fill(HIST("hCandBin"), poolBin); - if (applyEfficiency) { - efficiencyWeightCand = 1. / efficiencyLc->at(o2::analysis::findBin(binsPtEfficiencyLc, ptCand)); + if (cfgCharmCand.applyEfficiency) { + efficiencyWeightCand = 1. / cfgCharmCand.efficiencyLc->at(o2::analysis::findBin(cfgCharmCand.binsPtEfficiencyLc, ptCand)); } if constexpr (IsMcRec) { @@ -856,8 +1131,8 @@ struct HfCorrelatorLcScHadrons { ptScProng0 = candidateLc.pt(); softPiAbsDcaXY = std::abs(candidate.softPiDcaXY()); softPiAbsDcaZ = std::abs(candidate.softPiDcaZ()); - selLcPKPi = (candidateLc.isSelLcToPKPi() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPKPiFromPDG()); - selLcPiKP = (candidateLc.isSelLcToPiKP() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPiKPFromPDG()); + selLcPKPi = (candidateLc.isSelLcToPKPi() >= cfgCharmCand.selectionFlagLc) && (candidate.statusSpreadLcMinvPKPiFromPDG()); + selLcPiKP = (candidateLc.isSelLcToPiKP() >= cfgCharmCand.selectionFlagLc) && (candidate.statusSpreadLcMinvPiKPFromPDG()); if (selLcPKPi) { const auto& probs = candidateLc.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); @@ -882,7 +1157,7 @@ struct HfCorrelatorLcScHadrons { auto trackPos2 = candidateLc.template prong2_as(); signSoftPion = candidate.template prong1_as().sign(); ptSoftPi = candidate.template prong1_as().pt(); - if (calTrkEff && countCand == 1 && (isSignal || !calEffEventWithCand)) { + if (cfgCharmCand.calTrkEff && countCand == 1 && (isSignal || !cfgCharmCand.calEffEventWithCand)) { calculateTrkEff(trackPos1, trackPos2, *mcParticles); } registry.fill(HIST("hPtProng1"), candidate.template prong1_as().pt()); @@ -898,8 +1173,8 @@ struct HfCorrelatorLcScHadrons { } } else { - selLcPKPi = candidate.isSelLcToPKPi() >= selectionFlagLc; - selLcPiKP = candidate.isSelLcToPiKP() >= selectionFlagLc; + selLcPKPi = candidate.isSelLcToPKPi() >= cfgCharmCand.selectionFlagLc; + selLcPiKP = candidate.isSelLcToPiKP() >= cfgCharmCand.selectionFlagLc; if (selLcPKPi) { const auto& probs = candidate.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); @@ -915,7 +1190,7 @@ struct HfCorrelatorLcScHadrons { chargeCand = trackPos1.sign(); if constexpr (IsMcRec) { isSignal = std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; - if (calTrkEff && countCand == 1 && (isSignal || !calEffEventWithCand)) { + if (cfgCharmCand.calTrkEff && countCand == 1 && (isSignal || !cfgCharmCand.calEffEventWithCand)) { calculateTrkEff(trackPos1, trackPos2, *mcParticles); } } @@ -926,7 +1201,7 @@ struct HfCorrelatorLcScHadrons { if (isSignal) { registry.fill(HIST("hPtCandSig"), ptCand); - registry.fill(HIST("hEtaSig"), ptCand); + registry.fill(HIST("hEtaSig"), etaCand); registry.fill(HIST("hPhiSig"), phiCand); registry.fill(HIST("hYSig"), yCand); } @@ -982,7 +1257,7 @@ struct HfCorrelatorLcScHadrons { // Remove Lc daughters by checking track indices if constexpr (!IsCandSc) { if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { - if (!storeAutoCorrelationFlag) { + if (!cfgCharmCand.storeAutoCorrelationFlag) { continue; } correlationStatus = true; @@ -990,7 +1265,7 @@ struct HfCorrelatorLcScHadrons { } else { const auto& candidateLc = candidate.template prongLc_as(); if ((candidateLc.prong0Id() == track.globalIndex()) || (candidateLc.prong1Id() == track.globalIndex()) || (candidateLc.prong2Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex())) { - if (!storeAutoCorrelationFlag) { + if (!cfgCharmCand.storeAutoCorrelationFlag) { continue; } correlationStatus = true; @@ -999,20 +1274,20 @@ struct HfCorrelatorLcScHadrons { if (!track.isGlobalTrackWoDCA()) { continue; } - if (pidTrkApplied) { - if (!passPIDSelection(track, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { + if (cfgCharmCand.pidTrkApplied) { + if (!passPIDSelection(track, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { continue; } } - if (correlateLcWithLeadingParticle) { + if (cfgCharmCand.correlateLcWithLeadingParticle) { if (track.globalIndex() != leadingIndex) { continue; } } if constexpr (IsMcRec) { - if (calTrkEff && countCand == 1 && (isSignal || !calEffEventWithCand) && track.has_mcParticle()) { + if (cfgCharmCand.calTrkEff && countCand == 1 && (isSignal || !cfgCharmCand.calEffEventWithCand) && track.has_mcParticle()) { auto mcParticle = track.template mcParticle_as(); - if (!mcParticle.isPhysicalPrimary() && isRecTrkPhyPrimary) { + if (!mcParticle.isPhysicalPrimary() && cfgCharmCand.isRecTrkPhyPrimary) { continue; } @@ -1029,20 +1304,18 @@ struct HfCorrelatorLcScHadrons { } if (selLcPKPi) { - fillCorrelationTable(fillTrkPID, track, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, *mcParticles); - entryCandHadronRecoInfo(massCandPKPi, false); + fillCorrelationTable(cfgCharmCand.fillTrkPID, track, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, massCandPKPi, *mcParticles); entryScHadronRecoInfoExt(massPKPiLcFromSc, ptSoftPi, softPiAbsDcaXY, softPiAbsDcaZ); } if (selLcPiKP) { - fillCorrelationTable(fillTrkPID, track, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, *mcParticles); - entryCandHadronRecoInfo(massCandPiKP, false); + fillCorrelationTable(cfgCharmCand.fillTrkPID, track, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, massCandPiKP, *mcParticles); entryScHadronRecoInfoExt(massPiKPLcFromSc, ptSoftPi, softPiAbsDcaXY, softPiAbsDcaZ); } if (countCand == 1) { if (!skipMixedEventTableFilling) { entryHadron(track.phi(), track.eta(), track.pt() * track.sign(), poolBin, gCollisionId, timeStamp); - if (fillTrkPID) { + if (cfgCharmCand.fillTrkPID) { entryTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); } registry.fill(HIST("hTracksBin"), poolBin); @@ -1076,7 +1349,7 @@ struct HfCorrelatorLcScHadrons { bool selLcPiKP = false; auto tracksTuple = std::make_tuple(candidates, tracks); - Pair const pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair const pairData{corrBinning, cfgCharmCand.numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairData) { poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFT0M())); @@ -1099,8 +1372,8 @@ struct HfCorrelatorLcScHadrons { chargeCand = candidate.charge(); ptScProng0 = candidateLc.pt(); - selLcPKPi = (candidateLc.isSelLcToPKPi() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPKPiFromPDG()); - selLcPiKP = (candidateLc.isSelLcToPiKP() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPiKPFromPDG()); + selLcPKPi = (candidateLc.isSelLcToPKPi() >= cfgCharmCand.selectionFlagLc) && (candidate.statusSpreadLcMinvPKPiFromPDG()); + selLcPiKP = (candidateLc.isSelLcToPiKP() >= cfgCharmCand.selectionFlagLc) && (candidate.statusSpreadLcMinvPiKPFromPDG()); if (selLcPKPi) { const auto& probs = candidateLc.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); @@ -1123,8 +1396,8 @@ struct HfCorrelatorLcScHadrons { chargeCand = (signSoftPion < ChargeZero) ? AssignedChargeSc0 : -AssignedChargeSc0; // to distingush sc0 from anti-sc0, charge set to +1 and -1 } } else { - selLcPKPi = candidate.isSelLcToPKPi() >= selectionFlagLc; - selLcPiKP = candidate.isSelLcToPiKP() >= selectionFlagLc; + selLcPKPi = candidate.isSelLcToPKPi() >= cfgCharmCand.selectionFlagLc; + selLcPiKP = candidate.isSelLcToPiKP() >= cfgCharmCand.selectionFlagLc; if (selLcPKPi) { const auto& probs = candidate.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); @@ -1142,20 +1415,18 @@ struct HfCorrelatorLcScHadrons { } } - if (!assocParticle.isGlobalTrackWoDCA() || std::abs(yCand) > yCandMax) { + if (!assocParticle.isGlobalTrackWoDCA() || std::abs(yCand) > cfgCharmCand.yCandMax) { continue; } - if (pidTrkApplied) { - if (!passPIDSelection(assocParticle, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) { + if (cfgCharmCand.pidTrkApplied) { + if (!passPIDSelection(assocParticle, cfgCharmCand.trkPIDspecies, cfgCharmCand.pidTPCMax, cfgCharmCand.pidTOFMax, cfgCharmCand.tofPIDThreshold, cfgCharmCand.forceTOF)) { continue; } } if (selLcPKPi) { - fillCorrelationTable(fillTrkPID, assocParticle, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, *mcParticles); - entryCandHadronRecoInfo(massCandPKPi, false); - + fillCorrelationTable(cfgCharmCand.fillTrkPID, assocParticle, candidate, outputMlPKPi, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, massCandPKPi, *mcParticles); if (isPrompt) { registry.fill(HIST("hPtCandMcRecSigPrompt"), ptCand); registry.fill(HIST("hPtVsMultiplicityMcRecPrompt"), ptCand, 0); @@ -1166,8 +1437,7 @@ struct HfCorrelatorLcScHadrons { } if (selLcPiKP) { - fillCorrelationTable(fillTrkPID, assocParticle, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, *mcParticles); - entryCandHadronRecoInfo(massCandPiKP, false); + fillCorrelationTable(cfgCharmCand.fillTrkPID, assocParticle, candidate, outputMlPiKP, poolBin, correlationStatus, yCand, chargeCand, ptScProng0, massCandPiKP, *mcParticles); if (isPrompt) { registry.fill(HIST("hPtCandMcRecSigPrompt"), ptCand); @@ -1194,8 +1464,8 @@ struct HfCorrelatorLcScHadrons { registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); // find leading particle - if (correlateLcWithLeadingParticle) { - leadingIndex = findLeadingParticleMcGen(mcParticles, etaTrackMax.value, ptTrackMin.value); + if (cfgCharmCand.correlateLcWithLeadingParticle) { + leadingIndex = findLeadingParticleMcGen(mcParticles, cfgCharmCand.etaTrackMax.value, cfgCharmCand.ptTrackMin.value); } // Mc Gen level for (const auto& particle : mcParticles) { @@ -1207,7 +1477,7 @@ struct HfCorrelatorLcScHadrons { } double const yCand = RecoDecay::y(particle.pVector(), massCand); - if (std::abs(yCand) > yCandGenMax || particle.pt() < ptCandMin) { + if (std::abs(yCand) > cfgCharmCand.yCandGenMax || particle.pt() < cfgCharmCand.ptCandMin) { continue; } registry.fill(HIST("hCandBin"), poolBin); @@ -1265,12 +1535,12 @@ struct HfCorrelatorLcScHadrons { // if it's a Lc particle, search for Hadron and evalutate correlations registry.fill(HIST("hcountCandtriggersMcGen"), 0, particle.pt()); // to count trigger Lc for normalisation for (const auto& particleAssoc : mcParticles) { - if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + if (std::abs(particleAssoc.eta()) > cfgCharmCand.etaTrackMax || particleAssoc.pt() < cfgCharmCand.ptTrackMin || particleAssoc.pt() > cfgCharmCand.ptTrackMax) { continue; } if (std::find(prongsId.begin(), prongsId.end(), particleAssoc.globalIndex()) != prongsId.end()) { - if (!storeAutoCorrelationFlag) { + if (!cfgCharmCand.storeAutoCorrelationFlag) { continue; } correlationStatus = true; @@ -1280,7 +1550,7 @@ struct HfCorrelatorLcScHadrons { continue; } - if (pidTrkApplied && (std::abs(particleAssoc.pdgCode()) != kProton)) { + if (cfgCharmCand.pidTrkApplied && (std::abs(particleAssoc.pdgCode()) != kProton)) { continue; // proton PID } @@ -1288,7 +1558,7 @@ struct HfCorrelatorLcScHadrons { continue; } - if (correlateLcWithLeadingParticle) { + if (cfgCharmCand.correlateLcWithLeadingParticle) { if (particleAssoc.globalIndex() != leadingIndex) { continue; } @@ -1422,7 +1692,7 @@ struct HfCorrelatorLcScHadrons { { BinningTypeMcGen const corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair const pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair const pairMcGen{corrBinningMcGen, cfgCharmCand.numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { @@ -1430,10 +1700,10 @@ struct HfCorrelatorLcScHadrons { continue; } double const yL = RecoDecay::y(candidate.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandGenMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { + if (std::abs(yL) > cfgCharmCand.yCandGenMax || candidate.pt() < cfgCharmCand.ptCandMin || candidate.pt() > cfgCharmCand.ptCandMax) { continue; } - if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + if (std::abs(particleAssoc.eta()) > cfgCharmCand.etaTrackMax || particleAssoc.pt() < cfgCharmCand.ptTrackMin || particleAssoc.pt() > cfgCharmCand.ptTrackMax) { continue; } if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { @@ -1442,7 +1712,7 @@ struct HfCorrelatorLcScHadrons { if (!particleAssoc.isPhysicalPrimary()) { continue; } - if (pidTrkApplied && (std::abs(particleAssoc.pdgCode()) != kProton)) { + if (cfgCharmCand.pidTrkApplied && (std::abs(particleAssoc.pdgCode()) != kProton)) { continue; // proton PID } int8_t const chargeLc = pdg->GetParticle(candidate.pdgCode())->Charge(); // Retrieve charge @@ -1466,19 +1736,26 @@ struct HfCorrelatorLcScHadrons { } PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenMixedEvent, "Process Mixed Event McGen", false); - void processDataLambdaV0(SelCollisions::iterator const&, - TracksData const& tracks, aod::V0Datas const& v0s) + // Updated processDataLambdaV0 to include Lc candidates + void processDataLambdaV0(SelCollisions::iterator const& collision, + TracksData const& tracks, + aod::V0Datas const& v0s, + CandsLcDataFiltered const& candidates, + aod::BCsWithTimestamps const&) { - fillV0Histograms(v0s, tracks); + fillV0HistogramsWithLc(collision, v0s, tracks, candidates); } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLambdaV0, "Data process for v0 lambda", false); + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLambdaV0, "Data process for v0 lambda with Lc", true); - void processMcLambdaV0(SelCollisions::iterator const&, - TracksWithMc const& tracks, soa::Join const& v0s, aod::McParticles const&) + void processMcLambdaV0(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + soa::Join const& v0s, + CandsLcMcRecFiltered const& candidates, + aod::McParticles const& mcParticles) { - fillV0Histograms(v0s, tracks); + fillV0HistogramsWithLc(collision, v0s, tracks, candidates, &mcParticles); } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcLambdaV0, "Mc process for v0 lambda", false); + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcLambdaV0, "Mc process for v0 lambda with Lc", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 055ef0c3916cb9d92fad347ca8c1a8c0d1e3a166 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Wed, 20 May 2026 10:39:23 +0200 Subject: [PATCH 239/449] [Common] legacy centrality QA: add vertex Z cut (#16317) Co-authored-by: ALICE Builder --- Common/Tasks/centralityQa.cxx | 37 +++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/Common/Tasks/centralityQa.cxx b/Common/Tasks/centralityQa.cxx index 51dc8875e08..ab7bd502377 100644 --- a/Common/Tasks/centralityQa.cxx +++ b/Common/Tasks/centralityQa.cxx @@ -28,6 +28,7 @@ using namespace o2::framework; struct CentralityQa { Configurable nBins{"nBins", 1050, "number of bins"}; Configurable INELgtZERO{"INELgtZERO", 1, "0 - no, 1 - yes"}; + Configurable vertexZcut{"vertexZcut", 10, "vertex-Z position cut (absolute value in cm)"}; OutputObj hCentRun2V0M{TH1F("hCentRun2V0M", "V0M", nBins, 0, 105.)}; OutputObj hCentRun2V0A{TH1F("hCentRun2V0A", "V0A", nBins, 0, 105.)}; OutputObj hCentRun2SPDTks{TH1F("hCentRun2SPDTks", "SPD Tracklets", nBins, 0, 105.)}; @@ -115,8 +116,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { return; + } + if (std::abs(col.posZ()) > vertexZcut) { + return; + } LOGF(debug, "centFV0A=%.0f", col.centFV0A()); hCentFV0A->Fill(col.centFV0A()); hCentProfileFV0A->Fill(col.centFV0A(), col.multNTracksPVetaHalf()); @@ -128,8 +133,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { + return; + } + if (std::abs(col.posZ()) > vertexZcut) { return; + } LOGF(debug, "centFT0M=%.0f", col.centFT0M()); hCentFT0M->Fill(col.centFT0M()); hCentProfileFT0M->Fill(col.centFT0M(), col.multNTracksPVetaHalf()); @@ -141,8 +150,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { + return; + } + if (std::abs(col.posZ()) > vertexZcut) { return; + } hCentFT0A->Fill(col.centFT0A()); hCentProfileFT0A->Fill(col.centFT0A(), col.multNTracksPVetaHalf()); } @@ -153,8 +166,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { return; + } + if (std::abs(col.posZ()) > vertexZcut) { + return; + } hCentFT0C->Fill(col.centFT0C()); hCentProfileFT0C->Fill(col.centFT0C(), col.multNTracksPVetaHalf()); } @@ -165,8 +182,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { + return; + } + if (std::abs(col.posZ()) > vertexZcut) { return; + } hCentFDDM->Fill(col.centFDDM()); hCentProfileFDDM->Fill(col.centFDDM(), col.multNTracksPVetaHalf()); } @@ -177,8 +198,12 @@ struct CentralityQa { if (INELgtZERO && col.multNTracksPVeta1() < 1) { return; } - if (!col.sel8()) + if (!col.sel8()) { + return; + } + if (std::abs(col.posZ()) > vertexZcut) { return; + } hCentNTPV->Fill(col.centNTPV()); hCentProfileNTPV->Fill(col.centNTPV(), col.multNTracksPVetaHalf()); } From 674b7a2642b9e4573fd72dbe2b237bcaf99d7391 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 20 May 2026 11:28:18 +0200 Subject: [PATCH 240/449] [Common] Fix initialisation order (#16299) --- Common/TableProducer/propagationServiceV2.cxx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Common/TableProducer/propagationServiceV2.cxx b/Common/TableProducer/propagationServiceV2.cxx index 151c39eb2bc..364d27101e6 100644 --- a/Common/TableProducer/propagationServiceV2.cxx +++ b/Common/TableProducer/propagationServiceV2.cxx @@ -109,26 +109,29 @@ struct propagationServiceV2 { strangenessBuilderModule.init(baseOpts, v0BuilderOpts, cascadeBuilderOpts, preSelectOpts, histos, initContext); } - // Load MatLUT once (needs rectifyPtrFromFile, kept manual), set B-field per run from - // GRPMagField CCDB column, and refresh mMeanVtx pointer every call (pointer into current - // BC table, valid only for the duration of this process() invocation). + // Load MatLUT once (needs rectifyPtrFromFile, kept manual), set B-field and mean vertex + // once per run from GRPMagField/MeanVertex CCDB columns. template void initCCDB(TBC const& bc0) { + if (ccdbLoader.runNumber != bc0.runNumber()) { + LOG(info) << "Setting B-field to current " << bc0.grpMagField().getL3Current() << " A for run " << bc0.runNumber() << " from GRPMagField CCDB column"; + o2::base::Propagator::initFieldFromGRP(&bc0.grpMagField()); + ccdbLoader.mMeanVtx = &bc0.meanVertex(); + ccdbLoader.runNumber = bc0.runNumber(); + } else { + // Verify the CCDB column buffer has not been replaced mid-run. + // The deserialised pointer must be stable for the lifetime of a run. + if (&bc0.meanVertex() != ccdbLoader.mMeanVtx) { + LOG(fatal) << "MeanVertex CCDB column pointer changed within run " << bc0.runNumber() << " — unexpected buffer replacement"; + } + } if (!ccdbLoader.lut) { LOG(info) << "Loading material look-up table for run: " << bc0.runNumber(); ccdbLoader.lut = o2::base::MatLayerCylSet::rectifyPtrFromFile( ccdb->template getForRun(standardCCDBLoaderConfigurables.lutPath.value, bc0.runNumber())); o2::base::Propagator::Instance()->setMatLUT(ccdbLoader.lut); } - // Always refresh: pointer into current BC table, invalidated after process() returns - ccdbLoader.mMeanVtx = &bc0.meanVertex(); - if (ccdbLoader.runNumber != bc0.runNumber()) { - const auto& grpmag = bc0.grpMagField(); // from declarative CCDB column - LOG(info) << "Setting B-field to current " << grpmag.getL3Current() << " A for run " << bc0.runNumber() << " from GRPMagField CCDB column"; - o2::base::Propagator::initFieldFromGRP(&grpmag); - ccdbLoader.runNumber = bc0.runNumber(); - } } void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, BCsWithCCDB const& bcs) From d7fa719f68b3cf9d54318a624c5d5ee6f1a956dd Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Wed, 20 May 2026 13:29:03 +0200 Subject: [PATCH 241/449] [ALICE3] Update histograms in otf decayer QA task (#16319) --- ALICE3/Tasks/alice3DecayerQa.cxx | 66 ++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index da97cac6989..ff01b24a93b 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \file alice3DecayerQA.cxx +/// \file alice3DecayerQa.cxx /// /// \brief QA task for otf decayer /// @@ -36,7 +36,7 @@ using namespace o2; using namespace o2::framework; -struct Alice3DecayerQA { +struct Alice3DecayerQa { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; SliceCache cache; @@ -68,6 +68,9 @@ struct Alice3DecayerQA { Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); + static constexpr size_t NCascadeDaughters = 2; + static constexpr size_t NV0Daughters = 2; + template float radius(const TParticle& particle) const { @@ -106,20 +109,27 @@ struct Alice3DecayerQA { histos.add("MCWithDau/hE", "hE", kTH1D, {axes.axisPt}); // QA with daughters from Decayer - histos.add("K0S/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); - histos.add("K0S/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); - histos.add("K0S/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("K0S/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("Lambda/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); - histos.add("Lambda/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); - histos.add("Lambda/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("Lambda/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("XiMinus/hGeneratedPt", "hGeneratedPt", kTH1D, {axes.axisPt}); - histos.add("XiMinus/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); - histos.add("XiMinus/hBachDauDecayRadius", "hBachDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("XiMinus/hV0DauDecayRadius", "hV0DauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("XiMinus/hPosDauDecayRadius", "hPosDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); - histos.add("XiMinus/hNegDauDecayRadius", "hNegDauDecayRadius", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("K0S/hGeneratedPt", "hGeneratedPt;#it{p}_{T} (GeV/#it{c})", kTH1D, {axes.axisPt}); + histos.add("K0S/hPosDauDecayRadius", "hPosDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("K0S/hNegDauDecayRadius", "hNegDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("Lambda/hGeneratedPt", "hGeneratedPt;#it{p}_{T} (GeV/#it{c})", kTH1D, {axes.axisPt}); + histos.add("Lambda/hPosDauDecayRadius", "hPosDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("Lambda/hNegDauDecayRadius", "hNegDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hGeneratedPt", "hGeneratedPt;#it{p}_{T} (GeV/#it{c})", kTH1D, {axes.axisPt}); + histos.add("XiMinus/hBachDauDecayRadius", "hBachDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hV0DauDecayRadius", "hV0DauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hPosDauDecayRadius", "hPosDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + histos.add("XiMinus/hNegDauDecayRadius", "hNegDauDecayRadius;Decay radius 2D;#it{p}_{T} (GeV/#it{c})", kTH2D, {axes.axisRadiusLog, axes.axisPtLog}); + + auto hCheckHasK0SDecayed = histos.add("K0S/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + hCheckHasK0SDecayed->GetXaxis()->SetBinLabel(1, "No"); + hCheckHasK0SDecayed->GetXaxis()->SetBinLabel(2, "Yes"); + auto hCheckHasLambdaDecayed = histos.add("Lambda/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + hCheckHasLambdaDecayed->GetXaxis()->SetBinLabel(1, "No"); + hCheckHasLambdaDecayed->GetXaxis()->SetBinLabel(2, "Yes"); + auto hCheckHasXiMinusDecayed = histos.add("XiMinus/hHasDecayed", "hHasDecayed", kTH1D, {{2, -0.5, 1.5}}); + hCheckHasXiMinusDecayed->GetXaxis()->SetBinLabel(1, "No"); + hCheckHasXiMinusDecayed->GetXaxis()->SetBinLabel(2, "Yes"); } void process(const aod::McCollision& collision, const aod::McPartWithDaus& particles) @@ -152,9 +162,9 @@ struct Alice3DecayerQA { for (const auto& particle : trueK0ShortGrouped) { histos.fill(HIST("K0S/hGeneratedPt"), particle.pt()); if (particle.has_daughters()) { - histos.fill(HIST("K0S/hHasDecayed"), 0); + histos.fill(HIST("K0S/hHasDecayed"), 1); auto daughters = particle.daughtersIds(); - if (daughters.size() == 2) { + if (daughters.size() == NV0Daughters) { auto dau0 = particles.rawIteratorAt(daughters.front()); auto dau1 = particles.rawIteratorAt(daughters.back()); @@ -169,15 +179,15 @@ struct Alice3DecayerQA { } } } else { - histos.fill(HIST("K0S/hHasDecayed"), 1); + histos.fill(HIST("K0S/hHasDecayed"), 0); } } for (const auto& particle : trueLambdasGrouped) { histos.fill(HIST("Lambda/hGeneratedPt"), particle.pt()); if (particle.has_daughters()) { - histos.fill(HIST("Lambda/hHasDecayed"), 0); + histos.fill(HIST("Lambda/hHasDecayed"), 1); auto daughters = particle.daughtersIds(); - if (daughters.size() == 2) { + if (daughters.size() == NV0Daughters) { auto dau0 = particles.rawIteratorAt(daughters[0]); auto dau1 = particles.rawIteratorAt(daughters[1]); @@ -192,15 +202,15 @@ struct Alice3DecayerQA { } } } else { - histos.fill(HIST("Lambda/hHasDecayed"), 1); + histos.fill(HIST("Lambda/hHasDecayed"), 0); } } for (const auto& particle : trueXiMinusGrouped) { histos.fill(HIST("XiMinus/hGeneratedPt"), particle.pt()); if (particle.has_daughters()) { - histos.fill(HIST("XiMinus/hHasDecayed"), 0); + histos.fill(HIST("XiMinus/hHasDecayed"), 1); auto daughters = particle.daughtersIds(); - if (daughters.size() == 2) { + if (daughters.size() == NCascadeDaughters) { auto dau0 = particles.rawIteratorAt(daughters.front()); auto dau1 = particles.rawIteratorAt(daughters.back()); @@ -216,7 +226,7 @@ struct Alice3DecayerQA { // Lambda -> p pi- if (v0.has_daughters()) { auto v0daughters = v0.daughtersIds(); - if (v0daughters.size() == 2) { + if (v0daughters.size() == NV0Daughters) { auto v0dau0 = particles.rawIteratorAt(v0daughters.front()); auto v0dau1 = particles.rawIteratorAt(v0daughters.back()); const bool lambdaDecay = (v0dau0.pdgCode() == PDG_t::kProton && v0dau1.pdgCode() == PDG_t::kPiMinus) || @@ -232,7 +242,7 @@ struct Alice3DecayerQA { } } } else { - histos.fill(HIST("XiMinus/hHasDecayed"), 1); + histos.fill(HIST("XiMinus/hHasDecayed"), 0); } } @@ -266,10 +276,10 @@ struct Alice3DecayerQA { } } - PROCESS_SWITCH(Alice3DecayerQA, process, "fill MC-with-dau histograms", true); + PROCESS_SWITCH(Alice3DecayerQa, process, "fill MC-with-dau histograms", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& ctx) { - return WorkflowSpec{adaptAnalysisTask(ctx)}; + return WorkflowSpec{adaptAnalysisTask(ctx)}; } From 63c4c001022bfe88d1133fa748f1f4acdc1f01e5 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Wed, 20 May 2026 14:40:06 +0200 Subject: [PATCH 242/449] [Common] Minor adjustments to match multCentTable function (#16320) Co-authored-by: ALICE Builder --- Common/Tasks/centralityStudypp.cxx | 70 ++++++++++++++++-------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index df4d2f9fbf4..a43f59e1973 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -329,40 +329,46 @@ struct centralityStudypp { float multNTracksGlobal = collision.multNTracksGlobal(); float mftNtracks = collision.mftNtracks(); float multNTracksPV = collision.multNTracksPV(); + if (applyVertexZEqualization) { float epsilon = 1e-2; // average value after which this collision will be disregarded - multFV0A = -1.0f; - multFT0A = -1.0f; - multFT0C = -1.0f; - multFDDA = -1.0f; - multFDDC = -1.0f; - multNTracksGlobal = -1.0f; - mftNtracks = -1.0f; - multNTracksPV = -1.0f; - - if (hVtxZFV0A->Interpolate(collision.multPVz()) > epsilon) { - multFV0A = hVtxZFV0A->Interpolate(0.0) * collision.multFV0A() / hVtxZFV0A->Interpolate(collision.multPVz()); - } - if (hVtxZFT0A->Interpolate(collision.multPVz()) > epsilon) { - multFT0A = hVtxZFT0A->Interpolate(0.0) * collision.multFT0A() / hVtxZFT0A->Interpolate(collision.multPVz()); - } - if (hVtxZFT0C->Interpolate(collision.multPVz()) > epsilon) { - multFT0C = hVtxZFT0C->Interpolate(0.0) * collision.multFT0C() / hVtxZFT0C->Interpolate(collision.multPVz()); - } - if (hVtxZFDDA->Interpolate(collision.multPVz()) > epsilon) { - multFDDA = hVtxZFDDA->Interpolate(0.0) * collision.multFDDA() / hVtxZFDDA->Interpolate(collision.multPVz()); - } - if (hVtxZFDDC->Interpolate(collision.multPVz()) > epsilon) { - multFDDC = hVtxZFDDC->Interpolate(0.0) * collision.multFDDC() / hVtxZFDDC->Interpolate(collision.multPVz()); - } - if (hVtxZNGlobals->Interpolate(collision.multPVz()) > epsilon) { - multNTracksGlobal = hVtxZNGlobals->Interpolate(0.0) * collision.multNTracksGlobal() / hVtxZNGlobals->Interpolate(collision.multPVz()); - } - if (hVtxZMFT->Interpolate(collision.multPVz()) > epsilon) { - mftNtracks = hVtxZMFT->Interpolate(0.0) * collision.mftNtracks() / hVtxZMFT->Interpolate(collision.multPVz()); - } - if (hVtxZNTracks->Interpolate(collision.multPVz()) > epsilon) { - multNTracksPV = hVtxZNTracks->Interpolate(0.0) * collision.multNTracksPV() / hVtxZNTracks->Interpolate(collision.multPVz()); + float maxVertexZ = 15.0f; // max value for any equalization attempt + + // same defaults as multCentTable in case of unhealthy signals + multFV0A = 0.0f; + multFT0A = 0.0f; + multFT0C = 0.0f; + multFDDA = 0.0f; + multFDDC = 0.0f; + multNTracksGlobal = 0.0f; + mftNtracks = 0.0f; + multNTracksPV = 0.0f; + + if (std::abs(collision.multPVz()) < maxVertexZ) { // operate consistently vs multCentTable + if (hVtxZFV0A->Interpolate(collision.multPVz()) > epsilon && collision.multFV0A() > -1.0f) { + multFV0A = hVtxZFV0A->Interpolate(0.0) * collision.multFV0A() / hVtxZFV0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0A->Interpolate(collision.multPVz()) > epsilon && collision.multFT0A() > -1.0f) { + multFT0A = hVtxZFT0A->Interpolate(0.0) * collision.multFT0A() / hVtxZFT0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0C->Interpolate(collision.multPVz()) > epsilon && collision.multFT0C() > -1.0f) { + multFT0C = hVtxZFT0C->Interpolate(0.0) * collision.multFT0C() / hVtxZFT0C->Interpolate(collision.multPVz()); + } + if (hVtxZFDDA->Interpolate(collision.multPVz()) > epsilon && collision.multFDDA() > -1.0f) { + multFDDA = hVtxZFDDA->Interpolate(0.0) * collision.multFDDA() / hVtxZFDDA->Interpolate(collision.multPVz()); + } + if (hVtxZFDDC->Interpolate(collision.multPVz()) > epsilon && collision.multFDDC() > -1.0f) { + multFDDC = hVtxZFDDC->Interpolate(0.0) * collision.multFDDC() / hVtxZFDDC->Interpolate(collision.multPVz()); + } + if (hVtxZNGlobals->Interpolate(collision.multPVz()) > epsilon && collision.multNTracksGlobal() > -1.0f) { + multNTracksGlobal = hVtxZNGlobals->Interpolate(0.0) * collision.multNTracksGlobal() / hVtxZNGlobals->Interpolate(collision.multPVz()); + } + if (hVtxZMFT->Interpolate(collision.multPVz()) > epsilon && collision.mftNtracks() > -1.0f) { + mftNtracks = hVtxZMFT->Interpolate(0.0) * collision.mftNtracks() / hVtxZMFT->Interpolate(collision.multPVz()); + } + if (hVtxZNTracks->Interpolate(collision.multPVz()) > epsilon && collision.multNTracksPV() > -1.0f) { + multNTracksPV = hVtxZNTracks->Interpolate(0.0) * collision.multNTracksPV() / hVtxZNTracks->Interpolate(collision.multPVz()); + } } } From 827fc0cc7ca8555d249e03ab48e91d6cecc299e6 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Wed, 20 May 2026 16:29:07 +0200 Subject: [PATCH 243/449] fix table filling in the otf-tracker (#16324) --- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 6e2e7d0e0a7..c7da0654e42 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -1731,6 +1731,7 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tableMcTrackLabels(trackParCov.mcLabel, 0); + tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits, trackParCov.trackType); // populate extra tables if required to do so @@ -1955,6 +1956,12 @@ struct OnTheFlyTracker { const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), std::abs(mcParticle.pdgCode())) != nucleiPDGs.end(); const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled); + + o2::upgrade::OTFParticle otfParticle(mcParticle); + if (otfParticle.hasNaN()) { + continue; + } + if (!pdgsToBeHandled) { continue; } From ecc41784232d319bc8c9870f125cba86cbcec81c Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Wed, 20 May 2026 17:11:25 +0200 Subject: [PATCH 244/449] [PWGLF] Add quadratic response option (#16323) --- PWGLF/TableProducer/QC/flowQC.cxx | 91 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index 2d590e0df69..ae946265d88 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -89,8 +89,6 @@ enum methods { }; static const std::vector suffixes = {"EP", "Qvec"}; -std::shared_ptr hQxQy[kNmethods][kNqVecDetectors]; -std::shared_ptr hNormQxQy[kNmethods][kNqVecDetectors]; std::shared_ptr hPsi[kNmethods][kNqVecDetectors]; std::shared_ptr hDeltaPsi[kNmethods][kNqVecDetectors][kNqVecDetectors]; std::shared_ptr hScalarProduct[kNmethods][kNqVecDetectors][kNqVecDetectors]; @@ -122,6 +120,7 @@ struct flowQC { float mBz = 0.f; Configurable cfgHarmonic{"cfgHarmonic", 2.f, "Harmonics for flow analysis"}; + Configurable cfgQuadraticResponse{"cfgQuadraticResponse", false, "Use quadratic response for Q-vector quantities"}; // Flow analysis using CollWithEPandQvec = soa::Join -cfgCutVertex && collision.posZ() < cfgCutVertex && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.triggereventep() && collision.selection_bit(aod::evsel::kNoSameBunchPileup); } - float computeEventPlane(float y, float x) + float computeEventPlane(float y, float x, float harmonic) { - return 0.5 * TMath::ATan2(y, x); + return (1.f / harmonic) * TMath::ATan2(y, x); } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -183,11 +182,7 @@ struct flowQC { const AxisSpec centAxis{cfgCentralityBins, fmt::format("{} percentile", (std::string)centDetectorNames[cfgCentralityEstimator])}; - const AxisSpec QxAxis{cfgQvecBins, Form("Q_{%.0f,x}", cfgHarmonic.value)}; - const AxisSpec QyAxis{cfgQvecBins, Form("Q_{%.0f,y}", cfgHarmonic.value)}; - - const AxisSpec NormQxAxis{cfgQvecBins, Form("#frac{Q_{%.0f,x}}{||#vec{Q_{%.0f}}||}", cfgHarmonic.value, cfgHarmonic.value)}; - const AxisSpec NormQyAxis{cfgQvecBins, Form("#frac{Q_{%.0f,y}}{||#vec{Q_{%.0f}}||}", cfgHarmonic.value, cfgHarmonic.value)}; + const char* qLabel = cfgQuadraticResponse ? "Q^{2}" : "Q"; const AxisSpec psiAxis{cfgPhiBins, Form("#psi_{%.0f}", cfgHarmonic.value)}; const AxisSpec psiCompAxis{cfgPhiBins, Form("#psi_{%.0f}^{EP} - #psi_{%.0f}^{Qvec}", cfgHarmonic.value, cfgHarmonic.value)}; @@ -206,8 +201,6 @@ struct flowQC { HistogramRegistry* registry = (iMethod == methods::kEP) ? &flow_ep : &flow_qvec; for (int iQvecDet = 0; iQvecDet < qVecDetectors::kNqVecDetectors; iQvecDet++) { - hQxQy[iMethod][iQvecDet] = registry->add(Form("hQxQy_%s_%s", qVecDetectorNames[iQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH3F, {centAxis, QxAxis, QyAxis}); - hNormQxQy[iMethod][iQvecDet] = registry->add(Form("hNormQxQy_%s_%s", qVecDetectorNames[iQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH3F, {centAxis, NormQxAxis, NormQyAxis}); hPsi[iMethod][iQvecDet] = registry->add(Form("hPsi_%s_%s", qVecDetectorNames[iQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, psiAxis}); for (int jQvecDet = iQvecDet + 1; jQvecDet < qVecDetectors::kNqVecDetectors; jQvecDet++) { @@ -215,12 +208,12 @@ struct flowQC { hDeltaPsi[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hDeltaPsi_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgDeltaPhiBins, Form("#psi_{%s} - #psi_{%s}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str())}}); // Scalar-product histograms - auto spLabel = Form("#vec{Q}_{%.0f}^{%s} #upoint #vec{Q}_{%.0f}^{%s}", cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); + auto spLabel = Form("#vec{%s}_{%.0f}^{%s} #upoint #vec{%s}_{%.0f}^{%s}", qLabel, cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), qLabel, cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); hScalarProduct[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hScalarProduct_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgQvecBins, spLabel}}); // Normalised scalar-product histograms - auto normSpLabel = Form("#frac{#vec{Q}_{%.0f}^{%s} #upoint #vec{Q}_{%.0f}^{%s}}{||#vec{Q}_{%.0f}^{%s}|| ||#vec{Q}_{%.0f}^{%s}||}", cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); + auto normSpLabel = Form("#frac{#vec{%s}_{%.0f}^{%s} #upoint #vec{%s}_{%.0f}^{%s}}{||#vec{%s}_{%.0f}^{%s}|| ||#vec{%s}_{%.0f}^{%s}||}", qLabel, cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), qLabel, cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str(), qLabel, cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), qLabel, cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); hNormalisedScalarProduct[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hNormalisedScalarProduct_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgQvecBins, normSpLabel}}); } @@ -270,74 +263,76 @@ struct flowQC { float centrality = getCentrality(collision); + auto maybeSquare = [this](float value) { + return cfgQuadraticResponse ? value * value : value; + }; + const float qvecHarmonic = cfgQuadraticResponse ? (cfgHarmonic.value / 2.f) : cfgHarmonic.value; + const int qvecHarmonicIndex = static_cast(qvecHarmonic) - 2; + // EP method - float QmodFT0A_EP = collision.qFT0A(); + float QmodFT0A_EP = maybeSquare(collision.qFT0A()); float psiFT0A_EP = collision.psiFT0A(); - float QxFT0A_EP = QmodFT0A_EP * std::cos(cfgHarmonic.value * psiFT0A_EP); - float QyFT0A_EP = QmodFT0A_EP * std::sin(cfgHarmonic.value * psiFT0A_EP); - float QmodFT0C_EP = collision.qFT0C(); + float QmodFT0C_EP = maybeSquare(collision.qFT0C()); float psiFT0C_EP = collision.psiFT0C(); - float QxFT0C_EP = QmodFT0C_EP * std::cos(cfgHarmonic.value * psiFT0C_EP); - float QyFT0C_EP = QmodFT0C_EP * std::sin(cfgHarmonic.value * psiFT0C_EP); - float QmodTPCl_EP = collision.qTPCL(); + float QmodTPCl_EP = maybeSquare(collision.qTPCL()); float psiTPCl_EP = collision.psiTPCL(); - float QxTPCl_EP = QmodTPCl_EP * std::cos(cfgHarmonic.value * psiTPCl_EP); - float QyTPCl_EP = QmodTPCl_EP * std::sin(cfgHarmonic.value * psiTPCl_EP); - float QmodTPCr_EP = collision.qTPCR(); + float QmodTPCr_EP = maybeSquare(collision.qTPCR()); float psiTPCr_EP = collision.psiTPCR(); - float QxTPCr_EP = QmodTPCr_EP * std::cos(cfgHarmonic.value * psiTPCr_EP); - float QyTPCr_EP = QmodTPCr_EP * std::sin(cfgHarmonic.value * psiTPCr_EP); - float QmodTPC_EP = collision.qTPC(); + float QmodTPC_EP = maybeSquare(collision.qTPC()); float psiTPC_EP = collision.psiTPC(); - float QxTPC_EP = QmodTPC_EP * std::cos(cfgHarmonic.value * psiTPC_EP); - float QyTPC_EP = QmodTPC_EP * std::sin(cfgHarmonic.value * psiTPC_EP); // Qvec method - float QxFT0A_Qvec = collision.qvecFT0AReVec()[cfgHarmonic.value - 2]; - float QyFT0A_Qvec = collision.qvecFT0AImVec()[cfgHarmonic.value - 2]; + float QxFT0A_Qvec_raw = collision.qvecFT0AReVec()[qvecHarmonicIndex]; + float QyFT0A_Qvec_raw = collision.qvecFT0AImVec()[qvecHarmonicIndex]; + float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec_raw, QxFT0A_Qvec_raw, qvecHarmonic); + float QxFT0A_Qvec = maybeSquare(QxFT0A_Qvec_raw); + float QyFT0A_Qvec = maybeSquare(QyFT0A_Qvec_raw); float QmodFT0A_Qvec = std::hypot(QxFT0A_Qvec, QyFT0A_Qvec); - float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec, QxFT0A_Qvec); - float QxFT0C_Qvec = collision.qvecFT0CReVec()[cfgHarmonic.value - 2]; - float QyFT0C_Qvec = collision.qvecFT0CImVec()[cfgHarmonic.value - 2]; + float QxFT0C_Qvec_raw = collision.qvecFT0CReVec()[qvecHarmonicIndex]; + float QyFT0C_Qvec_raw = collision.qvecFT0CImVec()[qvecHarmonicIndex]; + float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec_raw, QxFT0C_Qvec_raw, qvecHarmonic); + float QxFT0C_Qvec = maybeSquare(QxFT0C_Qvec_raw); + float QyFT0C_Qvec = maybeSquare(QyFT0C_Qvec_raw); float QmodFT0C_Qvec = std::hypot(QxFT0C_Qvec, QyFT0C_Qvec); - float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec, QxFT0C_Qvec); - float QxTPCl_Qvec = collision.qvecTPCnegReVec()[cfgHarmonic.value - 2]; - float QyTPCl_Qvec = collision.qvecTPCnegImVec()[cfgHarmonic.value - 2]; + float QxTPCl_Qvec_raw = collision.qvecTPCnegReVec()[qvecHarmonicIndex]; + float QyTPCl_Qvec_raw = collision.qvecTPCnegImVec()[qvecHarmonicIndex]; + float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec_raw, QxTPCl_Qvec_raw, qvecHarmonic); + float QxTPCl_Qvec = maybeSquare(QxTPCl_Qvec_raw); + float QyTPCl_Qvec = maybeSquare(QyTPCl_Qvec_raw); float QmodTPCl_Qvec = std::hypot(QxTPCl_Qvec, QyTPCl_Qvec); - float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec, QxTPCl_Qvec); - float QxTPCr_Qvec = collision.qvecTPCposReVec()[cfgHarmonic.value - 2]; - float QyTPCr_Qvec = collision.qvecTPCposImVec()[cfgHarmonic.value - 2]; + float QxTPCr_Qvec_raw = collision.qvecTPCposReVec()[qvecHarmonicIndex]; + float QyTPCr_Qvec_raw = collision.qvecTPCposImVec()[qvecHarmonicIndex]; + float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec_raw, QxTPCr_Qvec_raw, qvecHarmonic); + float QxTPCr_Qvec = maybeSquare(QxTPCr_Qvec_raw); + float QyTPCr_Qvec = maybeSquare(QyTPCr_Qvec_raw); float QmodTPCr_Qvec = std::hypot(QxTPCr_Qvec, QyTPCr_Qvec); - float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec, QxTPCr_Qvec); - float QxTPC_Qvec = collision.qvecTPCallReVec()[cfgHarmonic.value - 2]; - float QyTPC_Qvec = collision.qvecTPCallImVec()[cfgHarmonic.value - 2]; + float QxTPC_Qvec_raw = collision.qvecTPCallReVec()[qvecHarmonicIndex]; + float QyTPC_Qvec_raw = collision.qvecTPCallImVec()[qvecHarmonicIndex]; + float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec_raw, QxTPC_Qvec_raw, qvecHarmonic); + float QxTPC_Qvec = maybeSquare(QxTPC_Qvec_raw); + float QyTPC_Qvec = maybeSquare(QyTPC_Qvec_raw); float QmodTPC_Qvec = std::hypot(QxTPC_Qvec, QyTPC_Qvec); - float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec, QxTPC_Qvec); - std::array vec_Qx[2] = {{QxFT0C_EP, QxFT0A_EP, QxTPCl_EP, QxTPCr_EP, QxTPC_EP}, {QxFT0C_Qvec, QxFT0A_Qvec, QxTPCl_Qvec, QxTPCr_Qvec, QxTPC_Qvec}}; - std::array vec_Qy[2] = {{QyFT0C_EP, QyFT0A_EP, QyTPCl_EP, QyTPCr_EP, QyTPC_EP}, {QyFT0C_Qvec, QyFT0A_Qvec, QyTPCl_Qvec, QyTPCr_Qvec, QyTPC_Qvec}}; std::array vec_Qmod[2] = {{QmodFT0C_EP, QmodFT0A_EP, QmodTPCl_EP, QmodTPCr_EP, QmodTPC_EP}, {QmodFT0C_Qvec, QmodFT0A_Qvec, QmodTPCl_Qvec, QmodTPCr_Qvec, QmodTPC_Qvec}}; std::array vec_Qpsi[2] = {{psiFT0C_EP, psiFT0A_EP, psiTPCl_EP, psiTPCr_EP, psiTPC_EP}, {psiFT0C_Qvec, psiFT0A_Qvec, psiTPCl_Qvec, psiTPCr_Qvec, psiTPC_Qvec}}; for (int iMethod = 0; iMethod < methods::kNmethods; iMethod++) { for (int iQvecDet = 0; iQvecDet < qVecDetectors::kNqVecDetectors; iQvecDet++) { - hQxQy[iMethod][iQvecDet]->Fill(centrality, vec_Qx[iMethod][iQvecDet], vec_Qy[iMethod][iQvecDet]); - hNormQxQy[iMethod][iQvecDet]->Fill(centrality, vec_Qx[iMethod][iQvecDet] / vec_Qmod[iMethod][iQvecDet], vec_Qy[iMethod][iQvecDet] / vec_Qmod[iMethod][iQvecDet]); hPsi[iMethod][iQvecDet]->Fill(centrality, vec_Qpsi[iMethod][iQvecDet]); for (int jQvecDet = iQvecDet + 1; jQvecDet < qVecDetectors::kNqVecDetectors; jQvecDet++) { // Q-vector azimuthal-angle differences hDeltaPsi[iMethod][iQvecDet][jQvecDet]->Fill(centrality, vec_Qpsi[iMethod][iQvecDet] - vec_Qpsi[iMethod][jQvecDet]); // Scalar-product histograms auto getSP = [&](int iDet1, int iDet2) { - return vec_Qx[iMethod][iDet1] * vec_Qx[iMethod][iDet2] + vec_Qy[iMethod][iDet1] * vec_Qy[iMethod][iDet2]; + return vec_Qmod[iMethod][iDet1] * vec_Qmod[iMethod][iDet2] * std::cos(cfgHarmonic.value * (vec_Qpsi[iMethod][iDet1] - vec_Qpsi[iMethod][iDet2])); }; hScalarProduct[iMethod][iQvecDet][jQvecDet]->Fill(centrality, getSP(iQvecDet, jQvecDet)); // Normalised scalar-product histograms From dfb477fa780132494eea95da18514b2a2daa4449 Mon Sep 17 00:00:00 2001 From: Lucas Ferrandi de Oliveira <70455848+LucasFerrandi@users.noreply.github.com> Date: Wed, 20 May 2026 17:39:50 +0200 Subject: [PATCH 245/449] [PWGDQ] Add jpsiKineDcaQualitynoPID2 cut and Change binning (#16003) --- PWGDQ/Core/CutsLibrary.cxx | 6 ++++++ PWGDQ/Core/HistogramsLibrary.cxx | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index bcd357e3e6d..f999af41b0e 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -288,6 +288,12 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug")); return cut; } + if (!nameStr.compare("jpsiKineDcaQualitynoPID2")) { + cut->AddCut(GetAnalysisCut("jpsiKineSkimmed")); + cut->AddCut(GetAnalysisCut("dcaCut1_ionut")); + cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug4")); + return cut; + } if (!nameStr.compare("electronSelection1_ionut_withTOFPID")) { cut->AddCut(GetAnalysisCut("jpsiStandardKine")); cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug")); diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 6bba77c8d40..9a9513634fd 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1203,7 +1203,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "CentFT0CMC", "MC Cent. FT0C", false, 18, 0., 90., VarManager::kMCEventCentrFT0C); hm->AddHistogram(histClass, "PtMC_YMC", "MC pT vs MC y", false, 120, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY); hm->AddHistogram(histClass, "PtMC_YMC_CentFT0CMC", "MC pT vs MC y vs MC Cent. FT0C", false, 300, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY, 20, 0., 100., VarManager::kMCEventCentrFT0C); - hm->AddHistogram(histClass, "EtaMC_PtMC", "", false, 40, -2.0, 2.0, VarManager::kMCEta, 200, 0.0, 20.0, VarManager::kMCPt); + hm->AddHistogram(histClass, "EtaMC_PtMC", "", false, 320, -2.0, 2.0, VarManager::kMCEta, 400, 0.0, 40.0, VarManager::kMCPt); hm->AddHistogram(histClass, "VzMC", "MC vz", false, 100, -15.0, 15.0, VarManager::kMCVz); hm->AddHistogram(histClass, "VzMC_VtxZMC", "MC vz vs MC vtxZ", false, 50, -15.0, 15.0, VarManager::kMCVz, 50, -15.0, 15.0, VarManager::kMCVtxZ); hm->AddHistogram(histClass, "Weight", "", false, 50, 0.0, 5.0, VarManager::kMCParticleWeight); @@ -1296,7 +1296,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h ptBins[50 + i] = 0.5 + i * 0.5; } hm->AddHistogram(histClass, "Mass_PtFine", "", false, 75, massBins, VarManager::kMass, 69, ptBins, VarManager::kPt); - hm->AddHistogram(histClass, "Eta_Pt", "", false, 40, -2.0, 2.0, VarManager::kEta, 40, 0.0, 20.0, VarManager::kPt); + hm->AddHistogram(histClass, "Eta_Pt", "", false, 320, -2.0, 2.0, VarManager::kEta, 400, 0.0, 40.0, VarManager::kPt); hm->AddHistogram(histClass, "Y_Pt", "", false, 40, -2.0, 2.0, VarManager::kRap, 40, 0.0, 20.0, VarManager::kPt); hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 500, 0.0, 5.0, VarManager::kMass); if (subGroupStr.Contains("energy-correlator")) { @@ -2320,7 +2320,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "PhiMC", "MC #phi", false, 50, -6.3, 6.3, VarManager::kMCPhi); hm->AddHistogram(histClass, "YMC", "MC y", false, 50, -5.0, 5.0, VarManager::kMCY); hm->AddHistogram(histClass, "PtMC_YMC", "MC pT vs MC y", false, 120, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY); - hm->AddHistogram(histClass, "EtaMC_PtMC", "", false, 40, -2.0, 2.0, VarManager::kMCEta, 200, 0.0, 20.0, VarManager::kMCPt); + hm->AddHistogram(histClass, "EtaMC_PtMC", "", false, 320, -2.0, 2.0, VarManager::kMCEta, 400, 0.0, 40.0, VarManager::kMCPt); hm->AddHistogram(histClass, "VzMC", "MC vz", false, 100, -15.0, 15.0, VarManager::kMCVz); hm->AddHistogram(histClass, "VzMC_VtxZMC", "MC vz vs MC vtxZ", false, 50, -15.0, 15.0, VarManager::kMCVz, 50, -15.0, 15.0, VarManager::kMCVtxZ); hm->AddHistogram(histClass, "LzMC", "", false, 1000, 0.0, 2.0, VarManager::kMCVertexingLz); From 0f872a51fc6737a6f08f0497c21bcdc6a93f292c Mon Sep 17 00:00:00 2001 From: Pravata Panigrahi <158029188+pravatp98@users.noreply.github.com> Date: Wed, 20 May 2026 22:14:08 +0530 Subject: [PATCH 246/449] [PWGCF] Net charge fluctuations3 (#16314) --- .../EbyEFluctuations/Tasks/nchCumulantsId.cxx | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index c10ece98349..0e23058ea7d 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -48,6 +48,12 @@ using namespace std; #define ID_BIT_EL 3 #define ID_BIT_DE 4 +#define MC_BIT_PI 0 // MC particle identification bits +#define MC_BIT_KA 1 +#define MC_BIT_PR 2 +#define MC_BIT_EL 3 +#define MC_BIT_DE 4 + #define BITSET(mask, ithBit) ((mask) |= (1 << (ithBit))) // avoid name bitset as std::bitset is already there #define BITCHECK(mask, ithBit) ((mask) & (1 << (ithBit))) // bit check will return int value, not bool, use BITCHECK != 0 in Analysi @@ -108,6 +114,7 @@ struct NchCumulantsId { Configurable checkCollPosZMc{"checkCollPosZMc", false, "checkCollPosZMc"}; Configurable flagUnusedVariableError{"flagUnusedVariableError", false, "flagUnusedVariableError"}; + Configurable cfgDoRejectionForId{"cfgDoRejectionForId", false, "Apply rejection cut before PID selection (selTrackForId)"}; Configurable cfgEvSel01doNoSameBunchPileup{"cfgEvSel01doNoSameBunchPileup", true, "apply kNoSameBunchPileup"}; Configurable cfgEvSel02doIsGoodZvtxFT0vsPV{"cfgEvSel02doIsGoodZvtxFT0vsPV", true, "apply kIsGoodZvtxFT0vsPV"}; @@ -150,6 +157,12 @@ struct NchCumulantsId { Configurable cfgIdPr08NSigmaTOFHighP{"cfgIdPr08NSigmaTOFHighP", 2.0, "cfgIdPr08NSigmaTOFHighP"}; Configurable cfgIdPr09NSigmaRadHighP{"cfgIdPr09NSigmaRadHighP", 4.0, "cfgIdPr09NSigmaRadHighP"}; + Configurable cfgIdElRejLowNSigma{"cfgIdElRejLowNSigma", -3.0, "cfgIdElRejLowNSigma"}; + Configurable cfgIdElRejHighNSigma{"cfgIdElRejHighNSigma", 5.0, "cfgIdElRejHighNSigma"}; + Configurable cfgIdPiRejNSigma{"cfgIdPiRejNSigma", 3.0, "cfgIdPiRejNSigma"}; + Configurable cfgIdKaRejNSigma{"cfgIdKaRejNSigma", 3.0, "cfgIdKaRejNSigma"}; + Configurable cfgIdPrRejNSigma{"cfgIdPrRejNSigma", 3.0, "cfgIdPrRejNSigma"}; + struct : ConfigurableGroup { Configurable cfgVetoId01PiTPC{"cfgVetoId01PiTPC", 3.0, "cfgVetoId01PiTPC"}; Configurable cfgVetoId02PiTOF{"cfgVetoId02PiTOF", 3.0, "cfgVetoId02PiTOF"}; @@ -244,8 +257,13 @@ struct NchCumulantsId { const AxisSpec axisPiCh(101, -1, 100, "Pion_Positive"); const AxisSpec axisAPiCh(101, -1, 100, "Pion_Negative"); + const AxisSpec axisIdTag = {32, -0.5f, 31.5f, "idTag"}; + const AxisSpec axisMcTag = {32, -0.5f, 31.5f, "mcTag"}; + HistogramConfigSpec qnHist1({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPrCh, axisAPrCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); HistogramConfigSpec qnHist2({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPiCh, axisAPiCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); + HistogramConfigSpec histTPCPIDSparse({HistType::kTHnSparseD, {axisP, axisTPCNSigma, axisIdTag, axisMcTag}}); + HistogramConfigSpec histTOFPIDSparse({HistType::kTHnSparseD, {axisP, axisTOFNSigma, axisIdTag, axisMcTag}}); HistogramConfigSpec histPPt({HistType::kTH2F, {axisP, axisPt}}); HistogramConfigSpec histPTpcInnerParam({HistType::kTH2F, {axisP, axisTPCInnerParam}}); @@ -265,6 +283,17 @@ struct NchCumulantsId { HistogramConfigSpec histPtMc({HistType::kTH1F, {axisPt}}); + // Register histograms for PID validation + // Register TPC spares per species + hist.add("PIDValidation/tpcSparse_Pi", "p vs tpcNSigmaPi vs idTag vs mcTag (Pion)", histTPCPIDSparse); + hist.add("PIDValidation/tpcSparse_Ka", "p vs tpcNSigmaKa vs idTag vs mcTag (Kaon)", histTPCPIDSparse); + hist.add("PIDValidation/tpcSparse_Pr", "p vs tpcNSigmaPr vs idTag vs mcTag (Proton)", histTPCPIDSparse); + + // Register TOF spares per species + hist.add("PIDValidation/tofSparse_Pi", "p vs tofNSigmaPi vs idTag vs mcTag (Pion)", histTOFPIDSparse); + hist.add("PIDValidation/tofSparse_Ka", "p vs tofNSigmaKa vs idTag vs mcTag (Kaon)", histTOFPIDSparse); + hist.add("PIDValidation/tofSparse_Pr", "p vs tofNSigmaPr vs idTag vs mcTag (Proton)", histTOFPIDSparse); + // QA check histos hist.add("QA/events/preSel/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); @@ -762,8 +791,44 @@ struct NchCumulantsId { } } + template + int getMCTag(const T& track) + { + int mcTag = 0; + if (!track.has_mcParticle()) + return mcTag; + auto mcPart = track.mcParticle(); + int pdgCode = std::abs(mcPart.pdgCode()); + + if (pdgCode == kPiPlus || pdgCode == kPiMinus) + BITSET(mcTag, MC_BIT_PI); + else if (pdgCode == kKPlus || pdgCode == kKMinus) + BITSET(mcTag, MC_BIT_KA); + else if (pdgCode == kProton || pdgCode == kProtonBar) + BITSET(mcTag, MC_BIT_PR); + else if (pdgCode == kElectron || pdgCode == kPositron) + BITSET(mcTag, MC_BIT_EL); + else if (pdgCode == kDeuteron || pdgCode == -kDeuteron) + BITSET(mcTag, MC_BIT_DE); + + return mcTag; + } // //______________________________Identification Functions________________________________________________________________ + // Victor slection cuts for electron and other rejections + template + bool selTrackForId(const T& track) + { + if (cfgIdElRejLowNSigma < track.tpcNSigmaEl() && track.tpcNSigmaEl() < cfgIdElRejHighNSigma && + std::fabs(track.tpcNSigmaPi()) > cfgIdPiRejNSigma && + std::fabs(track.tpcNSigmaKa()) > cfgIdKaRejNSigma && + std::fabs(track.tpcNSigmaPr()) > cfgIdPrRejNSigma) { + return false; + } else { + return true; + } + } + // Pion template bool selPion(const T& track, int& IdMethod) @@ -1137,6 +1202,11 @@ struct NchCumulantsId { nM += hPtEtaForEffCorrection[kCh][kNeg]->GetBinContent(ptEtaBin); } + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + int idMethod; // pion if (selPion(track, idMethod)) { @@ -1235,17 +1305,34 @@ struct NchCumulantsId { idMethodKa = kUnidentified; idMethodPr = kUnidentified; + // Get MC tag + int mcTag = getMCTag(track); + + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + if (selPion(track, idMethodPi)) { trackIsPion = true; BITSET(trackIdTag, ID_BIT_PI); + hist.fill(HIST("PIDValidation/tpcSparse_Pi"), track.p(), track.tpcNSigmaPi(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Pi"), track.p(), track.tofNSigmaPi(), trackIdTag, mcTag); } if (selKaon(track, idMethodKa)) { trackIsKaon = true; BITSET(trackIdTag, ID_BIT_KA); + hist.fill(HIST("PIDValidation/tpcSparse_Ka"), track.p(), track.tpcNSigmaKa(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Ka"), track.p(), track.tofNSigmaKa(), trackIdTag, mcTag); } if (selProton(track, idMethodPr)) { trackIsProton = true; BITSET(trackIdTag, ID_BIT_PR); + hist.fill(HIST("PIDValidation/tpcSparse_Pr"), track.p(), track.tpcNSigmaPr(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Pr"), track.p(), track.tofNSigmaPr(), trackIdTag, mcTag); } if constexpr (analysisType == doPurityProcessing) { @@ -1555,6 +1642,8 @@ struct NchCumulantsId { continue; int pdg = mcPart.pdgCode(); + int mcTag = getMCTag(track); + fillTrackQA(track); trackIsPion = false; @@ -1565,17 +1654,41 @@ struct NchCumulantsId { idMethodKa = kUnidentified; idMethodPr = kUnidentified; + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + + // Fill separate spares for each species if it passes the cut if (selPion(track, idMethodPi)) { trackIsPion = true; BITSET(trackIdTag, ID_BIT_PI); + // Fill TPC sparse for pion + hist.fill(HIST("PIDValidation/tpcSparse_Pi"), track.p(), track.tpcNSigmaPi(), trackIdTag, mcTag); + // Fill TOF sparse for pion if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Pi"), track.p(), track.tofNSigmaPi(), trackIdTag, mcTag); + } } if (selKaon(track, idMethodKa)) { trackIsKaon = true; BITSET(trackIdTag, ID_BIT_KA); + // Fill TPC sparse for kaon + hist.fill(HIST("PIDValidation/tpcSparse_Ka"), track.p(), track.tpcNSigmaKa(), trackIdTag, mcTag); + // Fill TOF sparse for kaon if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Ka"), track.p(), track.tofNSigmaKa(), trackIdTag, mcTag); + } } if (selProton(track, idMethodPr)) { trackIsProton = true; BITSET(trackIdTag, ID_BIT_PR); + // Fill TPC sparse for proton + hist.fill(HIST("PIDValidation/tpcSparse_Pr"), track.p(), track.tpcNSigmaPr(), trackIdTag, mcTag); + // Fill TOF sparse for proton if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Pr"), track.p(), track.tofNSigmaPr(), trackIdTag, mcTag); + } } // bool isKnownCharged = (std::abs(pdg) == kPiPlus || @@ -1614,6 +1727,11 @@ struct NchCumulantsId { nAPiRec += hPtEtaForEffCorrection[kPi][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for pions + if (idMethodPi == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodPi == kTPCTOFidentified) + fillIdentificationQA(hist, track); } else if (trackIsKaon) { if (track.sign() > 0) { nKaRec += hPtEtaForEffCorrection[kKa][kPos]->GetBinContent(ptEtaBin); @@ -1622,6 +1740,11 @@ struct NchCumulantsId { nAKaRec += hPtEtaForEffCorrection[kKa][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for kaons + if (idMethodKa == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodKa == kTPCTOFidentified) + fillIdentificationQA(hist, track); } else if (trackIsProton) { if (track.sign() > 0) { nPrRec += hPtEtaForEffCorrection[kPr][kPos]->GetBinContent(ptEtaBin); @@ -1630,6 +1753,11 @@ struct NchCumulantsId { nAPrRec += hPtEtaForEffCorrection[kPr][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for protons + if (idMethodPr == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodPr == kTPCTOFidentified) + fillIdentificationQA(hist, track); } // purity check - check pdg aginst sign bool purityPion = false; From 46abb77880bf45692b3f2f4392665efd1b56b3b2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Wed, 20 May 2026 19:58:05 +0200 Subject: [PATCH 247/449] [PWGLF] Add rapidity cut and charged-particle histograms for MB data (#16328) --- .../Strangeness/strangenessInJetsIons.cxx | 146 +++++++++++++----- 1 file changed, 109 insertions(+), 37 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index 9d5b341c884..efe715d91be 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -93,6 +93,7 @@ using DaughterTracks = soa::Join; using DaughterTracksMC = soa::Join; +using DaughterTracksMB = soa::Join; struct StrangenessInJetsIons { @@ -135,6 +136,7 @@ struct StrangenessInJetsIons { Configurable centrEstimator{"centrEstimator", 1, "Select centrality estimator. Options: 0 = FT0C, 1 = FT0M. CCDB objects available only for FT0M."}; Configurable calculateFeeddownMatrix{"calculateFeeddownMatrix", true, "Fill feeddown matrix for Lambda if MC"}; Configurable useV0inJetRec{"useV0inJetRec", true, "Include V0s in jet reconstruction"}; + Configurable saveChargedParticleMB{"saveChargedParticleMB", false, "Store charged particle information to build inclusive spectra."}; // Event selection Configurable requireNoSameBunchPileup{"requireNoSameBunchPileup", true, "Require kNoSameBunchPileup selection"}; @@ -287,7 +289,7 @@ struct StrangenessInJetsIons { registryData.add("number_of_events_vsmultiplicity", "number of events in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); // For MB - registryData.add("number_of_events_vsmultiplicity_MB", "number of events in data vs multiplicity (MB)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + // registryData.add("number_of_events_vsmultiplicity_MB", "number of events in data vs multiplicity (MB)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(1, "All collisions"); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(2, "Zorro selection"); @@ -555,17 +557,17 @@ struct StrangenessInJetsIons { if (doprocessDataMB) { // Event counters - registryDataMB.add("number_of_events_data", "number of events in data", HistType::kTH1D, {{20, 0, 20, "Event Cuts"}}); - registryDataMB.add("number_of_events_vsmultiplicity", "number of events in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); - - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(1, "All collisions"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(2, "Zorro selection"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(3, "sel8"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(4, "posZ cut"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(7, "No empty events"); - registryDataMB.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(8, "At least one jet"); + registryDataMB.add("number_of_events_data_MB", "number of events in data (MB)", HistType::kTH1D, {{20, 0, 20, "Event Cuts"}}); + registryDataMB.add("number_of_events_vsmultiplicity_MB", "number of events in data vs multiplicity (MB)", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(1, "All collisions"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(2, "Zorro selection"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(3, "sel8"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(4, "posZ cut"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(7, "No empty events"); + registryDataMB.get(HIST("number_of_events_data_MB"))->GetXaxis()->SetBinLabel(8, "At least one jet"); // Histograms for analysis of strange hadrons if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -588,6 +590,9 @@ struct StrangenessInJetsIons { if (particleOfInterestDict[ParticleOfInterest::kProtons]) { registryDataMB.add("Proton_in_MB", "Proton_in_MB", HistType::kTHnSparseF, {multAxis, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); } + if (saveChargedParticleMB) { + registryDataMB.add("ChargedTrack_in_MB", "ChargedTrack_in_MB", HistType::kTH2F, {multAxis, ptAxis}); + } } } @@ -1189,6 +1194,64 @@ struct StrangenessInJetsIons { return true; } + // --- MB Selections ------------------------------------ + // The rapidty cut is added, which is not required in jet and UE + // K0s selections (MB) + template + bool passedK0ShortSelectionMB(const K0short& v0, const TrackPos& ptrack, const TrackNeg& ntrack, const TVector3& vtxPos) + { + bool passedSel = passedK0ShortSelection(v0, ptrack, ntrack, vtxPos); + + if (!passedRapidityCut(v0.yK0Short(), configV0.rapidityMax)) + return false; + return passedSel; + } + + // Lambda selections (MB) + template + bool passedLambdaSelectionMB(const Lambda& v0, const TrackPos& ptrack, const TrackNeg& ntrack, const TVector3& vtxPos) + { + bool passedSel = passedLambdaSelection(v0, ptrack, ntrack, vtxPos); + + if (!passedRapidityCut(v0.yLambda(), configV0.rapidityMax)) + return false; + return passedSel; + } + + // AntiLambda selections (MB) + template + bool passedAntiLambdaSelectionMB(const AntiLambda& v0, const TrackPos& ptrack, const TrackNeg& ntrack, const TVector3& vtxPos) + { + bool passedSel = passedAntiLambdaSelection(v0, ptrack, ntrack, vtxPos); + + if (!passedRapidityCut(v0.yLambda(), configV0.rapidityMax)) + return false; + return passedSel; + } + + // Xi Selections (MB) + template + bool passedXiSelectionMB(const Xi& casc, const TrackPos& ptrack, const TrackNeg& ntrack, const TrackBac& btrack, const Coll& coll) + { + bool passedSel = passedXiSelection(casc, ptrack, ntrack, btrack, coll); + + if (!passedRapidityCut(casc.yXi(), configV0.rapidityMax)) + return false; + return passedSel; + } + + // Omega selections (MB) + template + bool passedOmegaSelectionMB(const Omega& casc, const TrackPos& ptrack, const TrackNeg& ntrack, const TrackBac& btrack, const Coll& coll) + { + bool passedSel = passedOmegaSelection(casc, ptrack, ntrack, btrack, coll); + + if (!passedRapidityCut(casc.yOmega(), configV0.rapidityMax)) + return false; + return passedSel; + } + // ------------------------------------------------------ + // Event selection for MC Reco collision template bool selectRecoEvent(const coll& recoColl) @@ -1911,13 +1974,13 @@ struct StrangenessInJetsIons { registryData.fill(HIST("number_of_events_data"), 5.5); // Event multiplicity - float centrality; - if (centrEstimator == 0) { - centrality = collision.centFT0C(); - } else { - centrality = collision.centFT0M(); - } - registryData.fill(HIST("number_of_events_vsmultiplicity_MB"), centrality); + // float centrality; + // if (centrEstimator == 0) { + // centrality = collision.centFT0C(); + // } else { + // centrality = collision.centFT0M(); + // } + // registryData.fill(HIST("number_of_events_vsmultiplicity_MB"), centrality); // Loop over reconstructed tracks std::vector fjParticles; @@ -2331,7 +2394,7 @@ struct StrangenessInJetsIons { // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); + double coneRadius = std::sqrt(jet.area() / PI); // TODO: replace with rJet (similar results) TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -3225,14 +3288,14 @@ struct StrangenessInJetsIons { // --- Process Minimum Bias events --- // Process data MB void processDataMB(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, - aod::CascDataExt const& Cascades, DaughterTracks const& tracks, + aod::CascDataExt const& Cascades, DaughterTracksMB const& tracks, aod::BCsWithTimestamps const&) { // Vertex position vector TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); // Fill event counter before event selection - registryDataMB.fill(HIST("number_of_events_data"), 0.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 0.5); // Get the bunch crossing (BC) information associated with the collision auto bc = collision.template bc_as(); @@ -3246,35 +3309,35 @@ struct StrangenessInJetsIons { } // Fill event counter after zorro selection - registryDataMB.fill(HIST("number_of_events_data"), 1.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 1.5); // Event selection if (!collision.sel8()) return; // Fill event counter after sel8 selection - registryDataMB.fill(HIST("number_of_events_data"), 2.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 2.5); // Require vertex position within the allowed z range if (std::fabs(collision.posZ()) > zVtx) return; // Fill event counter after z vertex selection - registryDataMB.fill(HIST("number_of_events_data"), 3.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 3.5); // Reject collisions associated to the same found BC if (requireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) return; // Fill event counter after selection kNoSameBunchPileup - registryDataMB.fill(HIST("number_of_events_data"), 4.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 4.5); // Compatible z_vtx from FT0 and from PV if (requireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return; // Fill event counter after selection kIsGoodZvtxFT0vsPV - registryDataMB.fill(HIST("number_of_events_data"), 5.5); + registryDataMB.fill(HIST("number_of_events_data_MB"), 5.5); // Event multiplicity float centrality; @@ -3283,26 +3346,35 @@ struct StrangenessInJetsIons { } else { centrality = collision.centFT0M(); } - registryDataMB.fill(HIST("number_of_events_vsmultiplicity"), centrality); + registryDataMB.fill(HIST("number_of_events_vsmultiplicity_MB"), centrality); + + if (saveChargedParticleMB) { + for (const auto& trk : tracks) { + if (!passedTrackSelectionForJetReconstruction(trk) || !trk.isGlobalTrack()) { + continue; + } + registryDataMB.fill(HIST("ChargedTrack_in_MB"), centrality, trk.pt()); + } + } if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { // V0s for (const auto& v0 : fullV0s) { // Get V0 daughters - const auto& pos = v0.posTrack_as(); - const auto& neg = v0.negTrack_as(); + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); TVector3 v0dir(v0.px(), v0.py(), v0.pz()); // K0s - if (passedK0ShortSelection(v0, pos, neg, vtxPos)) { + if (passedK0ShortSelectionMB(v0, pos, neg, vtxPos)) { registryDataMB.fill(HIST("K0s_in_MB"), centrality, v0.pt(), v0.mK0Short()); } // Lambda - if (passedLambdaSelection(v0, pos, neg, vtxPos)) { + if (passedLambdaSelectionMB(v0, pos, neg, vtxPos)) { registryDataMB.fill(HIST("Lambda_in_MB"), centrality, v0.pt(), v0.mLambda()); } // AntiLambda - if (passedAntiLambdaSelection(v0, pos, neg, vtxPos)) { + if (passedAntiLambdaSelectionMB(v0, pos, neg, vtxPos)) { registryDataMB.fill(HIST("AntiLambda_in_MB"), centrality, v0.pt(), v0.mAntiLambda()); } } @@ -3317,19 +3389,19 @@ struct StrangenessInJetsIons { TVector3 cascadeDir(casc.px(), casc.py(), casc.pz()); // Xi+ - if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { + if (passedXiSelectionMB(casc, pos, neg, bach, collision) && bach.sign() > 0) { registryDataMB.fill(HIST("XiPos_in_MB"), centrality, casc.pt(), casc.mXi()); } // Xi- - if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { + if (passedXiSelectionMB(casc, pos, neg, bach, collision) && bach.sign() < 0) { registryDataMB.fill(HIST("XiNeg_in_MB"), centrality, casc.pt(), casc.mXi()); } // Omega+ - if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { + if (passedOmegaSelectionMB(casc, pos, neg, bach, collision) && bach.sign() > 0) { registryDataMB.fill(HIST("OmegaPos_in_MB"), centrality, casc.pt(), casc.mOmega()); } // Omega- - if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { + if (passedOmegaSelectionMB(casc, pos, neg, bach, collision) && bach.sign() < 0) { registryDataMB.fill(HIST("OmegaNeg_in_MB"), centrality, casc.pt(), casc.mOmega()); } } From 002d1d8400f224d0810879c63bc9512e06d29b02 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 20 May 2026 20:29:23 +0200 Subject: [PATCH 248/449] [PWGEM/Dilepton] update taggingHFE (#16326) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/DataModel/dileptonTables.h | 16 + PWGEM/Dilepton/TableProducer/CMakeLists.txt | 5 + .../skimmerPrimaryElectronSCT.cxx | 283 +++ PWGEM/Dilepton/Tasks/taggingHFE.cxx | 3 +- PWGEM/Dilepton/Utils/ElectronModule.h | 2240 +++++++++++++++++ PWGEM/Dilepton/Utils/MlResponsePID.h | 147 ++ PWGEM/Dilepton/Utils/MlResponseSCT.h | 264 ++ 7 files changed, 2957 insertions(+), 1 deletion(-) create mode 100644 PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx create mode 100644 PWGEM/Dilepton/Utils/ElectronModule.h create mode 100644 PWGEM/Dilepton/Utils/MlResponsePID.h create mode 100644 PWGEM/Dilepton/Utils/MlResponseSCT.h diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 9b47e2d4dd4..7bbce9eeef0 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -691,6 +691,15 @@ DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! DECLARE_SOA_COLUMN(ProbElBDT, probElBDT, float); //! +DECLARE_SOA_COLUMN(BDTScorePrompt, bdtScorePrompt, std::vector); //! +DECLARE_SOA_COLUMN(BDTScorePromptHc, bdtScorePromptHc, std::vector); //! +DECLARE_SOA_COLUMN(BDTScoreNonpromptHc, bdtScoreNonpromptHc, std::vector); //! +DECLARE_SOA_COLUMN(BDTScoreHb, bdtScoreHb, std::vector); //! +DECLARE_SOA_COLUMN(HadronType, hadronType, std::vector); //! 0:track, 1:K0S, 2:Lambda, 3:AntiLambda, 4:XiMinus, 5:XiPlus, 6:OmegaMinus, 7:OmegaPlus + +DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](std::vector p0, std::vector p1, std::vector p2, std::vector p3, std::vector type, int index) -> std::array { return std::array{p0[index], p1[index], p2[index], p3[index], static_cast(type[index])}; }); +DECLARE_SOA_DYNAMIC_COLUMN(NSV, nSV, [](std::vector type) -> size_t { return type.size(); }); + DECLARE_SOA_COLUMN(ITSNSigmaEl, itsNSigmaEl, float); //! DECLARE_SOA_COLUMN(ITSNSigmaMu, itsNSigmaMu, float); //! DECLARE_SOA_COLUMN(ITSNSigmaPi, itsNSigmaPi, float); //! @@ -1007,6 +1016,13 @@ DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBDERIVED // iterators using EMPrimaryElectronPrefilterBitDerived = EMPrimaryElectronsPrefilterBitDerived::iterator; +DECLARE_SOA_TABLE(EMPrimaryElectronsBDTSCT, "AOD", "ELBDTSCT", // To be joined with EMPrimaryElectrons table at analysis level. + emprimaryelectron::BDTScorePrompt, emprimaryelectron::BDTScorePromptHc, emprimaryelectron::BDTScoreNonpromptHc, emprimaryelectron::BDTScoreHb, emprimaryelectron::HadronType, + emprimaryelectron::NSV, + emprimaryelectron::ProbaSCT); +// iterators +using EMPrimaryElectronBDTSCT = EMPrimaryElectronsBDTSCT::iterator; + namespace emprimarymuon { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index 617d07a86d1..0070a556748 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -31,6 +31,11 @@ o2physics_add_dpl_workflow(skimmer-primary-electron PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-primary-electron-sct + SOURCES skimmerPrimaryElectronSCT.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(skimmer-primary-electron-qc SOURCES skimmerPrimaryElectronQC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx new file mode 100644 index 00000000000..1df2cf31f2a --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx @@ -0,0 +1,283 @@ +// 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 write relevant information about primary electrons. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/ElectronModule.h" +#include "PWGEM/Dilepton/Utils/MlResponseO2Track.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/TableHelper.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/MlResponse.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 // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// using namespace o2; +// using namespace o2::soa; +// using namespace o2::framework; +// using namespace o2::framework::expressions; +// using namespace o2::constants::physics; +// using namespace o2::common::core; + +struct skimmerPrimaryElectronSCT { + + using MyBCs = o2::soa::Join; + using MyCollisions = o2::soa::Join; + using MyCollisionsWithSWT = o2::soa::Join; + + using MyTracks = o2::soa::Join; + using MyTrack = MyTracks::iterator; + using MyTracksMC = o2::soa::Join; + using MyTrackMC = MyTracksMC::iterator; + + using MyV0s = o2::soa::Join; + using MyCascades = o2::soa::Join; + + struct : o2::framework::ConfigurableGroup { + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + o2::framework::Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + } ccdbConfig; + + o2::framework::Configurable doSCTwithTracks{"doSCTwithTracks", true, "flag to tag electrons with tracks"}; + o2::framework::Configurable doSCTwithV0s{"doSCTwithV0s", false, "flag to tag electrons with v0s"}; + o2::framework::Configurable doSCTwithCascades{"doSCTwithCascades", false, "flag to tag electrons with cascades"}; + + o2::framework::Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service mTOFResponse; + + o2::framework::SliceCache cache; + o2::framework::Preslice perCol_track = o2::aod::track::collisionId; + o2::framework::Preslice trackIndicesPerCollision = o2::aod::track_association::collisionId; + o2::framework::Preslice perCol_v0 = o2::aod::v0data::collisionId; + o2::framework::Preslice perCol_casc = o2::aod::cascdata::collisionId; + + void init(o2::framework::InitContext& initContext) + { + mRunNumber = 0; + d_bz = 0; + + LOGF(info, "initializing CCDB"); + ccdb->setURL(ccdbConfig.ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + // ccdbApi.init(ccdbConfig.ccdburl); + // mTOFResponse->initSetup(ccdb, initContext); + + LOGF(info, "initializing electronModule"); + electronModule.init(cfgEelectronCut, cfgEelectronPFCut, cfgHadronCut, cfgV0Cut, cfgCascadeCut, cfgDFeT, cfgDFeV0, cfgDFeC, initContext, ccdb, mTOFResponse, ccdbConfig.ccdburl.value); + // electronModule.setTOFResponse(mTOFResponse); + electronModule.addHistograms(mRegistry); + // electronModule.doPFB(doPF.value); + + electronModule.doSCTwithTracks(doSCTwithTracks.value); + electronModule.doSCTwithV0s(doSCTwithV0s.value); + electronModule.doSCTwithCascades(doSCTwithCascades.value); + } + + o2::pwgem::dilepton::utils::ElectronModule electronModule; + o2::pwgem::dilepton::utils::ElectronProducts products; + o2::pwgem::dilepton::utils::electronCut cfgEelectronCut; + o2::pwgem::dilepton::utils::electronPFCut cfgEelectronPFCut; + o2::pwgem::dilepton::utils::hadronCut cfgHadronCut; + o2::pwgem::dilepton::utils::v0Cut cfgV0Cut; + o2::pwgem::dilepton::utils::cascadeCut cfgCascadeCut; + o2::pwgem::dilepton::utils::cfgDFeT cfgDFeT; + o2::pwgem::dilepton::utils::cfgDFeV0 cfgDFeV0; + o2::pwgem::dilepton::utils::cfgDFeC cfgDFeC; + + o2::framework::HistogramRegistry mRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; + // ---------- for data ---------- + + int mRunNumber{0}; + float d_bz{0}; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::dataformats::VertexBase mVtx; + // const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // load matLUT for this timestamp + if (!lut) { + LOG(info) << "Loading material look-up table for timestamp: " << bc.timestamp(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->getForTimeStamp(ccdbConfig.lutPath, bc.timestamp())); + } else { + LOG(info) << "Material look-up table already in place. Not reloading."; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPMagField* grpmag = 0x0; + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(ccdbConfig.grpPath, run3grp_timestamp); + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + o2::base::Propagator::Instance()->setMatLUT(lut); + // mMeanVtx = ccdb->getForTimeStamp(ccdbConfig.mVtxPath, bc.timestamp()); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(ccdbConfig.grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfig.grpmagPath << " of object GRPMagField and " << ccdbConfig.grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + // mMeanVtx = ccdb->getForTimeStamp(ccdbConfig.mVtxPath, bc.timestamp()); + + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + + mRunNumber = bc.runNumber(); + } + + //! type of V0. 0: built solely for cascades (does not pass standard V0 cut), 1: standard 2, 3: photon-like with TPC-only use. Regular analysis should always use type 1. + o2::framework::expressions::Filter v0Filter = o2::aod::v0data::v0Type == uint8_t(1) && o2::aod::v0data::v0cosPA > cfgV0Cut.cfg_min_cospa&& o2::aod::v0data::dcaV0daughters cfgV0Cut.cfg_min_dcaxy&& nabs(o2::aod::v0data::dcanegtopv) > cfgV0Cut.cfg_min_dcaxy; + using filteredMyV0s = o2::soa::Filtered; + + o2::framework::expressions::Filter cascadeFilter = nabs(o2::aod::cascdata::dcanegtopv) > cfgCascadeCut.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcanegtopv) > cfgCascadeCut.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcabachtopv) > cfgCascadeCut.cfg_min_dcaxy_bachelor&& o2::aod::cascdata::dcacascdaughters < cfgCascadeCut.cfg_max_dcadau&& o2::aod::cascdata::dcaV0daughters < cfgCascadeCut.cfg_max_dcadau_v0; + using filteredMyCascades = o2::soa::Filtered; + + void processRec_SA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) + { + initCCDB(bcs.begin()); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, nullptr, products, mRegistry); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA, "process reconstructed info only", true); // standalone + + void processRec_TTCA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) + { + initCCDB(bcs.begin()); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA, "process reconstructed info only", false); // with TTCA + + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) + { + initCCDB(bcs.begin()); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, nullptr, products, mRegistry); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA_SWT, "process reconstructed info only", false); // standalone with swt + + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) + { + initCCDB(bcs.begin()); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA with swt + + // ---------- for MC ---------- + + void processMC_SA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + { + initCCDB(bcs.begin()); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, mcCollisions, mcParticles, products, mRegistry); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_SA, "process reconstructed and MC info ", false); // without TTCA in MC + + void processMC_TTCA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + { + initCCDB(bcs.begin()); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, mcCollisions, mcParticles, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + } + PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_TTCA, "process reconstructed info only", false); // with TTCA in MC +}; + +struct associateAmbiguousElectron { + o2::framework::Produces em_amb_ele_ids; + + o2::framework::SliceCache cache; + o2::framework::PresliceUnsorted perTrack = o2::aod::emprimaryelectron::trackId; + std::vector ambele_self_Ids; + + void process(o2::aod::EMPrimaryElectrons const& electrons) + { + for (const auto& electron : electrons) { + auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); + ambele_self_Ids.reserve(electrons_with_same_trackId.size()); + for (const auto& amb_ele : electrons_with_same_trackId) { + if (amb_ele.globalIndex() == electron.globalIndex()) { // don't store myself. + continue; + } + ambele_self_Ids.emplace_back(amb_ele.globalIndex()); + } + em_amb_ele_ids(ambele_self_Ids); + ambele_self_Ids.clear(); + ambele_self_Ids.shrink_to_fit(); + } + } +}; +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); + return o2::framework::WorkflowSpec{ + adaptAnalysisTask(cfgc, o2::framework::TaskName{"skimmer-primary-electron-sct"}), + adaptAnalysisTask(cfgc, o2::framework::TaskName{"associate-ambiguous-electron"})}; +} diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 893767d09ee..24d3d72165a 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -440,7 +441,7 @@ struct taggingHFE { fRegistry.add("Generated/D0/hsAcc", "pT-#eta acc.;p_{T,l} (GeV/c);p_{T,K} (GeV/c);#eta_{l};#eta_{K};", kTHnSparseF, {{100, 0, 10}, {100, 0, 10}, {100, -5, +5}, {100, -5, +5}}, false); fRegistry.add("Generated/Lc/hsAcc", "pT-#eta acc.;p_{T,l} (GeV/c);p_{T,#Lambda} (GeV/c);#eta_{l};#eta_{#Lambda};", kTHnSparseF, {{100, 0, 10}, {100, 0, 10}, {100, -5, +5}, {100, -5, +5}}, false); - fRegistry.add("Electron/hs", "hs;p_{T} (GeV/c);#eta;#varphi (rad.)", kTHnSparseF, {{100, 0, 10}, {40, -1, 1}, {36, 0, 2 * M_PI}}, false); + fRegistry.add("Electron/hs", "hs;p_{T} (GeV/c);#eta;#varphi (rad.)", kTHnSparseF, {{100, 0, 10}, {80, -2, 2}, {36, 0, 2 * M_PI}}, false); fRegistry.add("Electron/hDCA", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1, 1}, {200, -1, 1}}, false); fRegistry.add("Electron/hTPCdEdx", "TPC dE/dx vs. pin;p_{in} (GeV/c);TPC dE/dx", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Electron/hTOFbeta", "TOF #beta vs. p;p_{pv} (GeV/c);TOF #beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h new file mode 100644 index 00000000000..87f4de166dc --- /dev/null +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -0,0 +1,2240 @@ +// 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 write relevant information about primary electrons. +/// \author daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_UTILS_ELECTRONMODULE_H_ +#define PWGEM_DILEPTON_UTILS_ELECTRONMODULE_H_ + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MlResponsePID.h" +#include "PWGEM/Dilepton/Utils/MlResponseSCT.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/SemiCharmTag.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TableHelper.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/MlResponse.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 // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace o2 +{ +namespace pwgem::dilepton::utils +{ + +struct ElectronProducts : o2::framework::ProducesGroup { + o2::framework::Produces electronTable; + o2::framework::Produces electronCovTable; + o2::framework::Produces electronPFTable; + o2::framework::Produces sctTable; +}; + +struct electronCut : o2::framework::ConfigurableGroup { + std::string prefix = "electronCut"; + o2::framework::Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + o2::framework::Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + o2::framework::Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + o2::framework::Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + o2::framework::Configurable minchi2tpc{"minchi2tpc", 0.0, "min. chi2/NclsTPC"}; + o2::framework::Configurable minchi2its{"minchi2its", 0.0, "min. chi2/NclsITS"}; + o2::framework::Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + o2::framework::Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; + o2::framework::Configurable minpt{"minpt", 0.05, "min pt"}; + o2::framework::Configurable maxeta{"maxeta", 0.9, "max eta"}; + o2::framework::Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + o2::framework::Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; + o2::framework::Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; + o2::framework::Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.5, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.5, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; // set to -2 for lowB, -1e+10 for nominalB + o2::framework::Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 2.5, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable minTPCNsigmaKa{"minTPCNsigmaKa", -2.5, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 2.5, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable minTPCNsigmaPr{"minTPCNsigmaPr", -2.5, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable requireTOF{"requireTOF", false, "require TOF hit"}; + o2::framework::Configurable min_pin_for_pion_rejection{"min_pin_for_pion_rejection", 0.0, "pion rejection is applied above this pin"}; // this is used only in TOFreq + o2::framework::Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; + o2::framework::Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + o2::framework::Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; + o2::framework::Configurable minNelectron{"minNelectron", 0, "min number of electron candidates per collision"}; + o2::framework::Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks only for MC. switch ON only if needed."}; + o2::framework::Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", false, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; + + // configuration for PID ML + o2::framework::Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.95, 0.95, 0.7, 0.7, 0.8, 0.8, 0.7, 0.7}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"tpcInnerParam", "tpcNClsFound", "tpcChi2NCl", "tpcNSigmaEl", "tofNSigmaEl", "meanClusterSizeITSobCosTgl"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; +}; + +struct electronPFCut : o2::framework::ConfigurableGroup { + std::string prefix = "electronPFCut"; + o2::framework::Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + o2::framework::Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + o2::framework::Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + o2::framework::Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + o2::framework::Configurable minchi2tpc{"minchi2tpc", 0.0, "min. chi2/NclsTPC"}; + o2::framework::Configurable minchi2its{"minchi2its", 0.0, "min. chi2/NclsITS"}; + o2::framework::Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + o2::framework::Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + o2::framework::Configurable minpt{"minpt", 0.05, "min pt"}; + o2::framework::Configurable maxeta{"maxeta", 0.9, "max eta"}; + o2::framework::Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + o2::framework::Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; + o2::framework::Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; + o2::framework::Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 1e+10, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 0.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable minTPCNsigmaPi{"minTPCNsigmaPi", 0.0, "min. TPC n sigma for pion exclusion"}; // set to -2 for lowB, -1e+10 for nominalB + o2::framework::Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 0.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable minTPCNsigmaKa{"minTPCNsigmaKa", 0.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 0.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable minTPCNsigmaPr{"minTPCNsigmaPr", 0.0, "min. TPC n sigma for proton exclusion"}; + // o2::framework::Configurable requireTOF{"requireTOF", false, "require TOF hit"}; + o2::framework::Configurable min_pin_for_pion_rejection{"min_pin_for_pion_rejection", 0.0, "pion rejection is applied above this pin"}; // this is used only in TOFreq + o2::framework::Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; + o2::framework::Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + + // configuration for PID ML + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.65, 0.65, 0.75, 0.75, 0.65, 0.65}, "ML cuts per bin"}; + + // for pair + o2::framework::Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; + o2::framework::Configurable doPF{"doPF", false, "flag to set pion prefilter"}; +}; + +struct hadronCut : o2::framework::ConfigurableGroup { + std::string prefix = "hadronCut"; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.01, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; + o2::framework::Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.f, "min. TPC Ncr/Nf ratio"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 4, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 1, "min ncluster itsib"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3, "min n sigma pi in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3, "max n sigma pi in TPC"}; + o2::framework::Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; + o2::framework::Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3, "min n sigma ka in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; + o2::framework::Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; + o2::framework::Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + o2::framework::Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + o2::framework::Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + o2::framework::Configurable requirePiKaPr{"requirePiKaPr", true, "require hadron to be pion or kaon or proton"}; +}; + +struct v0Cut : o2::framework::ConfigurableGroup { + std::string prefix = "v0Cut"; + o2::framework::Configurable cfg_min_mass_k0s{"cfg_min_mass_k0s", 0.48, "min mass for K0S"}; + o2::framework::Configurable cfg_max_mass_k0s{"cfg_max_mass_k0s", 0.51, "max mass for K0S"}; + o2::framework::Configurable cfg_min_mass_k0s_veto{"cfg_min_mass_k0s_veto", 0.48, "min mass for K0S veto for Lambda"}; + o2::framework::Configurable cfg_max_mass_k0s_veto{"cfg_max_mass_k0s_veto", 0.51, "max mass for K0S veto for Lambda"}; + o2::framework::Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for Lambda"}; + o2::framework::Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for Lambda"}; + o2::framework::Configurable cfg_min_mass_lambda_veto{"cfg_min_mass_lambda_veto", 1.11, "min mass for Lambda veto for K0S"}; + o2::framework::Configurable cfg_max_mass_lambda_veto{"cfg_max_mass_lambda_veto", 1.12, "max mass for Lambda veto for K0S"}; + o2::framework::Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "min cospa for v0"}; + o2::framework::Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 0.1, "max distance between 2 legs for v0"}; + o2::framework::Configurable cfg_min_radius{"cfg_min_radius", 0.1, "min rxy for v"}; + o2::framework::Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.f, "min. TPC Ncr/Nf ratio"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 2, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; + o2::framework::Configurable cfg_min_dcaxy{"cfg_min_dcaxy", 0.1, "min dca XY for v0 legs in cm"}; + + o2::framework::Configurable cfg_max_alpha_veto{"cfg_max_alpha_veto", 0.95, "max alpha for photon conversion rejection"}; + o2::framework::Configurable cfg_max_qt_veto{"cfg_max_qt_veto", 0.01, "max qT for photon conversion rejection"}; + + // for both v0 and cascade + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3, "min n sigma pi in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3, "max n sigma pi in TPC"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3, "min n sigma ka in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + // o2::framework::Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; + // o2::framework::Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; + // o2::framework::Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; + // o2::framework::Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; + // o2::framework::Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + // o2::framework::Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + // o2::framework::Configurable applyTOFif{"applyTOFif", false, "apply TOFif for hadron identification"}; +}; + +struct cascadeCut : o2::framework::ConfigurableGroup { + std::string prefix = "cascadeCut"; + o2::framework::Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for lambda in cascade"}; + o2::framework::Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for lambda in cascade"}; + o2::framework::Configurable cfg_min_mass_Xi{"cfg_min_mass_Xi", 1.314, "min mass for Xi"}; + o2::framework::Configurable cfg_max_mass_Xi{"cfg_max_mass_Xi", 1.328, "max mass for Xi"}; + o2::framework::Configurable cfg_min_mass_Xi_veto{"cfg_min_mass_Xi_veto", 1.31, "min mass for Xi veto"}; + o2::framework::Configurable cfg_max_mass_Xi_veto{"cfg_max_mass_Xi_veto", 1.33, "max mass for Xi veto"}; + o2::framework::Configurable cfg_min_mass_Omega{"cfg_min_mass_Omega", 1.668, "min mass for Omega"}; + o2::framework::Configurable cfg_max_mass_Omega{"cfg_max_mass_Omega", 1.678, "max mass for Omega"}; + o2::framework::Configurable cfg_min_mass_Omega_veto{"cfg_min_mass_Omega_veto", 1.665, "min mass for Omega veto"}; + o2::framework::Configurable cfg_max_mass_Omega_veto{"cfg_max_mass_Omega_veto", 1.680, "max mass for Omega veto"}; + o2::framework::Configurable cfg_min_cospa_v0{"cfg_min_cospa_v0", 0.95, "minimum V0 CosPA in cascade"}; + o2::framework::Configurable cfg_max_dcadau_v0{"cfg_max_dcadau_v0", 0.1, "max distance between V0 Daughters in cascade"}; + o2::framework::Configurable cfg_min_cospa{"cfg_min_cospa", 0.95, "minimum cascade CosPA"}; + o2::framework::Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.1, "max distance between bachelor and V0"}; + o2::framework::Configurable cfg_min_rxy_v0{"cfg_min_rxy_v0", 0.1, "minimum V0 rxy in cascade"}; + o2::framework::Configurable cfg_min_rxy{"cfg_min_rxy", 0.1, "minimum V0 rxy in cascade"}; + o2::framework::Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; + o2::framework::Configurable cfg_min_dcaxy_bachelor{"cfg_min_dcaxy_bachelor", 0.05, "min dca XY for bachelor in cm"}; + o2::framework::Configurable cfg_min_dcaxy_v0{"cfg_min_dcaxy_v0", 0.0, "min dca XY for V0 in cm"}; +}; + +struct cfgDFeT : o2::framework::ConfigurableGroup { + std::string prefix = "cfgDFeT"; + o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + + // configuration for PID ML + o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; +}; + +struct cfgDFeV0 : o2::framework::ConfigurableGroup { + std::string prefix = "cfgDFeV0"; + o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + // configuration for PID ML + o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; +}; + +struct cfgDFeC : o2::framework::ConfigurableGroup { + std::string prefix = "cfgDFeC"; + o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + // configuration for PID ML + o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; +}; + +class ElectronModule +{ + public: + ElectronModule() + { + // constructor + } + ~ElectronModule() + { + // destructor + } + + struct looseElectron { + float pt{1e+10}; + float eta{1e+10}; + float phi{1e+10}; + }; + + template + void init(TElectronCut const& eCut, TElectronPFCut const& ePFCut, THadronCut const& hCut, TV0Cut const& v0Cut, TCascadeCut const& cascadeCut, TDFConfigET const& cfgET, TDFConfigEV0 const& cfgEV0, TDFConfigEC const& cfgEC, TInitContext& initContext, TCCDB& ccdb, TTOFResponse const& tofResponse, std::string const& ccdburl) + { + mRunNumber = 0; + d_bz = 0; + + ccdbApi.init(ccdburl); + + LOGF(info, "intializing configurations"); + fElectronCut = eCut; + fElectronPFCut = ePFCut; + fHadronCut = hCut; + fV0Cut = v0Cut; + fCascadeCut = cascadeCut; + fConfigDFeT = cfgET; + fConfigDFeV0 = cfgEV0; + fConfigDFeC = cfgEC; + + LOGF(info, "intializing TOFResponse"); + mTOFResponse = tofResponse; + // mTOFResponse->initSetup(&ccdb->instance(), initContext); + mTOFResponse->initSetup(ccdb, initContext); + + dfeT.setPropagateToPCA(true); + dfeT.setMaxR(200.f); + dfeT.setMinParamChange(1e-3); + dfeT.setMinRelChi2Change(0.9); + dfeT.setMaxDZIni(1e9); + dfeT.setMaxChi2(1e9); + dfeT.setUseAbsDCA(fConfigDFeT.useAbsDCA); + dfeT.setWeightedFinalPCA(fConfigDFeT.useWeightedFinalPCA); + dfeT.setMatCorrType(matCorr); + + dfeV0.setPropagateToPCA(true); + dfeV0.setMaxR(200.f); + dfeV0.setMinParamChange(1e-3); + dfeV0.setMinRelChi2Change(0.9); + dfeV0.setMaxDZIni(1e9); + dfeV0.setMaxChi2(1e9); + dfeV0.setUseAbsDCA(fConfigDFeV0.useAbsDCA); + dfeV0.setWeightedFinalPCA(fConfigDFeV0.useWeightedFinalPCA); + dfeV0.setMatCorrType(matCorr); + + dfeC.setPropagateToPCA(true); + dfeC.setMaxR(200.f); + dfeC.setMinParamChange(1e-3); + dfeC.setMinRelChi2Change(0.9); + dfeC.setMaxDZIni(1e9); + dfeC.setMaxChi2(1e9); + dfeC.setUseAbsDCA(fConfigDFeC.useAbsDCA); + dfeC.setWeightedFinalPCA(fConfigDFeC.useWeightedFinalPCA); + dfeC.setMatCorrType(matCorr); + } + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + d_bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Configuring for timestamp " << bc.timestamp() << " with magnetic field of " << d_bz << " kG"; + + // initialize MLResponse + if (fElectronCut.usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; + const uint32_t nBinsMl = fElectronCut.binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = fElectronCut.cutsMl.value[i]; + } + o2::framework::LabeledArray cutsMltmp = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponsePID.configure(fElectronCut.binsMl.value, cutsMltmp, cutDirMl, nClassesMl); + if (fElectronCut.loadModelsFromCCDB) { + mlResponsePID.setModelPathsCCDB(fElectronCut.onnxFileNames, ccdbApi, fElectronCut.onnxPathsCCDB, bc.timestamp()); + } else { + mlResponsePID.setModelPathsLocal(fElectronCut.onnxFileNames); + } + mlResponsePID.cacheInputFeaturesIndices(fElectronCut.namesInputFeatures); + mlResponsePID.cacheBinningIndex(fElectronCut.nameBinningFeature); + mlResponsePID.init(fElectronCut.enableOptimizations); + } // end of ML PID + + if (fConfigDFeT.useML) { + static constexpr int nClassesMl = 4; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + const uint32_t nBinsMl = fConfigDFeT.binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = 0.0; + cutsMlArr[i][2] = 0.0; + cutsMlArr[i][3] = 0.0; + } + o2::framework::LabeledArray cutsMltmp = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSCTeT.configure(fConfigDFeT.binsMl.value, cutsMltmp, cutDirMl, nClassesMl); + if (fConfigDFeT.loadModelsFromCCDB) { + mlResponseSCTeT.setModelPathsCCDB(fConfigDFeT.onnxFileNames, ccdbApi, fConfigDFeT.onnxPathsCCDB, bc.timestamp()); + } else { + mlResponseSCTeT.setModelPathsLocal(fConfigDFeT.onnxFileNames); + } + mlResponseSCTeT.cacheInputFeaturesIndices(fConfigDFeT.namesInputFeatures); + mlResponseSCTeT.cacheBinningIndex(fConfigDFeT.nameBinningFeature); + mlResponseSCTeT.init(fConfigDFeT.enableOptimizations); + } // end of ML SCTeT + + if (fConfigDFeV0.useML) { + static constexpr int nClassesMl = 4; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + const uint32_t nBinsMl = fConfigDFeV0.binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = 0.0; + cutsMlArr[i][2] = 0.0; + cutsMlArr[i][3] = 0.0; + } + o2::framework::LabeledArray cutsMltmp = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSCTeV0.configure(fConfigDFeV0.binsMl.value, cutsMltmp, cutDirMl, nClassesMl); + if (fConfigDFeV0.loadModelsFromCCDB) { + mlResponseSCTeV0.setModelPathsCCDB(fConfigDFeV0.onnxFileNames, ccdbApi, fConfigDFeV0.onnxPathsCCDB, bc.timestamp()); + } else { + mlResponseSCTeV0.setModelPathsLocal(fConfigDFeV0.onnxFileNames); + } + mlResponseSCTeV0.cacheInputFeaturesIndices(fConfigDFeV0.namesInputFeatures); + mlResponseSCTeV0.cacheBinningIndex(fConfigDFeV0.nameBinningFeature); + mlResponseSCTeV0.init(fConfigDFeV0.enableOptimizations); + } // end of ML SCTeV0 + + if (fConfigDFeC.useML) { + static constexpr int nClassesMl = 4; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + const uint32_t nBinsMl = fConfigDFeC.binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = 0.0; + cutsMlArr[i][2] = 0.0; + cutsMlArr[i][3] = 0.0; + } + o2::framework::LabeledArray cutsMltmp = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSCTeC.configure(fConfigDFeC.binsMl.value, cutsMltmp, cutDirMl, nClassesMl); + if (fConfigDFeC.loadModelsFromCCDB) { + mlResponseSCTeC.setModelPathsCCDB(fConfigDFeC.onnxFileNames, ccdbApi, fConfigDFeC.onnxPathsCCDB, bc.timestamp()); + } else { + mlResponseSCTeC.setModelPathsLocal(fConfigDFeC.onnxFileNames); + } + mlResponseSCTeC.cacheInputFeaturesIndices(fConfigDFeC.namesInputFeatures); + mlResponseSCTeC.cacheBinningIndex(fConfigDFeC.nameBinningFeature); + mlResponseSCTeC.init(fConfigDFeC.enableOptimizations); + } // end of ML SCTeC + + mRunNumber = bc.runNumber(); + mTOFResponse->processSetup(bc); + } + + template + void addHistograms(THistoregistry& registry) + { + registry.add("Track/hPt", "pT;p_{T} (GeV/c)", o2::framework::HistType::kTH1F, {{1000, 0.0f, 10}}, false); + registry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", o2::framework::HistType::kTH1F, {{4000, -20, 20}}, false); + registry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", o2::framework::HistType::kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); + registry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", o2::framework::HistType::kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + registry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", o2::framework::HistType::kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + registry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + registry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + registry.add("Track/hNclsTPC", "number of TPC clusters", o2::framework::HistType::kTH1F, {{161, -0.5, 160.5}}, false); + registry.add("Track/hNcrTPC", "number of TPC crossed rows", o2::framework::HistType::kTH1F, {{161, -0.5, 160.5}}, false); + registry.add("Track/hChi2TPC", "chi2/number of TPC clusters", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("Track/hChi2TOF", "chi2 of TOF", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", o2::framework::HistType::kTH1F, {{200, 0, 2}}, false); + registry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", o2::framework::HistType::kTH1F, {{200, 0, 2}}, false); + registry.add("Track/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + registry.add("Track/hNclsITS", "number of ITS clusters", o2::framework::HistType::kTH1F, {{8, -0.5, 7.5}}, false); + registry.add("Track/hChi2ITS", "chi2/number of ITS clusters", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("Track/hITSClusterMap", "ITS cluster map", o2::framework::HistType::kTH1F, {{128, -0.5, 127.5}}, false); + registry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + registry.add("Track/hTPCdEdxMC", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + registry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + registry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + registry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); #times cos(#lambda)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + registry.add("Track/hMeanClusterSizeITSib", "mean cluster size ITSib;p_{pv} (GeV/c); #times cos(#lambda)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + registry.add("Track/hMeanClusterSizeITSob", "mean cluster size ITSob;p_{pv} (GeV/c); #times cos(#lambda)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + registry.add("Track/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + registry.add("Track/hNe", "electron counts;N_{e} per collision", o2::framework::HistType::kTH1F, {{51, -0.5, 50.5}}, false); + + registry.add("Prefilter/Track/hPt", "pT;p_{T} (GeV/c)", o2::framework::HistType::kTH1F, {{1000, 0.0f, 10}}, false); + registry.add("Prefilter/Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", o2::framework::HistType::kTH2F, {{180, 0, 2 * M_PI}, {40, -2, 2}}, false); + registry.add("Prefilter/Track/hTPCdEdx", "TPC dE/dx vs. pin;p_{in} (GeV/c);TPC dE/dx", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + registry.add("Prefilter/Track/hTOFbeta", "TOF #beta vs. p;p_{pv} (GeV/c);TOF #beta", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); + registry.add("Prefilter/Pair/hMvsPhiV", "mass vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", o2::framework::HistType::kTH2F, {{90, 0.f, M_PI}, {100, 0, 0.1}}); + + // for charged hadron + registry.add("SCT/Track/hs", "hs;p_{T} (GeV/c);#eta;#varphi (rad.)", o2::framework::HistType::kTHnSparseF, {{100, 0, 10}, {80, -2, 2}, {36, 0, 2 * M_PI}}, false); + registry.add("SCT/Track/hDCA", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", o2::framework::HistType::kTH2F, {{200, -1, 1}, {200, -1, 1}}, false); + registry.add("SCT/Track/hTPCdEdx", "TPC dE/dx vs. pin;p_{in} (GeV/c);TPC dE/dx", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + registry.add("SCT/Track/hTOFbeta", "TOF #beta vs. p;p_{pv} (GeV/c);TOF #beta", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); + + // for V0 + registry.add("SCT/V0/hPt", "pT of V0;p_{T} (GeV/c)", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("SCT/V0/hYPhi_K0S", "rapidity vs. #varphi of V0;#varphi (rad.);rapidity_{K0S}", o2::framework::HistType::kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); + registry.add("SCT/V0/hYPhi_Lambda", "rapidity vs. #varphi of V0;#varphi (rad.);rapidity_{#Lambda}", o2::framework::HistType::kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); + registry.add("SCT/V0/hAP", "AP plot;#alpha;q_{T} (GeV/c)", o2::framework::HistType::kTH2F, {{200, -1, 1}, {250, 0, 0.25}}, false); + registry.add("SCT/V0/hLxy", "decay length from PV;L_{xy} (cm)", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("SCT/V0/hCosPA", "cosPA;cosine of pointing angle", o2::framework::HistType::kTH1F, {{100, 0.9, 1}}, false); + registry.add("SCT/V0/hDCA2Legs", "distance between 2 legs at PCA;distance between 2 legs (cm)", o2::framework::HistType::kTH1F, {{100, 0, 1}}, false); + registry.add("SCT/V0/hMassK0S", "K0S mass;m_{#pi#pi} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 0.45, 0.55}}, false); + registry.add("SCT/V0/hMassLambda", "Lambda mass;m_{p#pi^{#minus}} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.08, 1.18}}, false); + registry.add("SCT/V0/hMassAntiLambda", "Anti-Lambda mass;m_{#bar{p}#pi^{+}} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.08, 1.18}}, false); + registry.add("SCT/V0/hMassGamma_misid", "#gamma mass;m_{ee} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 0, 0.1}}, false); + registry.add("SCT/V0/hMassK0S_misid", "K0S mass;m_{#pi#pi} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 0.45, 0.55}}, false); + registry.add("SCT/V0/hMassLambda_misid", "Lambda mass;m_{p#pi^{#minus}} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.08, 1.18}}, false); + registry.add("SCT/V0/hMassAntiLambda_misid", "Anti-Lambda mass;m_{#bar{p}#pi^{+}} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.08, 1.18}}, false); + + // for cascadeSCT/ + registry.add("SCT/Cascade/hPt", "pT of cascade;p_{T} (GeV/c)", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.add("SCT/Cascade/hYPhi_Xi", "rapidity vs. #varphi of cascade;#varphi (rad.);rapidity_{#Xi}", o2::framework::HistType::kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); + registry.add("SCT/Cascade/hYPhi_Omega", "rapidity vs. #varphi of cascade;#varphi (rad.);rapidity_{#Omega}", o2::framework::HistType::kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); + registry.add("SCT/Cascade/hCosPA", "cosPA;cosine of pointing angle", o2::framework::HistType::kTH1F, {{100, 0.9, 1}}, false); + registry.add("SCT/Cascade/hDCA2Legs", "distance between 2 legs at PCA;distance between 2 legs (cm)", o2::framework::HistType::kTH1F, {{100, 0, 1}}, false); + registry.add("SCT/Cascade/hV0CosPA", "cosPA of V0 in cascade;cosine of pointing angle", o2::framework::HistType::kTH1F, {{100, 0.9, 1}}, false); + registry.add("SCT/Cascade/hV0DCA2Legs", "distance between 2 legs at PCA of V0 in cascade;distance between 2 legs (cm)", o2::framework::HistType::kTH1F, {{100, 0, 1}}, false); + registry.add("SCT/Cascade/hMassLambda", "Lambda mass;m_{p#pi^{-}} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.08, 1.18}}, false); + registry.add("SCT/Cascade/hMassXi", "#Xi mass;m_{#Lambda#pi} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.27, 1.37}}, false); + registry.add("SCT/Cascade/hMassOmega", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.62, 1.72}}, false); + registry.add("SCT/Cascade/hMassXi_misid", "#Xi mass;m_{#Lambda#pi} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.27, 1.37}}, false); + registry.add("SCT/Cascade/hMassOmega_misid", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 1.62, 1.72}}, false); + + registry.add("SCT/eT/hImpactParameter", "eH impact parameter;IP in XY (cm);IP in Z (cm);", o2::framework::HistType::kTH2F, {{200, -1, 1}, {200, -1, 1}}, false); + registry.add("SCT/eT/hDecayLength", "eH decay length;L_{xy} (cm);L_{z} (cm);", o2::framework::HistType::kTH2F, {{100, 0, 1}, {200, -1, 1}}, false); + registry.add("SCT/eT/hCosPA", "eH cosPA;cosine of pointing angle", o2::framework::HistType::kTH1F, {{200, -1, 1}}, false); + registry.add("SCT/eT/hDCA2legs", "dca between e and hadron;dca between 2legs (cm)", o2::framework::HistType::kTH1F, {{100, 0, 1}}, false); + registry.add("SCT/eT/hMass", "invariant mass of e-h;m_{eh} (GeV/c^{2})", o2::framework::HistType::kTH1F, {{100, 0, 10}}, false); + registry.addClone("SCT/eT/", "SCT/eV0/"); + registry.addClone("SCT/eT/", "SCT/eC/"); + } + + template + void calculateTOFNSigmaWithReassociation(TCollisions const& collisions, TBCs const&, TTracks const& tracks, TTrackAssoc const& trackIndices, TSliceCache const&, TPresliceTrack const& perColTrack, TPresliceTrackAssoc const& trackIndicesPerCollision) + { + if (fElectronCut.useTOFNSigmaDeltaBC) { + if constexpr (withTTCA) { + std::unordered_map mapCollisionTime; + std::unordered_map mapCollisionTimeError; + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + + for (const auto& collision : collisions) { + if (mapCollisionTime.find(collision.globalIndex()) == mapCollisionTime.end()) { + continue; + } + auto bcCollision = collision.template bc_as(); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + + if (track.hasTOF() && track.has_collision()) { // TTCA may use orphan tracks. + auto bcTrack = track.template collision_as().template bc_as(); + fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.length() / (track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()) - mapCollisionTime[collision.globalIndex()]) / (TMath::C() * 1e+2 * 1e-12); + ; + } else { + fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); + fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + } else { // without TTCA + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perColTrack, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); + fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + } else { + if constexpr (withTTCA) { + for (const auto& collision : collisions) { + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); + fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } // end of track loop + } // end of collision loop + } else { + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perColTrack, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPi(); + fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaKa(); + fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaPr(); + fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + } + } // end of track loop + } // end of collision loop + } + } + + template + void fillMapMLPID(TCollision const& collision, TTrack const& track) + { + if (fElectronCut.usePIDML) { + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + return; + } + + if (!isElectron_TOFif(track, collision, fElectronCut)) { // minimal n sigma cut is taken from the main electron cut. + return; + } + + o2::analysis::pwgem::dilepton::mlpid::candidate candidate; + candidate.tpcInnerParam = track.tpcInnerParam(); + candidate.tpcNClsFound = track.tpcNClsFound(); + candidate.tpcChi2NCl = track.tpcChi2NCl(); + candidate.tpcNSigmaEl = track.tpcNSigmaEl(); + candidate.tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + int total_cluster_size_ob = 0, nl_ob = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl_ob++; + } + total_cluster_size_ob += cluster_size_per_layer; + } + candidate.meanClusterSizeITSobCosTgl = static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(trackParCov.getTgl())); + + std::vector inputFeatures = mlResponsePID.getInputFeatures(candidate); + float binningFeature = mlResponsePID.getBinningFeature(candidate); + + int pbin = lower_bound(fElectronCut.binsMl.value.begin(), fElectronCut.binsMl.value.end(), binningFeature) - fElectronCut.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fElectronCut.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fElectronCut.binsMl.value.size()) - 2; + } + + float probaEl = mlResponsePID.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron + fMapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + } else { + fMapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = 1.0; + } + } + + template + bool checkTrack(TCollision const& collision, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + if (fElectronCut.storeOnlyTrueElectronMC) { + const auto& mcParticle = track.template mcParticle_as(); + if (std::abs(mcParticle.pdgCode()) != 11) { + return false; + } + } + } + + float tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (fElectronCut.requireTOF && !(track.hasTOF() && std::fabs(tofNSigmaEl) < fElectronCut.maxTOFNsigmaEl)) { + return false; + } + + if (!track.hasITS()) { + return false; + } + + if (track.itsChi2NCl() < fElectronCut.minchi2its || fElectronCut.maxchi2its < track.itsChi2NCl()) { + return false; + } + if (track.itsNCls() < fElectronCut.min_ncluster_its) { + return false; + } + if (track.itsNClsInnerBarrel() < fElectronCut.min_ncluster_itsib) { + return false; + } + + if (!fElectronCut.includeITSsa && (!track.hasITS() || !track.hasTPC())) { + return false; + } + + if (track.hasTPC()) { + if (track.tpcChi2NCl() < fElectronCut.minchi2tpc || fElectronCut.maxchi2tpc < track.tpcChi2NCl()) { + return false; + } + + if (track.tpcNClsFound() < fElectronCut.min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < fElectronCut.mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < fElectronCut.min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > fElectronCut.max_frac_shared_clusters_tpc) { + return false; + } + } + + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + return false; + } + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + + if (std::fabs(dcaXY) > fElectronCut.dca_xy_max || std::fabs(dcaZ) > fElectronCut.dca_z_max) { + return false; + } + + if (trackParCov.getPt() < fElectronCut.minpt || std::fabs(trackParCov.getEta()) > fElectronCut.maxeta) { + return false; + } + + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + + if (fElectronCut.maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))) { + return false; + } + + return true; + } + + template + bool checkTrackPF(TCollision const&, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.itsChi2NCl() < fElectronPFCut.minchi2its || fElectronPFCut.maxchi2its < track.itsChi2NCl()) { + return false; + } + if (track.itsNCls() < fElectronPFCut.min_ncluster_its) { + return false; + } + if (track.itsNClsInnerBarrel() < fElectronPFCut.min_ncluster_itsib) { + return false; + } + + if (track.tpcChi2NCl() < fElectronPFCut.minchi2tpc || fElectronPFCut.maxchi2tpc < track.tpcChi2NCl()) { + return false; + } + + if (track.tpcNClsFound() < fElectronPFCut.min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < fElectronPFCut.mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < fElectronPFCut.min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > fElectronPFCut.max_frac_shared_clusters_tpc) { + return false; + } + + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + return false; + } + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + + if (std::fabs(dcaXY) > fElectronPFCut.dca_xy_max || std::fabs(dcaZ) > fElectronPFCut.dca_z_max) { + return false; + } + + if (trackParCov.getPt() < fElectronPFCut.minpt || std::fabs(trackParCov.getEta()) > fElectronPFCut.maxeta) { + return false; + } + + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + + if (fElectronPFCut.maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))) { + return false; + } + + return true; + } + + template + bool isElectron(TCollision const& collision, TTrack const& track, TConfig const& eCut) + { + if (fElectronCut.usePIDML) { // keep fElectronCut here intentinoally + if (isElectron_TOFif(track, collision, eCut)) { + o2::analysis::pwgem::dilepton::mlpid::candidate candidate; + candidate.tpcInnerParam = track.tpcInnerParam(); + float binningFeature = mlResponsePID.getBinningFeature(candidate); + int pbin = lower_bound(eCut.binsMl.value.begin(), eCut.binsMl.value.end(), binningFeature) - eCut.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(eCut.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(eCut.binsMl.value.size()) - 2; + } + return fMapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] > eCut.cutsMl.value[pbin]; + } else { + return false; + } + } else { + return isElectron_TPChadrej(track, collision, eCut) || isElectron_TOFreq(track, collision, eCut); + } + } + + template + bool isElectron_TOFif(TTrack const& track, TCollision const& collision, TConfig const& eCut) + { + float tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + bool is_EL_TPC = eCut.minTPCNsigmaEl.value < track.tpcNSigmaEl() && track.tpcNSigmaEl() < eCut.maxTPCNsigmaEl.value; + bool is_EL_TOF = track.hasTOF() ? (std::fabs(tofNSigmaEl) < eCut.maxTOFNsigmaEl.value) : true; // TOFif + return is_EL_TPC && is_EL_TOF; + } + + template + bool isElectron_TPChadrej(TTrack const& track, TCollision const& collision, TConfig const& eCut) + { + float tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (track.tpcNSigmaEl() < eCut.minTPCNsigmaEl.value || eCut.maxTPCNsigmaEl.value < track.tpcNSigmaEl()) { + return false; + } + if (eCut.minTPCNsigmaPi.value < track.tpcNSigmaPi() && track.tpcNSigmaPi() < eCut.maxTPCNsigmaPi.value && track.tpcInnerParam() < eCut.max_pin_for_pion_rejection.value) { + return false; + } + if (eCut.minTPCNsigmaKa.value < track.tpcNSigmaKa() && track.tpcNSigmaKa() < eCut.maxTPCNsigmaKa.value) { + return false; + } + if (eCut.minTPCNsigmaPr.value < track.tpcNSigmaPr() && track.tpcNSigmaPr() < eCut.maxTPCNsigmaPr.value) { + return false; + } + if (track.hasTOF() && (eCut.maxTOFNsigmaEl.value < std::fabs(tofNSigmaEl))) { + return false; + } + return true; + } + + template + bool isElectron_TOFreq(TTrack const& track, TCollision const& collision, TConfig const& eCut) + { + float tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (eCut.minTPCNsigmaPi.value < track.tpcNSigmaPi() && track.tpcNSigmaPi() < eCut.maxTPCNsigmaPi.value && (eCut.min_pin_for_pion_rejection.value < track.tpcInnerParam() && track.tpcInnerParam() < eCut.max_pin_for_pion_rejection.value)) { + return false; + } + return eCut.minTPCNsigmaEl.value < track.tpcNSigmaEl() && track.tpcNSigmaEl() < eCut.maxTPCNsigmaEl.value && std::fabs(tofNSigmaEl) < eCut.maxTOFNsigmaEl.value; + } + + template + bool isSelectedHadron(TCollision const&, TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ) + { + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (trackParCov.getPt() < fHadronCut.cfg_min_pt_track || fHadronCut.cfg_max_pt_track < trackParCov.getPt()) { + return false; + } + + if (trackParCov.getEta() < fHadronCut.cfg_min_eta_track || fHadronCut.cfg_max_eta_track < trackParCov.getEta()) { + return false; + } + + if (std::fabs(dcaXY) > fHadronCut.cfg_max_dcaxy) { + return false; + } + + if (std::fabs(dcaZ) > fHadronCut.cfg_max_dcaz) { + return false; + } + + if (track.itsChi2NCl() < 0.f || fHadronCut.cfg_max_chi2its < track.itsChi2NCl()) { + return false; + } + + if (track.itsNCls() < fHadronCut.cfg_min_ncluster_its) { + return false; + } + + if (track.itsNClsInnerBarrel() < fHadronCut.cfg_min_ncluster_itsib) { + return false; + } + + if (track.tpcChi2NCl() < 0.f || fHadronCut.cfg_max_chi2tpc < track.tpcChi2NCl()) { + return false; + } + + if (track.tpcNClsFound() < fHadronCut.cfg_min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < fHadronCut.cfg_min_ncrossedrows_tpc) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < fHadronCut.cfg_min_cr2findable_ratio_tpc) { + return false; + } + + if (track.tpcFractionSharedCls() > fHadronCut.cfg_max_frac_shared_clusters_tpc) { + return false; + } + + if (fHadronCut.requirePiKaPr && !isPiKaPr(track)) { + return false; + } + + return true; + } + + template + void fillElectronTable(TCollision const& collision, TTrack const& track, TTrackParCov const& trackParCov, const float dcaXY, const float dcaZ, TProducts& products, THistoregistry& registry) + { + float pt = trackParCov.getPt(); + float eta = trackParCov.getEta(); + float phi = RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U); + + float tofNSigmaEl = fMapTOFNsigmaElReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float tofNSigmaPi = fMapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float tofNSigmaKa = fMapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float tofNSigmaPr = fMapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float beta = fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float probaEl = fMapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())]; + + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); + float mcTunedTPCSignal = 0.f; + if constexpr (isMC) { + mcTunedTPCSignal = track.mcTunedTPCSignal(); + } + + products.electronTable(collision.globalIndex(), track.globalIndex(), track.sign(), + pt, eta, phi, + dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusPID(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + beta, tofNSigmaEl, + track.itsClusterSizes(), + track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), + isAssociatedToMPC, false, probaEl, track.flags(), mcTunedTPCSignal); + + products.electronCovTable( + trackParCov.getX(), + trackParCov.getAlpha(), + trackParCov.getY(), + trackParCov.getZ(), + trackParCov.getSnp(), + // trackParCov.getTgl(), + // trackParCov.getSigmaY2(), + // trackParCov.getSigmaZY(), + // trackParCov.getSigmaZ2(), + trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), + trackParCov.getSigmaSnp2(), + trackParCov.getSigmaTglY(), + trackParCov.getSigmaTglZ(), + trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), + trackParCov.getSigma1PtY(), + trackParCov.getSigma1PtZ(), + trackParCov.getSigma1PtSnp(), + trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); + + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl++; + } + total_cluster_size += cluster_size_per_layer; + } + + int total_cluster_size_ib = 0, nl_ib = 0; + for (unsigned int layer = 0; layer < 3; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl_ib++; + } + total_cluster_size_ib += cluster_size_per_layer; + } + + int total_cluster_size_ob = 0, nl_ob = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl_ob++; + } + total_cluster_size_ob += cluster_size_per_layer; + } + + registry.fill(HIST("Track/hPt"), pt); + registry.fill(HIST("Track/hQoverPt"), track.sign() / pt); + registry.fill(HIST("Track/hEtaPhi"), phi, eta); + registry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + registry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); + registry.fill(HIST("Track/hDCAxyRes_Pt"), pt, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um + registry.fill(HIST("Track/hDCAzRes_Pt"), pt, std::sqrt(trackParCov.getSigmaZ2()) * 1e+4); // convert cm to um + registry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + registry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + registry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + registry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + registry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + registry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); + registry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + registry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + registry.fill(HIST("Track/hChi2TOF"), track.tofChi2()); + registry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + registry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + registry.fill(HIST("Track/hTPCdEdxMC"), track.tpcInnerParam(), mcTunedTPCSignal); + registry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + registry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + registry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + registry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); + registry.fill(HIST("Track/hTOFbeta"), trackParCov.getP(), beta); + registry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), tofNSigmaEl); + registry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), tofNSigmaPi); + registry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), tofNSigmaKa); + registry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), tofNSigmaPr); + registry.fill(HIST("Track/hMeanClusterSizeITS"), trackParCov.getP(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))); + registry.fill(HIST("Track/hMeanClusterSizeITSib"), trackParCov.getP(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(trackParCov.getTgl()))); + registry.fill(HIST("Track/hMeanClusterSizeITSob"), trackParCov.getP(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(trackParCov.getTgl()))); + registry.fill(HIST("Track/hProbElBDT"), track.tpcInnerParam(), probaEl); + } + + template + bool isPiKaPr(TTrack const& track) + { + bool is_pi_included_TPC = fHadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < fHadronCut.cfg_max_TPCNsigmaPi; + bool is_ka_included_TPC = fHadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < fHadronCut.cfg_max_TPCNsigmaKa; + bool is_pr_included_TPC = fHadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < fHadronCut.cfg_max_TPCNsigmaPr; + return is_pi_included_TPC || is_ka_included_TPC || is_pr_included_TPC; + } + + template + bool isSelectedV0Leg(TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.itsChi2NCl() > fV0Cut.cfg_max_chi2its) { + return false; + } + + if (track.itsNCls() < fV0Cut.cfg_min_ncluster_its) { + return false; + } + + if (track.itsNClsInnerBarrel() < fV0Cut.cfg_min_ncluster_itsib) { + return false; + } + + if (track.tpcChi2NCl() > fV0Cut.cfg_max_chi2tpc) { + return false; + } + + if (track.tpcNClsFound() < fV0Cut.cfg_min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < fV0Cut.cfg_min_ncrossedrows_tpc) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < fV0Cut.cfg_min_cr2findable_ratio_tpc) { + return false; + } + + if (track.tpcFractionSharedCls() > fV0Cut.cfg_max_frac_shared_clusters_tpc) { + return false; + } + + return true; + } + + template + bool isPion(TTrack const& track) + { + return fV0Cut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < fV0Cut.cfg_max_TPCNsigmaPi; + } + + template + bool isKaon(TTrack const& track) + { + return fV0Cut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < fV0Cut.cfg_max_TPCNsigmaKa; + } + + template + bool isProton(TTrack const& track) + { + return fV0Cut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < fV0Cut.cfg_max_TPCNsigmaPr; + } + + template + bool isK0S(TV0 const& v0) + { + return (fV0Cut.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < fV0Cut.cfg_max_mass_k0s) && (v0.mLambda() < fV0Cut.cfg_min_mass_lambda_veto || fV0Cut.cfg_max_mass_lambda_veto < v0.mLambda()) && (v0.mAntiLambda() < fV0Cut.cfg_min_mass_lambda_veto || fV0Cut.cfg_max_mass_lambda_veto < v0.mAntiLambda()); + } + + template + bool isLambda(TV0 const& v0) + { + return (fV0Cut.cfg_min_mass_lambda < v0.mLambda() && v0.mLambda() < fV0Cut.cfg_max_mass_lambda) && (v0.mK0Short() < fV0Cut.cfg_min_mass_k0s_veto || fV0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()); + } + + template + bool isAntiLambda(TV0 const& v0) + { + return (fV0Cut.cfg_min_mass_lambda < v0.mAntiLambda() && v0.mAntiLambda() < fV0Cut.cfg_max_mass_lambda) && (v0.mK0Short() < fV0Cut.cfg_min_mass_k0s_veto || fV0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()); + } + + template + bool isXi(TCascade const& cascade) + { + return (fCascadeCut.cfg_min_mass_Xi < cascade.mXi() && cascade.mXi() < fCascadeCut.cfg_max_mass_Xi) && (cascade.mOmega() < fCascadeCut.cfg_min_mass_Omega_veto || fCascadeCut.cfg_max_mass_Omega_veto < cascade.mOmega()); + } + + template + bool isOmega(TCascade const& cascade) + { + return (fCascadeCut.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < fCascadeCut.cfg_max_mass_Omega) && (cascade.mXi() < fCascadeCut.cfg_min_mass_Xi_veto || fCascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()); + } + + template + void fillV0Histograms(TCollision const&, TV0 const& v0, THistoregistry& registry) + { + auto pos = v0.template posTrack_as(); + auto neg = v0.template negTrack_as(); + registry.fill(HIST("SCT/V0/hPt"), v0.pt()); + registry.fill(HIST("SCT/V0/hAP"), v0.alpha(), v0.qtarm()); + registry.fill(HIST("SCT/V0/hCosPA"), v0.v0cosPA()); + registry.fill(HIST("SCT/V0/hLxy"), v0.v0radius()); + registry.fill(HIST("SCT/V0/hDCA2Legs"), v0.dcaV0daughters()); + + if (isPion(pos) && isPion(neg)) { + if ((v0.mLambda() < fV0Cut.cfg_min_mass_lambda_veto || fV0Cut.cfg_max_mass_lambda_veto < v0.mLambda()) && (v0.mAntiLambda() < fV0Cut.cfg_min_mass_lambda_veto || fV0Cut.cfg_max_mass_lambda_veto < v0.mAntiLambda())) { + registry.fill(HIST("SCT/V0/hMassK0S"), v0.mK0Short()); + registry.fill(HIST("SCT/V0/hYPhi_K0S"), v0.phi(), v0.yK0Short()); + } + registry.fill(HIST("SCT/V0/hMassGamma_misid"), v0.mGamma()); + registry.fill(HIST("SCT/V0/hMassLambda_misid"), v0.mLambda()); + registry.fill(HIST("SCT/V0/hMassAntiLambda_misid"), v0.mAntiLambda()); + } + + if (isProton(pos) && isPion(neg)) { + if (v0.mK0Short() < fV0Cut.cfg_min_mass_k0s_veto || fV0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()) { + registry.fill(HIST("SCT/V0/hMassLambda"), v0.mLambda()); + registry.fill(HIST("SCT/V0/hYPhi_Lambda"), v0.phi(), v0.yLambda()); + } + registry.fill(HIST("SCT/V0/hMassGamma_misid"), v0.mGamma()); + registry.fill(HIST("SCT/V0/hMassK0S_misid"), v0.mK0Short()); + } + + if (isProton(neg) && isPion(pos)) { + if (v0.mK0Short() < fV0Cut.cfg_min_mass_k0s_veto || fV0Cut.cfg_max_mass_k0s_veto < v0.mK0Short()) { + registry.fill(HIST("SCT/V0/hMassAntiLambda"), v0.mAntiLambda()); + registry.fill(HIST("SCT/V0/hYPhi_Lambda"), v0.phi(), v0.yLambda()); + } + registry.fill(HIST("SCT/V0/hMassGamma_misid"), v0.mGamma()); + registry.fill(HIST("SCT/V0/hMassK0S_misid"), v0.mK0Short()); + } + } + + template + void fillCascadeHistograms(TCollision const& collision, TCascade const& cascade, THistoregistry& registry) + { + auto pos = cascade.template posTrack_as(); + auto neg = cascade.template negTrack_as(); + auto bachelor = cascade.template bachelor_as(); + + registry.fill(HIST("SCT/Cascade/hPt"), cascade.pt()); + registry.fill(HIST("SCT/Cascade/hMassLambda"), cascade.mLambda()); + registry.fill(HIST("SCT/Cascade/hCosPA"), cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("SCT/Cascade/hDCA2Legs"), cascade.dcacascdaughters()); + registry.fill(HIST("SCT/Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("SCT/Cascade/hV0DCA2Legs"), cascade.dcaV0daughters()); + + if (cascade.sign() < 0) { // Xi- or Omega- + if (isPion(bachelor) && isProton(pos) && isPion(neg)) { + if (cascade.mOmega() < fCascadeCut.cfg_min_mass_Omega_veto || fCascadeCut.cfg_max_mass_Omega_veto < cascade.mOmega()) { + registry.fill(HIST("SCT/Cascade/hMassXi"), cascade.mXi()); + registry.fill(HIST("SCT/Cascade/hYPhi_Xi"), cascade.phi(), cascade.yXi()); + } + registry.fill(HIST("SCT/Cascade/hMassOmega_misid"), cascade.mOmega()); + } + if (isKaon(bachelor) && isProton(pos) && isPion(neg)) { + if (cascade.mXi() < fCascadeCut.cfg_min_mass_Xi_veto || fCascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()) { + registry.fill(HIST("SCT/Cascade/hMassOmega"), cascade.mOmega()); + registry.fill(HIST("SCT/Cascade/hYPhi_Omega"), cascade.phi(), cascade.yOmega()); + } + registry.fill(HIST("SCT/Cascade/hMassXi_misid"), cascade.mXi()); + } + } else { // Xi+ or Omega+ + if (isPion(bachelor) && isProton(neg) && isPion(pos)) { + if (cascade.mOmega() < fCascadeCut.cfg_min_mass_Omega_veto || fCascadeCut.cfg_max_mass_Omega_veto < cascade.mOmega()) { + registry.fill(HIST("SCT/Cascade/hMassXi"), cascade.mXi()); + registry.fill(HIST("SCT/Cascade/hYPhi_Xi"), cascade.phi(), cascade.yXi()); + } + registry.fill(HIST("SCT/Cascade/hMassOmega_misid"), cascade.mOmega()); + } + if (isKaon(bachelor) && isProton(neg) && isPion(pos)) { + if (cascade.mXi() < fCascadeCut.cfg_min_mass_Xi_veto || fCascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()) { + registry.fill(HIST("SCT/Cascade/hMassOmega"), cascade.mOmega()); + registry.fill(HIST("SCT/Cascade/hYPhi_Omega"), cascade.phi(), cascade.yOmega()); + } + registry.fill(HIST("SCT/Cascade/hMassXi_misid"), cascade.mXi()); + } + } + } + + template + void processWithTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const& tracks, TV0s const& v0s, TCascades const& cascades, TTrackAssoc const& trackIndices, TMCCollisions const&, TMCParticles const&, TProducts& products, THistoregistry& registry, TSliceCache& cache, TPresliceTrack const& perColTrack, TPresliceTrackAssoc const& trackIndicesPerCollision, TPresliceV0 const& perColV0, TPresliceCascade const& perColCasc) + { + initCCDB(bcs.begin()); + + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices, cache, perColTrack, trackIndicesPerCollision); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if constexpr (isMC) { + if (!collision.has_mcCollision()) { + continue; + } + } + + if (!collision.isSelected()) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } + } + + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + std::unordered_multimap multiMapTracksPerCollision; // collisionId -> trackIds + + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + + std::vector looseElectronIds; // for pion prefilter + if (fElectronPFCut.doPF) { + looseElectronIds.reserve(trackIdsThisCollision.size()); + } + + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) && !checkTrackPF(collision, track)) { + continue; + } + + fillMapMLPID(collision, track); // call this function for all track also for loose electron sample. + + if (checkTrack(collision, track) && isElectron(collision, track, fElectronCut)) { + multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); + } + + if (fElectronPFCut.doPF && checkTrackPF(collision, track) && isElectron(collision, track, fElectronPFCut)) { + looseElectronIds.emplace_back(track.globalIndex()); + } + } // end of track loop + + int count_electrons = multiMapTracksPerCollision.count(collision.globalIndex()); + registry.fill(HIST("Track/hNe"), count_electrons); + if (count_electrons < fElectronCut.minNelectron) { + continue; + } + + std::vector hadronIds; + std::vector k0sIds; + std::vector lambdaIds; + std::vector antilambdaIds; + std::vector xiMinusIds; + std::vector xiPlusIds; + std::vector omegaMinusIds; + std::vector omegaPlusIds; + + if (fDoSCTwithTracks) { + hadronIds.reserve(trackIdsThisCollision.size()); + } + + if (fDoSCTwithV0s) { + auto v0s_per_collision = v0s.sliceBy(perColV0, collision.globalIndex()); + k0sIds.reserve(v0s_per_collision.size()); + lambdaIds.reserve(v0s_per_collision.size()); + antilambdaIds.reserve(v0s_per_collision.size()); + + for (const auto& v0 : v0s_per_collision) { + auto pos = v0.template posTrack_as(); + auto neg = v0.template negTrack_as(); + + if (pos.sign() * neg.sign() > 0) { + continue; + } + if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { + continue; + } + + if (v0.dcaV0daughters() > fV0Cut.cfg_max_dca2legs) { + continue; + } + + if (v0.v0radius() < fV0Cut.cfg_min_radius) { + continue; + } + + if (v0.v0cosPA() < fV0Cut.cfg_min_cospa) { + continue; + } + + if (std::sqrt(std::pow(v0.alpha() / fV0Cut.cfg_max_alpha_veto, 2) + std::pow(v0.qtarm() / fV0Cut.cfg_max_qt_veto, 2)) < 1.f) { // photon conversion rejection at small qT + continue; + } + + fillV0Histograms(collision, v0, registry); + + if (isK0S(v0) && isPion(pos) && isPion(neg)) { + k0sIds.emplace_back(v0.globalIndex()); + } + + if (isLambda(v0) && isProton(pos) && isPion(neg)) { + lambdaIds.emplace_back(v0.globalIndex()); + } else if (isAntiLambda(v0) && isProton(neg) && isPion(pos)) { + antilambdaIds.emplace_back(v0.globalIndex()); + } + + } // end of v0 loop + } + + if (fDoSCTwithCascades) { + auto cascades_per_collision = cascades.sliceBy(perColCasc, collision.globalIndex()); + xiMinusIds.reserve(cascades_per_collision.size()); + xiPlusIds.reserve(cascades_per_collision.size()); + omegaMinusIds.reserve(cascades_per_collision.size()); + omegaPlusIds.reserve(cascades_per_collision.size()); + + for (const auto& cascade : cascades_per_collision) { + auto pos = cascade.template posTrack_as(); + auto neg = cascade.template negTrack_as(); + auto bachelor = cascade.template bachelor_as(); + if (pos.sign() * neg.sign() > 0) { + continue; + } + if (cascade.mLambda() < fCascadeCut.cfg_min_mass_lambda || fCascadeCut.cfg_max_mass_lambda < cascade.mLambda()) { + continue; + } + + if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg) || !isSelectedV0Leg(bachelor)) { + continue; + } + + if (cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < fCascadeCut.cfg_min_cospa) { + continue; + } + if (cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < fCascadeCut.cfg_min_cospa_v0) { + continue; + } + + if (cascade.cascradius() > cascade.v0radius()) { + continue; + } + + if (cascade.dcaV0daughters() > fCascadeCut.cfg_max_dcadau_v0) { + continue; + } + if (cascade.v0radius() < fCascadeCut.cfg_min_rxy_v0) { + continue; + } + if (cascade.cascradius() < fCascadeCut.cfg_min_rxy) { + continue; + } + + if (cascade.dcacascdaughters() > fCascadeCut.cfg_max_dcadau) { + continue; + } + + if (std::fabs(cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < fCascadeCut.cfg_min_dcaxy_v0) { + continue; + } + + fillCascadeHistograms(collision, cascade, registry); + + if (cascade.sign() < 0) { // Xi- or Omega- + if (isXi(cascade) && isPion(bachelor) && isProton(pos) && isPion(neg)) { + xiMinusIds.emplace_back(cascade.globalIndex()); + } + if (isOmega(cascade) && isKaon(bachelor) && isProton(pos) && isPion(neg)) { + omegaMinusIds.emplace_back(cascade.globalIndex()); + } + } else { // Xi+ or Omega+ + if (isXi(cascade) && isPion(bachelor) && isProton(neg) && isPion(pos)) { + xiPlusIds.emplace_back(cascade.globalIndex()); + } + if (isOmega(cascade) && isKaon(bachelor) && isProton(neg) && isPion(pos)) { + omegaPlusIds.emplace_back(cascade.globalIndex()); + } + } + } // end of cascade loop + } + + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + auto trackParCov = getTrackParCov(track); + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + trackParCov.setPID(track.pidForTracking()); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + continue; + } + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + if (isSelectedHadron(collision, track, trackParCov, dcaXY, dcaZ)) { + float tpcSignal = track.tpcSignal(); + if constexpr (isMC) { + tpcSignal = track.mcTunedTPCSignal(); + } + registry.fill(HIST("SCT/Track/hs"), trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U)); + registry.fill(HIST("SCT/Track/hDCA"), dcaXY, dcaZ); + registry.fill(HIST("SCT/Track/hTPCdEdx"), track.tpcInnerParam(), tpcSignal); + registry.fill(HIST("SCT/Track/hTOFbeta"), trackParCov.getP(), fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + hadronIds.emplace_back(track.globalIndex()); + } + } // end of track loop + + auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); + for (auto it = range_electrons.first; it != range_electrons.second; it++) { + auto electron = tracks.rawIteratorAt(it->second); + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(electron); + trackParCov.setPID(o2::track::PID::Electron); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + continue; + } + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + fillElectronTable(collision, electron, trackParCov, dcaXY, dcaZ, products, registry); + ROOT::Math::PtEtaPhiMVector v1(trackParCov.getPt(), trackParCov.getEta(), RecoDecay::constrainAngle(trackParCov.getPhi(), 0, 1U), o2::constants::physics::MassElectron); // main electron + + // apply pion prefilter + uint8_t pfb = 0; + for (const auto& looseElectronId : looseElectronIds) { + auto looseElectron = tracks.rawIteratorAt(looseElectronId); + if (looseElectron.globalIndex() == electron.globalIndex()) { + continue; + } + if (looseElectron.sign() * electron.sign() > 0) { // reject LS, because pi0dalitz and photon conversion must be ULS. + continue; + } + + auto trackParCov2 = getTrackParCov(looseElectron); + trackParCov2.setPID(o2::track::PID::Electron); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov2, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + continue; + } + + float tpcSignal = looseElectron.tpcSignal(); + if constexpr (isMC) { + tpcSignal = looseElectron.mcTunedTPCSignal(); + } + registry.fill(HIST("Prefilter/Track/hPt"), trackParCov2.getPt()); + registry.fill(HIST("Prefilter/Track/hEtaPhi"), RecoDecay::constrainAngle(trackParCov2.getPhi(), 0, 1U), trackParCov2.getEta()); + registry.fill(HIST("Prefilter/Track/hTPCdEdx"), looseElectron.tpcInnerParam(), tpcSignal); + registry.fill(HIST("Prefilter/Track/hTOFbeta"), trackParCov2.getP(), fMapTOFBetaReassociated[std::make_pair(collision.globalIndex(), looseElectron.globalIndex())]); + + ROOT::Math::PtEtaPhiMVector v2(trackParCov2.getPt(), trackParCov2.getEta(), RecoDecay::constrainAngle(trackParCov2.getPhi(), 0, 1U), o2::constants::physics::MassElectron); // loose electron + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(v1.Px(), v1.Py(), v1.Pz(), v2.Px(), v2.Py(), v2.Pz(), electron.sign(), looseElectron.sign(), d_bz); + registry.fill(HIST("Prefilter/Pair/hMvsPhiV"), phiv, v12.M()); + + if (v12.M() < fElectronPFCut.slope * phiv + fElectronPFCut.intercept) { + pfb |= (uint8_t(1) << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC)); + } + + for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { + if (v12.M() < max_mee_vec.at(i)) { + pfb |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); + } + } // end of mee loop + + } // end of loose electron loop + products.electronPFTable(pfb); + + // perform SCT from here + std::vector bdtScorePrompt; + std::vector bdtScorePromptHc; + std::vector bdtScoreNonpromptHc; + std::vector bdtScoreHb; + std::vector hadronType; + + bdtScorePrompt.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + bdtScorePromptHc.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + bdtScoreNonpromptHc.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + bdtScoreHb.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + hadronType.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + + // eTrack pair + for (const auto& hadronId : hadronIds) { + auto hadron = tracks.rawIteratorAt(hadronId); + if (hadron.globalIndex() == electron.globalIndex()) { + continue; + } + + auto hadronParCov = getTrackParCov(hadron); + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + hadronParCov.setPID(hadron.pidForTracking()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, hadronParCov, 2.f, matCorr, &mDcaInfoCov); + + auto eTpair = o2::aod::pwgem::dilepton::utils::makePairLeptonTrack(dfeT, collision, electron, hadron, o2::track::PID::Electron, hadron.pidForTracking()); + registry.fill(HIST("SCT/eT/hImpactParameter"), eTpair.impParXY, eTpair.impParZ); + registry.fill(HIST("SCT/eT/hDecayLength"), eTpair.lxy, eTpair.lz); + registry.fill(HIST("SCT/eT/hCosPA"), eTpair.cospa); + registry.fill(HIST("SCT/eT/hDCA2legs"), eTpair.dca2legs); + registry.fill(HIST("SCT/eT/hMass"), eTpair.mass); + if (eTpair.isOK && fConfigDFeT.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eTpair, trackParCov, mDcaInfoCov); + candidate.ptL = trackParCov.getPt(); + candidate.signLH = electron.sign() * hadron.sign(); + candidate.signedMassLH = electron.sign() * hadron.sign() * eTpair.mass; + candidate.tpcNSigmaKa = hadron.tpcNSigmaKa(); + + std::vector inputFeatures = mlResponseSCTeT.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeT.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeT.binsMl.value.begin(), fConfigDFeT.binsMl.value.end(), binningFeature) - fConfigDFeT.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeT.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeT.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[3]; + + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(0); + } + } // end of charged track loop + + // eK0S pair + for (const auto& k0sId : k0sIds) { + auto v0 = v0s.rawIteratorAt(k0sId); + if (v0.posTrackId() == electron.globalIndex() || v0.negTrackId() == electron.globalIndex()) { + continue; + } + const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; + const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; + std::array covV0 = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV0[MomInd[i]] = v0.momentumCovMat()[i]; + covV0[i] = v0.positionCovMat()[i]; + } + auto v0ParCov = o2::track::TrackParCov(vertexV0, momV0, covV0, 0, true); + v0ParCov.setAbsCharge(0); + v0ParCov.setPID(o2::track::PID::K0); + o2::dataformats::DCA impactParameterV0; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, v0ParCov, 2.f, matCorr, &impactParameterV0); // v0ParCov is TrackParCov object + + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(dfeV0, collision, electron, v0, o2::track::PID::Electron, o2::track::PID::K0); + registry.fill(HIST("SCT/eV0/hImpactParameter"), eV0pair.impParXY, eV0pair.impParZ); + registry.fill(HIST("SCT/eV0/hDecayLength"), eV0pair.lxy, eV0pair.lz); + registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); + registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); + registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); + if (eV0pair.isOK && fConfigDFeV0.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeV0.binsMl.value.begin(), fConfigDFeV0.binsMl.value.end(), binningFeature) - fConfigDFeV0.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeV0.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(1); + } + } // end of k0s loop + + if (electron.sign() > 0) { // positron + // eL pair // sign is restricted in baryon decay: Lc+ -> e+ nu_e Lambda + for (const auto& lambdaId : lambdaIds) { + auto v0 = v0s.rawIteratorAt(lambdaId); + if (v0.posTrackId() == electron.globalIndex() || v0.negTrackId() == electron.globalIndex()) { + continue; + } + const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; + const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; + std::array covV0 = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV0[MomInd[i]] = v0.momentumCovMat()[i]; + covV0[i] = v0.positionCovMat()[i]; + } + auto v0ParCov = o2::track::TrackParCov(vertexV0, momV0, covV0, 0, true); + v0ParCov.setAbsCharge(0); + v0ParCov.setPID(o2::track::PID::Lambda); + o2::dataformats::DCA impactParameterV0; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, v0ParCov, 2.f, matCorr, &impactParameterV0); // v0ParCov is TrackParCov object + + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(dfeV0, collision, electron, v0, o2::track::PID::Electron, o2::track::PID::Lambda); + registry.fill(HIST("SCT/eV0/hImpactParameter"), eV0pair.impParXY, eV0pair.impParZ); + registry.fill(HIST("SCT/eV0/hDecayLength"), eV0pair.lxy, eV0pair.lz); + registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); + registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); + registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); + if (eV0pair.isOK && fConfigDFeV0.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeV0.binsMl.value.begin(), fConfigDFeV0.binsMl.value.end(), binningFeature) - fConfigDFeV0.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeV0.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(2); + } + } // end of lambda loop + + // eXi pair // sign is restricted in baryon decay: Xic0 -> e+ nu_e Xi- + for (const auto& xiId : xiMinusIds) { + auto cascade = cascades.rawIteratorAt(xiId); + if (cascade.posTrackId() == electron.globalIndex() || cascade.negTrackId() == electron.globalIndex() || cascade.bachelorId() == electron.globalIndex()) { + continue; + } + + const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; + const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; + std::array covCasc = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covCasc[MomInd[i]] = cascade.momentumCovMat()[i]; + covCasc[i] = cascade.positionCovMat()[i]; + } + auto cascadeParCov = o2::track::TrackParCov(vertexCasc, momCasc, covCasc, cascade.sign(), true); + cascadeParCov.setAbsCharge(1); + cascadeParCov.setPID(o2::track::PID::XiMinus); + o2::dataformats::DCA impactParameterCasc; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, cascadeParCov, 2.f, matCorr, &impactParameterCasc); // cascadeParCov is TrackParCov object + + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(dfeC, collision, electron, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); + registry.fill(HIST("SCT/eC/hImpactParameter"), eCpair.impParXY, eCpair.impParZ); + registry.fill(HIST("SCT/eC/hDecayLength"), eCpair.lxy, eCpair.lz); + registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); + registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); + registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); + if (eCpair.isOK && fConfigDFeC.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeC.binsMl.value.begin(), fConfigDFeC.binsMl.value.end(), binningFeature) - fConfigDFeC.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeC.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(4); + } + } // end of Xi- loop + + // eOmega pair // sign is restricted in baryon decay: Omegac0 -> e+ nu_e Omega- + for (const auto& omegaId : omegaMinusIds) { + auto cascade = cascades.rawIteratorAt(omegaId); + if (cascade.posTrackId() == electron.globalIndex() || cascade.negTrackId() == electron.globalIndex() || cascade.bachelorId() == electron.globalIndex()) { + continue; + } + + const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; + const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; + std::array covCasc = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covCasc[MomInd[i]] = cascade.momentumCovMat()[i]; + covCasc[i] = cascade.positionCovMat()[i]; + } + auto cascadeParCov = o2::track::TrackParCov(vertexCasc, momCasc, covCasc, cascade.sign(), true); + cascadeParCov.setAbsCharge(1); + cascadeParCov.setPID(o2::track::PID::OmegaMinus); + o2::dataformats::DCA impactParameterCasc; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, cascadeParCov, 2.f, matCorr, &impactParameterCasc); // cascadeParCov is TrackParCov object + + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(dfeC, collision, electron, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); + registry.fill(HIST("SCT/eC/hImpactParameter"), eCpair.impParXY, eCpair.impParZ); + registry.fill(HIST("SCT/eC/hDecayLength"), eCpair.lxy, eCpair.lz); + registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); + registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); + registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); + if (eCpair.isOK && fConfigDFeC.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeC.binsMl.value.begin(), fConfigDFeC.binsMl.value.end(), binningFeature) - fConfigDFeC.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeC.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(6); + } + } // end of Omega- loop + + } else { // electron + // eL pair // sign is restricted in baryon decay: Lc- -> e- anti_nu_e antiLambda + for (const auto& antilambdaId : antilambdaIds) { + auto v0 = v0s.rawIteratorAt(antilambdaId); + if (v0.posTrackId() == electron.globalIndex() || v0.negTrackId() == electron.globalIndex()) { + continue; + } + const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; + const std::array momV0 = {v0.px(), v0.py(), v0.pz()}; + std::array covV0 = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covV0[MomInd[i]] = v0.momentumCovMat()[i]; + covV0[i] = v0.positionCovMat()[i]; + } + auto v0ParCov = o2::track::TrackParCov(vertexV0, momV0, covV0, 0, true); + v0ParCov.setAbsCharge(0); + v0ParCov.setPID(o2::track::PID::Lambda); + o2::dataformats::DCA impactParameterV0; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, v0ParCov, 2.f, matCorr, &impactParameterV0); // v0ParCov is TrackParCov object + + auto eV0pair = o2::aod::pwgem::dilepton::utils::makePairLeptonV0(dfeV0, collision, electron, v0, o2::track::PID::Electron, o2::track::PID::Lambda); + registry.fill(HIST("SCT/eV0/hImpactParameter"), eV0pair.impParXY, eV0pair.impParZ); + registry.fill(HIST("SCT/eV0/hDecayLength"), eV0pair.lxy, eV0pair.lz); + registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); + registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); + registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); + if (eV0pair.isOK && fConfigDFeV0.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeV0.binsMl.value.begin(), fConfigDFeV0.binsMl.value.end(), binningFeature) - fConfigDFeV0.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeV0.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(3); + } + } // end of antilambda loop + + // eXi pair // sign is restricted in baryon decay: Xic0bar -> e- anti_nu_e Xi+ + for (const auto& xiId : xiPlusIds) { + auto cascade = cascades.rawIteratorAt(xiId); + if (cascade.posTrackId() == electron.globalIndex() || cascade.negTrackId() == electron.globalIndex() || cascade.bachelorId() == electron.globalIndex()) { + continue; + } + + const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; + const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; + std::array covCasc = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covCasc[MomInd[i]] = cascade.momentumCovMat()[i]; + covCasc[i] = cascade.positionCovMat()[i]; + } + auto cascadeParCov = o2::track::TrackParCov(vertexCasc, momCasc, covCasc, cascade.sign(), true); + cascadeParCov.setAbsCharge(1); + cascadeParCov.setPID(o2::track::PID::XiMinus); + o2::dataformats::DCA impactParameterCasc; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, cascadeParCov, 2.f, matCorr, &impactParameterCasc); // cascadeParCov is TrackParCov object + + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(dfeC, collision, electron, cascade, o2::track::PID::Electron, o2::track::PID::XiMinus); + registry.fill(HIST("SCT/eC/hImpactParameter"), eCpair.impParXY, eCpair.impParZ); + registry.fill(HIST("SCT/eC/hDecayLength"), eCpair.lxy, eCpair.lz); + registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); + registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); + registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); + if (eCpair.isOK && fConfigDFeC.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeC.binsMl.value.begin(), fConfigDFeC.binsMl.value.end(), binningFeature) - fConfigDFeC.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeC.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(5); + } + } // end of Xi- loop + + // eOmega pair // sign is restricted in baryon decay: Omegac0bar -> e- anti_nu_e Omega+ + for (const auto& omegaId : omegaPlusIds) { + auto cascade = cascades.rawIteratorAt(omegaId); + if (cascade.posTrackId() == electron.globalIndex() || cascade.negTrackId() == electron.globalIndex() || cascade.bachelorId() == electron.globalIndex()) { + continue; + } + + const std::array vertexCasc = {cascade.x(), cascade.y(), cascade.z()}; + const std::array momCasc = {cascade.px(), cascade.py(), cascade.pz()}; + std::array covCasc = {0.}; + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + covCasc[MomInd[i]] = cascade.momentumCovMat()[i]; + covCasc[i] = cascade.positionCovMat()[i]; + } + auto cascadeParCov = o2::track::TrackParCov(vertexCasc, momCasc, covCasc, cascade.sign(), true); + cascadeParCov.setAbsCharge(1); + cascadeParCov.setPID(o2::track::PID::OmegaMinus); + o2::dataformats::DCA impactParameterCasc; + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, cascadeParCov, 2.f, matCorr, &impactParameterCasc); // cascadeParCov is TrackParCov object + + auto eCpair = o2::aod::pwgem::dilepton::utils::makePairLeptonCascade(dfeC, collision, electron, cascade, o2::track::PID::Electron, o2::track::PID::OmegaMinus); + registry.fill(HIST("SCT/eC/hImpactParameter"), eCpair.impParXY, eCpair.impParZ); + registry.fill(HIST("SCT/eC/hDecayLength"), eCpair.lxy, eCpair.lz); + registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); + registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); + registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); + if (eCpair.isOK && fConfigDFeC.useML) { + o2::analysis::pwgem::dilepton::sct::candidate candidate; + fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); + candidate.ptL = trackParCov.getPt(); + + std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); + float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); + + int pbin = lower_bound(fConfigDFeC.binsMl.value.begin(), fConfigDFeC.binsMl.value.end(), binningFeature) - fConfigDFeC.binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(fConfigDFeC.binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; + } + + float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; + float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; + float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; + float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; + bdtScorePrompt.emplace_back(probaPrompt); + bdtScorePromptHc.emplace_back(probaPromptHc); + bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); + bdtScoreHb.emplace_back(probaHb); + hadronType.emplace_back(7); + } + } // end of Omega- loop + } + + products.sctTable(bdtScorePrompt, bdtScorePromptHc, bdtScoreNonpromptHc, bdtScoreHb, hadronType); + + bdtScorePrompt.clear(); + bdtScorePromptHc.clear(); + bdtScoreNonpromptHc.clear(); + bdtScoreHb.clear(); + hadronType.clear(); + bdtScorePrompt.shrink_to_fit(); + bdtScorePromptHc.shrink_to_fit(); + bdtScoreNonpromptHc.shrink_to_fit(); + bdtScoreHb.shrink_to_fit(); + hadronType.shrink_to_fit(); + } // end of main electron loop + + hadronIds.clear(); + hadronIds.shrink_to_fit(); + + k0sIds.clear(); + k0sIds.shrink_to_fit(); + + lambdaIds.clear(); + lambdaIds.shrink_to_fit(); + antilambdaIds.clear(); + antilambdaIds.shrink_to_fit(); + + xiMinusIds.clear(); + xiMinusIds.shrink_to_fit(); + xiPlusIds.clear(); + xiPlusIds.shrink_to_fit(); + + omegaMinusIds.clear(); + omegaMinusIds.shrink_to_fit(); + omegaPlusIds.clear(); + omegaPlusIds.shrink_to_fit(); + + looseElectronIds.clear(); + looseElectronIds.shrink_to_fit(); + multiMapTracksPerCollision.clear(); + } // end of collision loop + clear(); + } + + template + void processWithoutTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const&, TV0s const&, TCascades const&, TMCCollisions const&, TMCParticles const&, TProducts&, THistoregistry&) + { + LOGF(info, "processWithoutTTCA is not supported. Bye."); + return; + + initCCDB(bcs.begin()); + // calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if constexpr (isMC) { + if (!collision.has_mcCollision()) { + continue; + } + } + + if (!collision.isSelected()) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } + } + + } // end of collision loop + + clear(); + } + + void clear() + { + // this should be called at the end of DF. + fMapProbaEl.clear(); + fMapTOFNsigmaElReassociated.clear(); + fMapTOFNsigmaPiReassociated.clear(); + fMapTOFNsigmaKaReassociated.clear(); + fMapTOFNsigmaPrReassociated.clear(); + fMapTOFBetaReassociated.clear(); + } + + void doSCTwithTracks(const bool flag) { fDoSCTwithTracks = flag; } + void doSCTwithV0s(const bool flag) { fDoSCTwithV0s = flag; } + void doSCTwithCascades(const bool flag) { fDoSCTwithCascades = flag; } + + float dca3DinSigmaOTF(const float dcaXY, const float dcaZ, const float cYY, const float cZZ, const float cZY) + { + float det = cYY * cZZ - cZY * cZY; // determinant + if (det < 0) { + return 999.f; + } else { + return std::sqrt(std::fabs((dcaXY * dcaXY * cZZ + dcaZ * dcaZ * cYY - 2. * dcaXY * dcaZ * cZY) / det / 2.)); // dca 3d in sigma + } + } + + template + void fillCandidate(TCandidate& candidate, TPair const& pair, TTrackParCov const& trackParCov, TDCA const& dcaInfo) + { + candidate.ptH = trackParCov.getPt(); + candidate.tpcNSigmaKa = 0; + candidate.impParXYH = dcaInfo.getY(); + candidate.impParZH = dcaInfo.getZ(); + candidate.impPar3DH = std::sqrt(std::pow(candidate.impParXYH, 2) + std::pow(candidate.impParZH, 2)); + candidate.impParXYHinSigma = candidate.impParXYH / std::sqrt(trackParCov.getSigmaY2()); + candidate.impParZHinSigma = candidate.impParZH / std::sqrt(trackParCov.getSigmaZ2()); + candidate.impPar3DHinSigma = dca3DinSigmaOTF(candidate.impParXYH, candidate.impParZH, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY()); + candidate.signLH = 0; + candidate.dcaLH = pair.dca2legs; + candidate.massLH = pair.mass; + candidate.ptLH = pair.pt; + candidate.signedMassLH = pair.mass; + candidate.cpa = pair.cospa; + candidate.cpaXY = pair.cospaXY; + candidate.impParXY = pair.impParXY; + candidate.impParZ = pair.impParZ; + candidate.impPar3D = std::sqrt(std::pow(candidate.impParXY, 2) + std::pow(candidate.impParZ, 2)); + candidate.impParXYinSigma = candidate.impParXY / std::sqrt(pair.impParCYY); + candidate.impParZinSigma = candidate.impParZ / std::sqrt(pair.impParCZZ); + candidate.impPar3DinSigma = dca3DinSigmaOTF(candidate.impParXY, candidate.impParZ, pair.impParCYY, pair.impParCZY, pair.impParCZZ); + candidate.decayLengthXY = pair.lxy; + candidate.decayLengthZ = pair.lz; + candidate.decayLength3D = pair.lxyz; + candidate.decayLengthXYinSigma = pair.lxy / pair.lxyErr; + candidate.decayLengthZinSigma = pair.lz / pair.lzErr; + candidate.decayLength3DinSigma = pair.lxyz / pair.lxyzErr; + } + + protected: + electronCut fElectronCut; + electronPFCut fElectronPFCut; + hadronCut fHadronCut; + v0Cut fV0Cut; + cascadeCut fCascadeCut; + cfgDFeT fConfigDFeT; + cfgDFeV0 fConfigDFeV0; + cfgDFeC fConfigDFeC; + + std::map, float> fMapProbaEl; // map pair(collisionId, trackId) -> probaEl + std::map, float> fMapTOFNsigmaElReassociated; // map pair(collisionId, trackId) -> tof n sigma el + std::map, float> fMapTOFNsigmaPiReassociated; // map pair(collisionId, trackId) -> tof n sigma pi + std::map, float> fMapTOFNsigmaKaReassociated; // map pair(collisionId, trackId) -> tof n sigma ka + std::map, float> fMapTOFNsigmaPrReassociated; // map pair(collisionId, trackId) -> tof n sigma pr + std::map, float> fMapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta + + int mRunNumber{0}; + float d_bz{0}; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::dataformats::VertexBase mVtx; + o2::framework::Service mTOFResponse; + o2::analysis::MlResponsePID mlResponsePID; + o2::analysis::MlResponseSCT mlResponseSCTeT; + o2::analysis::MlResponseSCT mlResponseSCTeV0; + o2::analysis::MlResponseSCT mlResponseSCTeC; + + bool fDoSCTwithTracks{false}; + bool fDoSCTwithV0s{false}; + bool fDoSCTwithCascades{false}; + const std::vector max_mee_vec{0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14}; + o2::vertexing::DCAFitterN<2> dfeT; + o2::vertexing::DCAFitterN<2> dfeV0; + o2::vertexing::DCAFitterN<2> dfeC; + o2::ccdb::CcdbApi ccdbApi; + +}; // end ElectronModule + +} // namespace pwgem::dilepton::utils +} // namespace o2 + +#endif // PWGEM_DILEPTON_UTILS_ELECTRONMODULE_H_ diff --git a/PWGEM/Dilepton/Utils/MlResponsePID.h b/PWGEM/Dilepton/Utils/MlResponsePID.h new file mode 100644 index 00000000000..13e8048f798 --- /dev/null +++ b/PWGEM/Dilepton/Utils/MlResponsePID.h @@ -0,0 +1,147 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MlResponsePID.h +/// \brief Class to compute the ML response for fwdtracks +/// \author Daiki Sekihata + +#ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEPID_H_ +#define PWGEM_DILEPTON_UTILS_MLRESPONSEPID_H_ + +#include "Tools/ML/MlResponse.h" + +#include + +#include +#include +#include + +// Fill the map of available input features +// the key is the feature's name (std::string) +// the value is the corresponding value in EnumInputFeatures +#define FILL_MAP_TRACK(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesPID::FEATURE)} + +// Check if the index of mCachedIndices (index associated to a FEATURE) +// matches the entry in EnumInputFeatures associated to this FEATURE +// if so, the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER=FEATURE from track +#define CHECK_AND_FILL_TRACK(GETTER) \ + case static_cast(InputFeaturesPID::GETTER): { \ + inputFeature = track.GETTER; \ + break; \ + } + +namespace o2::analysis +{ +// possible input features for ML +enum class InputFeaturesPID : uint8_t { + tpcInnerParam, + tpcNClsFound, + tpcChi2NCl, + tpcNSigmaEl, + tofNSigmaEl, + meanClusterSizeITSobCosTgl, +}; + +namespace pwgem::dilepton::mlpid +{ +struct candidate { + float tpcInnerParam{0}; + int tpcNClsFound{0}; + float tpcChi2NCl{0}; + float tpcNSigmaEl{0}; + float tofNSigmaEl{0}; + float meanClusterSizeITSobCosTgl{0}; +}; +} // namespace pwgem::dilepton::mlpid + +template +class MlResponsePID : public MlResponse +{ + public: + /// Default constructor + MlResponsePID() = default; + /// Default destructor + virtual ~MlResponsePID() = default; + + template + float return_feature(uint8_t idx, T const& track) + { + float inputFeature = 0.; + switch (idx) { + CHECK_AND_FILL_TRACK(tpcInnerParam); + CHECK_AND_FILL_TRACK(tpcNClsFound); + CHECK_AND_FILL_TRACK(tpcChi2NCl); + CHECK_AND_FILL_TRACK(tpcNSigmaEl); + CHECK_AND_FILL_TRACK(tofNSigmaEl); + CHECK_AND_FILL_TRACK(meanClusterSizeITSobCosTgl); + } + return inputFeature; + } + + /// Method to get the input features vector needed for ML inference + /// \param track is the single track, \param collision is the collision + /// \return inputFeatures vector + template + std::vector getInputFeatures(T const& track) + { + std::vector inputFeatures; + for (const auto& idx : MlResponse::mCachedIndices) { + float inputFeature = return_feature(idx, track); + inputFeatures.emplace_back(inputFeature); + } + return inputFeatures; + } + + /// Method to get the value of variable chosen for binning + /// \param track is the single track, \param collision is the collision + /// \return binning variable + template + float getBinningFeature(T const& track) + { + return return_feature(mCachedIndexBinning, track); + } + + void cacheBinningIndex(std::string const& cfgBinningFeature) + { + setAvailableInputFeatures(); + if (MlResponse::mAvailableInputFeatures.count(cfgBinningFeature)) { + mCachedIndexBinning = MlResponse::mAvailableInputFeatures[cfgBinningFeature]; + } else { + LOG(fatal) << "Binning feature " << cfgBinningFeature << " not available! Please check your configurables."; + } + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_TRACK(tpcInnerParam), + FILL_MAP_TRACK(tpcNClsFound), + FILL_MAP_TRACK(tpcChi2NCl), + FILL_MAP_TRACK(tpcNSigmaEl), + FILL_MAP_TRACK(tofNSigmaEl), + FILL_MAP_TRACK(meanClusterSizeITSobCosTgl), + }; + } + + uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features +}; + +} // namespace o2::analysis + +#undef FILL_MAP_TRACK +#undef CHECK_AND_FILL_TRACK + +#endif // PWGEM_DILEPTON_UTILS_MLRESPONSEPID_H_ diff --git a/PWGEM/Dilepton/Utils/MlResponseSCT.h b/PWGEM/Dilepton/Utils/MlResponseSCT.h new file mode 100644 index 00000000000..d0c1353e443 --- /dev/null +++ b/PWGEM/Dilepton/Utils/MlResponseSCT.h @@ -0,0 +1,264 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MlResponseSCT.h +/// \brief Class to compute the ML response for fwdtracks +/// \author Daiki Sekihata + +#ifndef PWGEM_DILEPTON_UTILS_MLRESPONSESCT_H_ +#define PWGEM_DILEPTON_UTILS_MLRESPONSESCT_H_ + +#include "Tools/ML/MlResponse.h" + +#include + +#include +#include +#include + +// Fill the map of available input features +// the key is the feature's name (std::string) +// the value is the corresponding value in EnumInputFeatures +#define FILL_MAP_TRACK(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesSCT::FEATURE)} + +// Check if the index of mCachedIndices (index associated to a FEATURE) +// matches the entry in EnumInputFeatures associated to this FEATURE +// if so, the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER=FEATURE from track +#define CHECK_AND_FILL_TRACK(GETTER) \ + case static_cast(InputFeaturesSCT::GETTER): { \ + inputFeature = track.GETTER; \ + break; \ + } + +namespace o2::analysis +{ +// possible input features for ML +enum class InputFeaturesSCT : uint8_t { + ptL, + impParXYL, + impParZL, + impPar3DL, + impParXYLinSigma, + impParZLinSigma, + impPar3DLinSigma, + ptH, + tpcNSigmaKa, + impParXYH, + impParZH, + impPar3DH, + impParXYHinSigma, + impParZHinSigma, + impPar3DHinSigma, + signLH, + dcaLH, + massLH, + ptLH, + signedMassLH, + cpa, + cpaXY, + impParXY, + impParZ, + impPar3D, + impParXYinSigma, + impParZinSigma, + impPar3DinSigma, + decayLengthXY, + decayLengthZ, + decayLength3D, + decayLengthXYinSigma, + decayLengthZinSigma, + decayLength3DinSigma, +}; + +namespace pwgem::dilepton::sct +{ +struct candidate { + // lepton info. (don't use them to avoid bias to single lepton) + float ptL{0}; + float impParXYL{0}; + float impParZL{0}; + float impPar3DL{0}; + float impParXYLinSigma{0}; + float impParZLinSigma{0}; + float impPar3DLinSigma{0}; + + // hadron information + float ptH{0}; + float tpcNSigmaKa{0}; + float impParXYH{0}; + float impParZH{0}; + float impPar3DH{0}; + float impParXYHinSigma{0}; + float impParZHinSigma{0}; + float impPar3DHinSigma{0}; + + // LH pair information + int signLH{0}; + float dcaLH{0}; + float massLH{0}; + float ptLH{0}; + float signedMassLH{0}; + float cpa{0}; + float cpaXY{0}; + float impParXY{0}; + float impParZ{0}; + float impPar3D{0}; + float impParXYinSigma{0}; + float impParZinSigma{0}; + float impPar3DinSigma{0}; + float decayLengthXY{0}; + float decayLengthZ{0}; + float decayLength3D{0}; + float decayLengthXYinSigma{0}; + float decayLengthZinSigma{0}; + float decayLength3DinSigma{0}; +}; +} // namespace pwgem::dilepton::sct + +template +class MlResponseSCT : public MlResponse +{ + public: + /// Default constructor + MlResponseSCT() = default; + /// Default destructor + virtual ~MlResponseSCT() = default; + + template + float return_feature(uint8_t idx, T const& track) + { + float inputFeature = 0.; + switch (idx) { + CHECK_AND_FILL_TRACK(ptL); + CHECK_AND_FILL_TRACK(impParXYL); + CHECK_AND_FILL_TRACK(impParZL); + CHECK_AND_FILL_TRACK(impPar3DL); + CHECK_AND_FILL_TRACK(impParXYLinSigma); + CHECK_AND_FILL_TRACK(impParZLinSigma); + CHECK_AND_FILL_TRACK(impPar3DLinSigma); + CHECK_AND_FILL_TRACK(ptH); + CHECK_AND_FILL_TRACK(tpcNSigmaKa); + CHECK_AND_FILL_TRACK(impParXYH); + CHECK_AND_FILL_TRACK(impParZH); + CHECK_AND_FILL_TRACK(impPar3DH); + CHECK_AND_FILL_TRACK(impParXYHinSigma); + CHECK_AND_FILL_TRACK(impParZHinSigma); + CHECK_AND_FILL_TRACK(impPar3DHinSigma); + CHECK_AND_FILL_TRACK(signLH); + CHECK_AND_FILL_TRACK(dcaLH); + CHECK_AND_FILL_TRACK(massLH); + CHECK_AND_FILL_TRACK(ptLH); + CHECK_AND_FILL_TRACK(signedMassLH); + CHECK_AND_FILL_TRACK(cpa); + CHECK_AND_FILL_TRACK(cpaXY); + CHECK_AND_FILL_TRACK(impParXY); + CHECK_AND_FILL_TRACK(impParZ); + CHECK_AND_FILL_TRACK(impPar3D); + CHECK_AND_FILL_TRACK(impParXYinSigma); + CHECK_AND_FILL_TRACK(impParZinSigma); + CHECK_AND_FILL_TRACK(impPar3DinSigma); + CHECK_AND_FILL_TRACK(decayLengthXY); + CHECK_AND_FILL_TRACK(decayLengthZ); + CHECK_AND_FILL_TRACK(decayLength3D); + CHECK_AND_FILL_TRACK(decayLengthXYinSigma); + CHECK_AND_FILL_TRACK(decayLengthZinSigma); + CHECK_AND_FILL_TRACK(decayLength3DinSigma); + } + return inputFeature; + } + + /// Method to get the input features vector needed for ML inference + /// \param track is the single track, \param collision is the collision + /// \return inputFeatures vector + template + std::vector getInputFeatures(T const& track) + { + std::vector inputFeatures; + for (const auto& idx : MlResponse::mCachedIndices) { + float inputFeature = return_feature(idx, track); + inputFeatures.emplace_back(inputFeature); + } + return inputFeatures; + } + + /// Method to get the value of variable chosen for binning + /// \param track is the single track, \param collision is the collision + /// \return binning variable + template + float getBinningFeature(T const& track) + { + return return_feature(mCachedIndexBinning, track); + } + + void cacheBinningIndex(std::string const& cfgBinningFeature) + { + setAvailableInputFeatures(); + if (MlResponse::mAvailableInputFeatures.count(cfgBinningFeature)) { + mCachedIndexBinning = MlResponse::mAvailableInputFeatures[cfgBinningFeature]; + } else { + LOG(fatal) << "Binning feature " << cfgBinningFeature << " not available! Please check your configurables."; + } + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_TRACK(ptL), + FILL_MAP_TRACK(impParXYL), + FILL_MAP_TRACK(impParZL), + FILL_MAP_TRACK(impPar3DL), + FILL_MAP_TRACK(impParXYLinSigma), + FILL_MAP_TRACK(impParZLinSigma), + FILL_MAP_TRACK(impPar3DLinSigma), + FILL_MAP_TRACK(ptH), + FILL_MAP_TRACK(tpcNSigmaKa), + FILL_MAP_TRACK(impParXYH), + FILL_MAP_TRACK(impParZH), + FILL_MAP_TRACK(impPar3DH), + FILL_MAP_TRACK(impParXYHinSigma), + FILL_MAP_TRACK(impParZHinSigma), + FILL_MAP_TRACK(impPar3DHinSigma), + FILL_MAP_TRACK(signLH), + FILL_MAP_TRACK(dcaLH), + FILL_MAP_TRACK(massLH), + FILL_MAP_TRACK(ptLH), + FILL_MAP_TRACK(signedMassLH), + FILL_MAP_TRACK(cpa), + FILL_MAP_TRACK(cpaXY), + FILL_MAP_TRACK(impParXY), + FILL_MAP_TRACK(impParZ), + FILL_MAP_TRACK(impPar3D), + FILL_MAP_TRACK(impParXYinSigma), + FILL_MAP_TRACK(impParZinSigma), + FILL_MAP_TRACK(impPar3DinSigma), + FILL_MAP_TRACK(decayLengthXY), + FILL_MAP_TRACK(decayLengthZ), + FILL_MAP_TRACK(decayLength3D), + FILL_MAP_TRACK(decayLengthXYinSigma), + FILL_MAP_TRACK(decayLengthZinSigma), + FILL_MAP_TRACK(decayLength3DinSigma), + }; + } + + uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features +}; + +} // namespace o2::analysis + +#undef FILL_MAP_TRACK +#undef CHECK_AND_FILL_TRACK + +#endif // PWGEM_DILEPTON_UTILS_MLRESPONSESCT_H_ From 490e87557136f7270e82211d39a465dca426cafa Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 21 May 2026 05:06:45 +0200 Subject: [PATCH 249/449] [PWGHF] Fix deltaphiEP calculation (#16332) --- PWGHF/D2H/Tasks/taskCharmPolarisation.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 74a57633ce1..5bd5b1b4bb4 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -2344,11 +2344,11 @@ struct HfTaskCharmPolarisation { float const xQvec = (*qVecs).at(0); float const yQvec = (*qVecs).at(1); ROOT::Math::XYZVector const qVecNorm = ROOT::Math::XYZVector(yQvec, -xQvec, 0.f); - ROOT::Math::XYZVector const qVec = ROOT::Math::XYZVector(xQvec, yQvec, 0.); - ROOT::Math::XYZVector threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); - float const phiEP = qVec.Dot(threeVecDauCMXY) / std::sqrt(threeVecDauCMXY.Mag2()) / std::sqrt(qVec.Mag2()); + float const phiStarBeam = std::atan2(threeVecDauCM.Y(), threeVecDauCM.X()); + float const psiAngle = epHelper.GetEventPlane(xQvec, yQvec, 2); + float const deltaPhiStarEP = RecoDecay::constrainAngle(phiStarBeam - psiAngle, 0., 2); float const cosThetaStarEP = qVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(qVecNorm.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, phiEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, deltaPhiStarEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); } if (DoMc) { // EP analysis for MC From eacf1a2b3d3f548fb4aa8c51fbcf8b765793eafb Mon Sep 17 00:00:00 2001 From: Florian Jonas Date: Thu, 21 May 2026 11:14:06 +0200 Subject: [PATCH 250/449] [PWGJE] isolation fixes & MC prompt photon information fixes (#16308) Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/gammaJetTreeProducer.cxx | 214 ++++++++++++++++++++++----- 1 file changed, 177 insertions(+), 37 deletions(-) diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index de043149abe..c117287038c 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -120,9 +121,11 @@ struct GammaJetTreeProducer { std::vector trackEta; std::vector trackPhi; std::vector trackPt; + std::vector trackSourceIndex; std::vector mcParticleEta; std::vector mcParticlePhi; std::vector mcParticlePt; + std::vector mcParticleSourceIndex; TKDTree* trackTree = nullptr; TKDTree* mcParticleTree = nullptr; @@ -265,22 +268,36 @@ struct GammaJetTreeProducer { curMcParticleTreeColIndex = collision.globalIndex(); } - trackEta.clear(); - trackPhi.clear(); - trackPt.clear(); - mcParticleEta.clear(); - mcParticlePhi.clear(); - mcParticlePt.clear(); - // if the track type is aod::JetTracks, we need to build the kd tree for the tracks if constexpr (std::is_same_v, aod::JetTracks>) { + trackEta.clear(); + trackPhi.clear(); + trackPt.clear(); + trackSourceIndex.clear(); + const float maxMatchingDistance = std::max(static_cast(isoR), static_cast(perpConeJetR)); + const float additionalMargin = 0.05f; for (const auto& track : objects) { if (!isTrackSelected(track)) { continue; } + const float phi = RecoDecay::constrainAngle(track.phi(), 0.0); + const int originalIndex = static_cast(trackPt.size()); trackEta.push_back(track.eta()); - trackPhi.push_back(track.phi()); + trackPhi.push_back(phi); trackPt.push_back(track.pt()); + trackSourceIndex.push_back(originalIndex); + if (phi <= (maxMatchingDistance + additionalMargin)) { + trackEta.push_back(track.eta()); + trackPhi.push_back(phi + o2::constants::math::TwoPI); + trackPt.push_back(track.pt()); + trackSourceIndex.push_back(originalIndex); + } + if (phi >= (o2::constants::math::TwoPI - (maxMatchingDistance + additionalMargin))) { + trackEta.push_back(track.eta()); + trackPhi.push_back(phi - o2::constants::math::TwoPI); + trackPt.push_back(track.pt()); + trackSourceIndex.push_back(originalIndex); + } } if (trackEta.size() > 0) { delete trackTree; @@ -288,10 +305,20 @@ struct GammaJetTreeProducer { trackTree->SetData(0, trackEta.data()); trackTree->SetData(1, trackPhi.data()); trackTree->Build(); + } else { + // Keep tree state consistent with the current event content. + delete trackTree; + trackTree = nullptr; } } // if the track type is aod::JetParticles, we need to build the kd tree for the mc particles if constexpr (std::is_same_v, aod::JetParticles>) { + mcParticleEta.clear(); + mcParticlePhi.clear(); + mcParticlePt.clear(); + mcParticleSourceIndex.clear(); + const float maxMatchingDistance = std::max(static_cast(isoR), static_cast(perpConeJetR)); + const float additionalMargin = 0.05f; for (const auto& particle : objects) { if (!particle.isPhysicalPrimary()) { continue; @@ -302,9 +329,24 @@ struct GammaJetTreeProducer { if (particle.pt() < trackMinPt) { continue; } + const float phi = RecoDecay::constrainAngle(particle.phi(), 0.0); + const int originalIndex = static_cast(mcParticlePt.size()); mcParticleEta.push_back(particle.eta()); - mcParticlePhi.push_back(particle.phi()); + mcParticlePhi.push_back(phi); mcParticlePt.push_back(particle.pt()); + mcParticleSourceIndex.push_back(originalIndex); + if (phi <= (maxMatchingDistance + additionalMargin)) { + mcParticleEta.push_back(particle.eta()); + mcParticlePhi.push_back(phi + o2::constants::math::TwoPI); + mcParticlePt.push_back(particle.pt()); + mcParticleSourceIndex.push_back(originalIndex); + } + if (phi >= (o2::constants::math::TwoPI - (maxMatchingDistance + additionalMargin))) { + mcParticleEta.push_back(particle.eta()); + mcParticlePhi.push_back(phi - o2::constants::math::TwoPI); + mcParticlePt.push_back(particle.pt()); + mcParticleSourceIndex.push_back(originalIndex); + } } if (mcParticleEta.size() > 0) { delete mcParticleTree; @@ -312,6 +354,10 @@ struct GammaJetTreeProducer { mcParticleTree->SetData(0, mcParticleEta.data()); mcParticleTree->SetData(1, mcParticlePhi.data()); mcParticleTree->Build(); + } else { + // Keep tree state consistent with the current event content. + delete mcParticleTree; + mcParticleTree = nullptr; } } } @@ -350,7 +396,7 @@ struct GammaJetTreeProducer { { mHistograms.fill(HIST("eventQA"), 0); - if (collision.posZ() > mVertexCut) { + if (std::abs(collision.posZ()) > mVertexCut) { return false; } mHistograms.fill(HIST("eventQA"), 1); @@ -385,6 +431,33 @@ struct GammaJetTreeProducer { return std::abs(pdg->GetParticle(particle.pdgCode())->Charge()) >= 1.; } + /// \brief Sums pt values once per unique source index from KD-tree query indices + /// \param indices KD-tree result indices + /// \param sourceIndexMap Maps KD-tree entry index to original object index + /// \param ptValues pt values of original objects + /// \param uniqueSourceIndices Set used to deduplicate source indices + /// \return Sum of unique pt values for the given indices + double sumUniquePtFromIndices(const std::vector& indices, + const std::vector& sourceIndexMap, + const std::vector& ptValues, + std::unordered_set& uniqueSourceIndices) + { + double ptSum = 0; + for (const auto& index : indices) { + if (index < 0 || static_cast(index) >= sourceIndexMap.size()) { + continue; + } + const int sourceIndex = sourceIndexMap[index]; + if (sourceIndex < 0 || static_cast(sourceIndex) >= ptValues.size()) { + continue; + } + if (uniqueSourceIndices.insert(sourceIndex).second) { + ptSum += ptValues[sourceIndex]; + } + } + return ptSum; + } + /// \brief Calculates the charged particle isolation in a cone of given size using a pre-built kd tree /// \param particle The particle to calculate the isolation for /// \param radius The cone radius @@ -394,15 +467,14 @@ struct GammaJetTreeProducer { double ch_iso_in_cone(const T& particle, float radius = 0.4, bool mcGenIso = false) { double iso = 0; - float point[2] = {particle.eta(), particle.phi()}; + float point[2] = {particle.eta(), RecoDecay::constrainAngle(particle.phi(), 0.0)}; std::vector indices; + std::unordered_set uniqueSourceIndices; if (!mcGenIso) { if (trackTree) { trackTree->FindInRange(point, radius, indices); - for (const auto& index : indices) { - iso += trackPt[index]; - } + iso += sumUniquePtFromIndices(indices, trackSourceIndex, trackPt, uniqueSourceIndices); } else { LOG(error) << "Track tree not found"; return 0; @@ -410,9 +482,7 @@ struct GammaJetTreeProducer { } else { if (mcParticleTree) { mcParticleTree->FindInRange(point, radius, indices); - for (const auto& index : indices) { - iso += mcParticlePt[index]; - } + iso += sumUniquePtFromIndices(indices, mcParticleSourceIndex, mcParticlePt, uniqueSourceIndices); } else { LOG(error) << "MC particle tree not found"; return 0; @@ -435,14 +505,16 @@ struct GammaJetTreeProducer { double cPhi = TVector2::Phi_0_2pi(object.phi()); // rotate cone left by 90 degrees - float cPhiLeft = cPhi - o2::constants::math::PIHalf; - float cPhiRight = cPhi + o2::constants::math::PIHalf; + float cPhiLeft = RecoDecay::constrainAngle(cPhi - o2::constants::math::PIHalf, 0.0); + float cPhiRight = RecoDecay::constrainAngle(cPhi + o2::constants::math::PIHalf, 0.0); float pointLeft[2] = {object.eta(), cPhiLeft}; float pointRight[2] = {object.eta(), cPhiRight}; std::vector indicesLeft; std::vector indicesRight; + std::unordered_set uniqueSourceIndicesLeft; + std::unordered_set uniqueSourceIndicesRight; if (!mcGenIso) { if (trackTree) { @@ -453,12 +525,8 @@ struct GammaJetTreeProducer { return 0; } - for (const auto& index : indicesLeft) { - ptSumLeft += trackPt[index]; - } - for (const auto& index : indicesRight) { - ptSumRight += trackPt[index]; - } + ptSumLeft += sumUniquePtFromIndices(indicesLeft, trackSourceIndex, trackPt, uniqueSourceIndicesLeft); + ptSumRight += sumUniquePtFromIndices(indicesRight, trackSourceIndex, trackPt, uniqueSourceIndicesRight); } else { if (mcParticleTree) { mcParticleTree->FindInRange(pointLeft, radius, indicesLeft); @@ -467,12 +535,8 @@ struct GammaJetTreeProducer { LOG(error) << "MC particle tree not found"; return 0; } - for (const auto& index : indicesLeft) { - ptSumLeft += mcParticlePt[index]; - } - for (const auto& index : indicesRight) { - ptSumRight += mcParticlePt[index]; - } + ptSumLeft += sumUniquePtFromIndices(indicesLeft, mcParticleSourceIndex, mcParticlePt, uniqueSourceIndicesLeft); + ptSumRight += sumUniquePtFromIndices(indicesRight, mcParticleSourceIndex, mcParticlePt, uniqueSourceIndicesRight); } float rho = (ptSumLeft + ptSumRight) / (o2::constants::math::TwoPI * radius * radius); @@ -494,6 +558,46 @@ struct GammaJetTreeProducer { } } + /// \brief Prints the mother chain of a given MC particle. + /// \param particle The particle to print the mother chain for + template + void printMotherChain(const T& particle) const + { + T current = particle; + int depth = 0; + bool continueTracing = true; + while (continueTracing) { + LOG(info) << "Level " << depth + << " | PDG: " << current.pdgCode() + << " | E: " << current.energy() + << " | pt: " << current.pt() + << " | eta: " << current.eta() + << " | phi: " << current.phi() + << " | genStatusCode: " << current.getGenStatusCode() + << " | globalIndex: " << current.globalIndex(); + auto mothers = current.template mothers_as(); + if (mothers.size() == 0) { + break; + } + // Handle case with potentially duplicate mothers + int selectedMother = -1; + if (mothers.size() == 1) { + selectedMother = 0; + } else if (mothers.size() == 2 && + mothers[0].globalIndex() == mothers[1].globalIndex() && + mothers[0].pdgCode() == mothers[1].pdgCode() && + mothers[0].getGenStatusCode() == mothers[1].getGenStatusCode()) { + selectedMother = 0; + } + if (selectedMother == -1) { + LOG(info) << "Branching in mother chain or unclear mothers, stopping trace."; + break; + } + current = mothers[selectedMother]; + ++depth; + } + } + /// \brief Finds the top-most copy of a particle in the decay chain (following carbon copies) /// \param particle The particle to start from /// \return The top-most copy of the particle @@ -504,10 +608,36 @@ struct GammaJetTreeProducer { T currentParticle = particle; int pdgCode = particle.pdgCode(); auto mothers = particle.template mothers_as(); - while (iUp > 0 && mothers.size() == 1 && mothers[0].globalIndex() > 0 && mothers[0].pdgCode() == pdgCode) { - iUp = mothers[0].globalIndex(); - currentParticle = mothers[0]; + // sometimes the particle will have two identical mothers, not sure why, but we need to cover this case + // if there are two mothers, but they are not identical, we will stop + bool twoMothersIdentical = false; + int selectedMother = -1; + if (mothers.size() == 1) { + selectedMother = 0; + } else if (mothers.size() == 2) { + twoMothersIdentical = (mothers[0].globalIndex() == mothers[1].globalIndex() && + mothers[0].pdgCode() == mothers[1].pdgCode() && + mothers[0].getGenStatusCode() == mothers[1].getGenStatusCode()); + if (twoMothersIdentical) { + selectedMother = 0; + } + } + while (iUp > 0 && selectedMother >= 0 && mothers[selectedMother].globalIndex() > 0 && mothers[selectedMother].pdgCode() == pdgCode) { + iUp = mothers[selectedMother].globalIndex(); + currentParticle = mothers[selectedMother]; mothers = currentParticle.template mothers_as(); + selectedMother = -1; + twoMothersIdentical = false; + if (mothers.size() == 1) { + selectedMother = 0; + } else if (mothers.size() == 2) { + twoMothersIdentical = (mothers[0].globalIndex() == mothers[1].globalIndex() && + mothers[0].pdgCode() == mothers[1].pdgCode() && + mothers[0].getGenStatusCode() == mothers[1].getGenStatusCode()); + if (twoMothersIdentical) { + selectedMother = 0; + } + } } return currentParticle; } @@ -889,7 +1019,7 @@ struct GammaJetTreeProducer { // check that mother has exactly two daughters which are e+ and e- if (daughters.size() == 2) { LOG(debug) << "Got the daughters"; - if ((daughters.iteratorAt(0).pdgCode() == PDG_t::kElectron && daughters.iteratorAt(1).pdgCode() == PDG_t::kPositron) || (daughters.iteratorAt(0).pdgCode() == -PDG_t::kPositron && daughters.iteratorAt(1).pdgCode() == PDG_t::kElectron)) { + if ((daughters.iteratorAt(0).pdgCode() == PDG_t::kElectron && daughters.iteratorAt(1).pdgCode() == PDG_t::kPositron) || (daughters.iteratorAt(0).pdgCode() == PDG_t::kPositron && daughters.iteratorAt(1).pdgCode() == PDG_t::kElectron)) { SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kConvertedPhoton)); LOG(debug) << "Cluster is a converted photon"; } @@ -932,7 +1062,7 @@ struct GammaJetTreeProducer { int nRecCollisions = 0; mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 0); for (auto const& collision : collisions) { - if (collision.posZ() > mVertexCut) { + if (std::abs(collision.posZ()) > mVertexCut) { continue; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, true, true, rctLabel)) { @@ -1203,7 +1333,7 @@ struct GammaJetTreeProducer { if (jet.pt() < jetPtMin) { return; } - for (auto& jetConstituent : jet.template tracks_as()) { + for (const auto& jetConstituent : jet.template tracks_as()) { fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); } @@ -1305,11 +1435,21 @@ struct GammaJetTreeProducer { if (particle.pdgCode() != PDG_t::kPi0 && particle.pdgCode() != PDG_t::kGamma) { continue; } + // check the origin of the particle uint16_t origin = getMCParticleOrigin(particle); double mcIsolation = ch_iso_in_cone(particle, isoR, true); mcParticlesTable(storedColIndex, particle.energy(), particle.eta(), particle.phi(), particle.pt(), particle.pdgCode(), mcIsolation, origin); + // DEBUGGING for photons. If it is a photon, print the origin and then print the chain + // leaving this in here + // if (particle.pdgCode() == PDG_t::kGamma) { + // LOG(info) << "Particle PDG: " << particle.pdgCode() << " isPhysicalPrimary: " << particle.isPhysicalPrimary() << " getGenStatusCode: " << particle.getGenStatusCode(); + // LOG(info) << "Origin: " << "kPromptPhoton (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPromptPhoton))) << "), kDirectPromptPhoton (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDirectPromptPhoton))) << "), kFragmentationPhoton (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kFragmentationPhoton))) << "), kDecayPhoton (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhoton))) << "), kDecayPhotonPi0 (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonPi0))) << "), kDecayPhotonEta (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonEta))) << "), kDecayPhotonOther (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonOther))) << "), kPi0 (" << (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPi0))) << ")"; + // LOG(info) << "Mother chain: "; + // printMotherChain(particle); + // } + // fill mc gen trigger particle histograms mHistograms.fill(HIST("mcGenTrigger_E"), particle.energy()); mHistograms.fill(HIST("mcGenTrigger_Eta"), particle.eta()); From 32bb1695b8479aaee40a6da7a011d6be29041a8d Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Thu, 21 May 2026 12:44:01 +0200 Subject: [PATCH 251/449] [PWGCF] Fixing minor bugs related to mixed-event histograms (#16321) Co-authored-by: Sushanta Tripathy Co-authored-by: ALICE Action Bot --- .../Tasks/nucleibalance.cxx | 273 ++++++++++-------- 1 file changed, 153 insertions(+), 120 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx index dca0592bd91..f4ad2949422 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -1739,17 +1739,18 @@ struct Lambdastarproxy { // Helpers for invariant-mass kinematics static float phiFromPxPy(float px, float py) { - return std::atan2(py, px); + return RecoDecay::constrainAngle(std::atan2(py, px), -o2::constants::math::PI); } - static float rapidityFromEPz(double e, double pz) + static float ptFromPxPy(float px, float py) { - const double num = e + pz; - const double den = e - pz; - if (num <= 0.0 || den <= 0.0) { - return 0.f; - } - return static_cast(Half * std::log(num / den)); + return RecoDecay::pt(std::array{px, py}); + } + + static float rapidityFromMomentumAndMass(float px, float py, float pz, double mass) + + { + return RecoDecay::y(std::array{px, py, pz}, mass); } // Mixed-event pool entry for pK / proxy background (AO2D only) @@ -1757,6 +1758,7 @@ struct Lambdastarproxy { float mult = 0.f; float zvtx = 0.f; std::vector kaons; + std::vector protons; std::vector proxies; }; @@ -1966,56 +1968,44 @@ struct Lambdastarproxy { "pK invariant mass (like-sign);M_{pK} (GeV/c^{2});Counts", HistType::kTH1F, {massAxis}); - // Invariant-mass vs pair pT (use p_{T} of pK system) - histos.add("hInvMassPKUnlikeVsPt", - "pK invariant mass vs p_{T} (unlike-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", - HistType::kTH2F, {massAxis, ptAxis}); - histos.add("hInvMassPKLikeVsPt", - "pK invariant mass vs p_{T} (like-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", - HistType::kTH2F, {massAxis, ptAxis}); - - // THnSparse for invariant-mass analysis (mass, pT, y, phi) + // THnSparse for invariant-mass analysis (mass, pT, multiplicity/centrality) if (lstarEnableSparse.value != 0) { histos.add("hLambdaStarPKUnlikeSparse", - "#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + "#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality", HistType::kTHnSparseF, - {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, - AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, - AxisSpec{60, -1.5, 1.5, "y_{pK}"}, - AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + {AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis}); histos.add("hLambdaStarPKLikeSparse", - "#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + "#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality", HistType::kTHnSparseF, - {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, - AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, - AxisSpec{60, -1.5, 1.5, "y_{pK}"}, - AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + {AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis}); histos.add("hLambdaStarPKMixedSparse", - "#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + "#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);multiplicity/centrality", HistType::kTHnSparseF, - {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, - AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, - AxisSpec{60, -1.5, 1.5, "y_{pK}"}, - AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + {AxisSpec{400, 1.4, 1.8, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, centAxis}); - // THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, y, phi) + // THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, multiplicity/centrality) histos.add("hLambdaStarProxySparse", - "#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + "#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality", + HistType::kTHnSparseF, + {AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis}); + + histos.add("hLambdaStarProxyLikeSparse", + "#Lambda^{*}(1520) deuteron-proxy like-sign candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality", HistType::kTHnSparseF, - {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, - AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, - AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, - AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + {AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis}); histos.add("hLambdaStarProxyMixedSparse", - "#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + "#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);multiplicity/centrality", HistType::kTHnSparseF, - {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, - AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, - AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, - AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + {AxisSpec{400, 1.4, 1.8, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, centAxis}); } // Deuteron-proxy invariant mass (p_{proxy} from d/2 combined with K) @@ -2317,15 +2307,9 @@ struct Lambdastarproxy { static double invariantMass(float px1, float py1, float pz1, double m1, float px2, float py2, float pz2, double m2) { - const double e1 = std::sqrt(m1 * m1 + px1 * px1 + py1 * py1 + pz1 * pz1); - const double e2 = std::sqrt(m2 * m2 + px2 * px2 + py2 * py2 + pz2 * pz2); - const double ex = px1 + px2; - const double ey = py1 + py2; - const double ez = pz1 + pz2; - const double eTot = e1 + e2; - const double p2Tot = ex * ex + ey * ey + ez * ez; - const double m2Tot = eTot * eTot - p2Tot; - return m2Tot > 0. ? std::sqrt(m2Tot) : 0.; + return RecoDecay::m(std::array{std::array{px1, py1, pz1}, + std::array{px2, py2, pz2}}, + std::array{m1, m2}); } void process(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks) @@ -2635,12 +2619,15 @@ struct Lambdastarproxy { kaonCands.push_back(KaonCand{pxK, pyK, pzK, static_cast(trkK.sign()), static_cast(trkK.globalIndex())}); } - if (proxyCands.empty() || kaonCands.empty()) { - // still update mixing buffer so that later events can mix with this one + if (kaonCands.empty()) { + // Still update mixing buffer so that later events can mix with this one. + // The pK mixed-event background needs stored protons, while the proxy background + // needs stored proxy candidates. Therefore, do not require proxy candidates here. LStarMixEventEntry entry; entry.mult = eventMult; entry.zvtx = collision.posZ(); entry.kaons = std::move(kaonCands); + entry.protons = std::move(protonCands); entry.proxies = std::move(proxyCands); mLStarMixEvents.push_front(std::move(entry)); if (mLStarMixEvents.size() > static_cast(lstarNoMixedEvents.value)) { @@ -2649,103 +2636,148 @@ struct Lambdastarproxy { return; } + const bool hasProtonCandidates = !protonCands.empty(); + const bool hasProxyCandidates = !proxyCands.empty(); + // --- SAME-EVENT: genuine pK #Lambda^{*} candidates --- - for (auto const& pr : protonCands) { - for (auto const& k : kaonCands) { - if (pr.tid == k.tid) { - continue; - } - const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, - k.px, k.py, k.pz, MassKaonCharged); + if (hasProtonCandidates) { + for (auto const& pr : protonCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) { + continue; + } + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, + k.px, k.py, k.pz, MassKaonCharged); - const float pxTot = pr.px + k.px; - const float pyTot = pr.py + k.py; - const float pzTot = pr.pz + k.pz; - const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); - const float phiPair = phiFromPxPy(pxTot, pyTot); + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = ptFromPxPy(pxTot, pyTot); - const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + - static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); - const float yPair = rapidityFromEPz(eTot, pzTot); + const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass); - if (std::abs(yPair) > lstarLambdaAbsYMax.value) { - continue; - } - - const bool unlikeSignPK = (pr.charge * k.charge) < 0; - if (unlikeSignPK) { - histos.fill(HIST("hInvMassPKUnlike"), mass); - histos.fill(HIST("hInvMassPKUnlikeVsPt"), mass, ptPair); - if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + if (std::abs(yPair) > lstarLambdaAbsYMax.value) { + continue; } - } else { - histos.fill(HIST("hInvMassPKLike"), mass); - histos.fill(HIST("hInvMassPKLikeVsPt"), mass, ptPair); - if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + + const bool unlikeSignPK = (pr.charge * k.charge) < 0; + if (unlikeSignPK) { + histos.fill(HIST("hInvMassPKUnlike"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, eventMult); + } + } else { + histos.fill(HIST("hInvMassPKLike"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, eventMult); + } } } } } // --- SAME-EVENT: proxy (d/2) + K --- - for (auto const& pr : proxyCands) { - for (auto const& k : kaonCands) { - if (pr.tid == k.tid) - continue; // sanity check: should never match, but just in case of bug in candidate-building logic - const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); - - const float pxTot = pr.px + k.px; - const float pyTot = pr.py + k.py; - const float pzTot = pr.pz + k.pz; - const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); - const float phiPair = phiFromPxPy(pxTot, pyTot); - - const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); - const float yPair = rapidityFromEPz(eTot, pzTot); - - // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K) - histos.fill(HIST("hDeuteronProxyMass"), mass); - if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult); + if (hasProxyCandidates) { + for (auto const& pr : proxyCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float ptPair = ptFromPxPy(pxTot, pyTot); + + // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K) + histos.fill(HIST("hDeuteronProxyMass"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, eventMult); + + // Like-sign proxy background: proxy and kaon have the same charge sign. + // Here the proxy charge follows the original deuteron-candidate charge. + if ((pr.charge * k.charge) > 0) { + histos.fill(HIST("hLambdaStarProxyLikeSparse"), mass, ptPair, eventMult); + } + } } } } - // --- MIXED-EVENT: current proxies + previous-event kaons --- + // --- MIXED-EVENT: current kaons + previous-event real protons --- + // This fills the standard pK mixed-event background. for (auto const& prev : mLStarMixEvents) { - if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) + if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) { continue; - if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) + } + if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) { continue; - if (prev.kaons.empty()) { + } + if (prev.protons.empty()) { continue; } - for (auto const& pr : proxyCands) { - for (auto const& k : prev.kaons) { - // convention: mix for unlike-sign only (resonance background) + for (auto const& pr : prev.protons) { + for (auto const& k : kaonCands) { + // Unlike-sign pK mixed-event background. if ((pr.charge * k.charge) >= 0) { continue; } - if (pr.tid == k.tid) - continue; // sanity check: should never match, but just in case of bug in candidate-building logic - - const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, + k.px, k.py, k.pz, MassKaonCharged); const float pxTot = pr.px + k.px; const float pyTot = pr.py + k.py; const float pzTot = pr.pz + k.pz; - const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); - const float phiPair = phiFromPxPy(pxTot, pyTot); + const float ptPair = ptFromPxPy(pxTot, pyTot); - const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); - const float yPair = rapidityFromEPz(eTot, pzTot); + const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass); + if (std::abs(yPair) > lstarLambdaAbsYMax.value) { + continue; + } - // Fill mixed-event THnSparse (proxy only) if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); + histos.fill(HIST("hLambdaStarPKMixedSparse"), mass, ptPair, eventMult); + } + } + } + } + + // --- MIXED-EVENT: current proxies + previous-event kaons --- + // This fills the deuteron-proxy mixed-event background. + if (hasProxyCandidates) { + for (auto const& prev : mLStarMixEvents) { + if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) { + continue; + } + if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) { + continue; + } + if (prev.kaons.empty()) { + continue; + } + + for (auto const& pr : proxyCands) { + for (auto const& k : prev.kaons) { + // Unlike-sign proxy-K mixed-event background. + if ((pr.charge * k.charge) >= 0) { + continue; + } + + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, + k.px, k.py, k.pz, MassKaonCharged); + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = ptFromPxPy(pxTot, pyTot); + + const float yPair = rapidityFromMomentumAndMass(pxTot, pyTot, pzTot, mass); + if (std::abs(yPair) > lstarLambdaAbsYMax.value) { + continue; + } + + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, eventMult); + } } } } @@ -2756,6 +2788,7 @@ struct Lambdastarproxy { entry.mult = eventMult; entry.zvtx = collision.posZ(); entry.kaons = std::move(kaonCands); + entry.protons = std::move(protonCands); entry.proxies = std::move(proxyCands); mLStarMixEvents.push_front(std::move(entry)); From d763ae856764a3e1047a6dc813b4baf9c252b5d2 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 21 May 2026 14:05:17 +0200 Subject: [PATCH 252/449] [PWGEM/Dilepton] remove unnecessary variables (#16336) --- .../TableProducer/skimmerPrimaryElectronSCT.cxx | 16 ++++++++-------- PWGEM/Dilepton/Utils/ElectronModule.h | 12 +++++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx index 1df2cf31f2a..2836feae3db 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx @@ -208,44 +208,44 @@ struct skimmerPrimaryElectronSCT { void processRec_SA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { initCCDB(bcs.begin()); - electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, nullptr, products, mRegistry); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA, "process reconstructed info only", true); // standalone void processRec_TTCA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { initCCDB(bcs.begin()); - electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA, "process reconstructed info only", false); // with TTCA void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { initCCDB(bcs.begin()); - electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, nullptr, products, mRegistry); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA_SWT, "process reconstructed info only", false); // standalone with swt void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { initCCDB(bcs.begin()); - electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA with swt // ---------- for MC ---------- - void processMC_SA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + void processMC_SA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McParticles const& mcParticles) { initCCDB(bcs.begin()); - electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, mcCollisions, mcParticles, products, mRegistry); + electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, mcParticles, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_SA, "process reconstructed and MC info ", false); // without TTCA in MC - void processMC_TTCA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + void processMC_TTCA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McParticles const& mcParticles) { initCCDB(bcs.begin()); - electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, mcCollisions, mcParticles, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); + electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, mcParticles, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_TTCA, "process reconstructed info only", false); // with TTCA in MC }; diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index 87f4de166dc..b4b65f9beb5 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -271,7 +271,7 @@ struct cfgDFeT : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeT"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - + o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -288,6 +288,7 @@ struct cfgDFeV0 : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeV0"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -304,6 +305,7 @@ struct cfgDFeC : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeC"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -1343,8 +1345,8 @@ class ElectronModule } } - template - void processWithTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const& tracks, TV0s const& v0s, TCascades const& cascades, TTrackAssoc const& trackIndices, TMCCollisions const&, TMCParticles const&, TProducts& products, THistoregistry& registry, TSliceCache& cache, TPresliceTrack const& perColTrack, TPresliceTrackAssoc const& trackIndicesPerCollision, TPresliceV0 const& perColV0, TPresliceCascade const& perColCasc) + template + void processWithTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const& tracks, TV0s const& v0s, TCascades const& cascades, TTrackAssoc const& trackIndices, TMCParticles const&, TProducts& products, THistoregistry& registry, TSliceCache& cache, TPresliceTrack const& perColTrack, TPresliceTrackAssoc const& trackIndicesPerCollision, TPresliceV0 const& perColV0, TPresliceCascade const& perColCasc) { initCCDB(bcs.begin()); @@ -2105,8 +2107,8 @@ class ElectronModule clear(); } - template - void processWithoutTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const&, TV0s const&, TCascades const&, TMCCollisions const&, TMCParticles const&, TProducts&, THistoregistry&) + template + void processWithoutTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const&, TV0s const&, TCascades const&, TMCParticles const&, TProducts&, THistoregistry&) { LOGF(info, "processWithoutTTCA is not supported. Bye."); return; From 8a3eacbd08b07a093ea02c11768bab2cc84e1ae1 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Thu, 21 May 2026 15:54:50 +0200 Subject: [PATCH 253/449] [PWGCF] FemtoUniverse Cascade Task -- fixed misplaced brackets (#16330) Co-authored-by: Shirajum Monira --- ...toUniversePairTaskTrackCascadeExtended.cxx | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 897e2ac749a..9b9ddbb7d64 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -1222,34 +1222,33 @@ struct femtoUniversePairTaskTrackCascadeExtended { int pdgCode = static_cast(part.pidCut()); if ((confCascType1 == 0 && pdgCode != kOmegaMinus) || (confCascType1 == 2 && pdgCode != kOmegaPlusBar) || (confCascType1 == 1 && pdgCode != kXiMinus) || (confCascType1 == 3 && pdgCode != kXiPlusBar)) continue; - cascQAHistos.fillQA(part); + } - for (const auto& part : groupPartsOne) { - int pdgCode = static_cast(part.pidCut()); - if (pdgCode != trackparticleconfigs.confTrkPDGCodePartOne) - continue; - const auto& pdgTrackParticle = pdgMC->GetParticle(pdgCode); - if (!pdgTrackParticle) { - continue; - } - - if (pdgTrackParticle->Charge() > 0) { - trackHistoPartOnePos.fillQA(part); - } else if (pdgTrackParticle->Charge() < 0) { - trackHistoPartOneNeg.fillQA(part); - } + for (const auto& part : groupPartsOne) { + int pdgCode = static_cast(part.pidCut()); + if (pdgCode != trackparticleconfigs.confTrkPDGCodePartOne) + continue; + const auto& pdgTrackParticle = pdgMC->GetParticle(pdgCode); + if (!pdgTrackParticle) { + continue; } - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (static_cast(p1.pidCut()) != trackparticleconfigs.confTrkPDGCodePartOne) - continue; - int pdgCodeCasc = static_cast(p2.pidCut()); - if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) - continue; - sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + if (pdgTrackParticle->Charge() > 0) { + trackHistoPartOnePos.fillQA(part); + } else if (pdgTrackParticle->Charge() < 0) { + trackHistoPartOneNeg.fillQA(part); } } + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (static_cast(p1.pidCut()) != trackparticleconfigs.confTrkPDGCodePartOne) + continue; + int pdgCodeCasc = static_cast(p2.pidCut()); + if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) + continue; + sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + } } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventMCgen, "Enable processing same event MC truth for track - cascade", false); @@ -1268,24 +1267,23 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; cascQAHistos.fillQA(part); + } + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + int pdgCodeCasc1 = static_cast(p1.pidCut()); + if ((confCascType1 == 0 && pdgCodeCasc1 != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc1 != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc1 != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc1 != kXiPlusBar)) + return; + int pdgCodeCasc2 = static_cast(p2.pidCut()); + if ((confCascType2 == 0 && pdgCodeCasc2 != kOmegaMinus) || (confCascType2 == 2 && pdgCodeCasc2 != kOmegaPlusBar) || (confCascType2 == 1 && pdgCodeCasc2 != kXiMinus) || (confCascType2 == 3 && pdgCodeCasc2 != kXiPlusBar)) + return; + sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + }; - auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { - int pdgCodeCasc1 = static_cast(p1.pidCut()); - if ((confCascType1 == 0 && pdgCodeCasc1 != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc1 != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc1 != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc1 != kXiPlusBar)) - return; - int pdgCodeCasc2 = static_cast(p2.pidCut()); - if ((confCascType2 == 0 && pdgCodeCasc2 != kOmegaMinus) || (confCascType2 == 2 && pdgCodeCasc2 != kOmegaPlusBar) || (confCascType2 == 1 && pdgCodeCasc2 != kXiMinus) || (confCascType2 == 3 && pdgCodeCasc2 != kXiPlusBar)) - return; - sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); - }; - - if (confCascType1 == confCascType2) { - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) - pairProcessFunc(p1, p2); - } else { - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) - pairProcessFunc(p1, p2); - } + if (confCascType1 == confCascType2) { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) + pairProcessFunc(p1, p2); + } else { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) + pairProcessFunc(p1, p2); } } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCascMCgen, "Enable processing same event MC truth for cascade - cascade", false); From 15dc93f4a220dd889bf74f1b60d6b857360733a3 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Thu, 21 May 2026 16:01:17 +0200 Subject: [PATCH 254/449] [PWGLF] Fix Qvec ampl (#16337) --- PWGLF/TableProducer/QC/flowQC.cxx | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index ae946265d88..ec7e06c276f 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -289,37 +289,27 @@ struct flowQC { float QxFT0A_Qvec_raw = collision.qvecFT0AReVec()[qvecHarmonicIndex]; float QyFT0A_Qvec_raw = collision.qvecFT0AImVec()[qvecHarmonicIndex]; float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec_raw, QxFT0A_Qvec_raw, qvecHarmonic); - float QxFT0A_Qvec = maybeSquare(QxFT0A_Qvec_raw); - float QyFT0A_Qvec = maybeSquare(QyFT0A_Qvec_raw); - float QmodFT0A_Qvec = std::hypot(QxFT0A_Qvec, QyFT0A_Qvec); + float QmodFT0A_Qvec = maybeSquare(std::hypot(QxFT0A_Qvec_raw, QyFT0A_Qvec_raw)); float QxFT0C_Qvec_raw = collision.qvecFT0CReVec()[qvecHarmonicIndex]; float QyFT0C_Qvec_raw = collision.qvecFT0CImVec()[qvecHarmonicIndex]; float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec_raw, QxFT0C_Qvec_raw, qvecHarmonic); - float QxFT0C_Qvec = maybeSquare(QxFT0C_Qvec_raw); - float QyFT0C_Qvec = maybeSquare(QyFT0C_Qvec_raw); - float QmodFT0C_Qvec = std::hypot(QxFT0C_Qvec, QyFT0C_Qvec); + float QmodFT0C_Qvec = maybeSquare(std::hypot(QxFT0C_Qvec_raw, QyFT0C_Qvec_raw)); float QxTPCl_Qvec_raw = collision.qvecTPCnegReVec()[qvecHarmonicIndex]; float QyTPCl_Qvec_raw = collision.qvecTPCnegImVec()[qvecHarmonicIndex]; float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec_raw, QxTPCl_Qvec_raw, qvecHarmonic); - float QxTPCl_Qvec = maybeSquare(QxTPCl_Qvec_raw); - float QyTPCl_Qvec = maybeSquare(QyTPCl_Qvec_raw); - float QmodTPCl_Qvec = std::hypot(QxTPCl_Qvec, QyTPCl_Qvec); + float QmodTPCl_Qvec = maybeSquare(std::hypot(QxTPCl_Qvec_raw, QyTPCl_Qvec_raw)); float QxTPCr_Qvec_raw = collision.qvecTPCposReVec()[qvecHarmonicIndex]; float QyTPCr_Qvec_raw = collision.qvecTPCposImVec()[qvecHarmonicIndex]; float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec_raw, QxTPCr_Qvec_raw, qvecHarmonic); - float QxTPCr_Qvec = maybeSquare(QxTPCr_Qvec_raw); - float QyTPCr_Qvec = maybeSquare(QyTPCr_Qvec_raw); - float QmodTPCr_Qvec = std::hypot(QxTPCr_Qvec, QyTPCr_Qvec); + float QmodTPCr_Qvec = maybeSquare(std::hypot(QxTPCr_Qvec_raw, QyTPCr_Qvec_raw)); float QxTPC_Qvec_raw = collision.qvecTPCallReVec()[qvecHarmonicIndex]; float QyTPC_Qvec_raw = collision.qvecTPCallImVec()[qvecHarmonicIndex]; float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec_raw, QxTPC_Qvec_raw, qvecHarmonic); - float QxTPC_Qvec = maybeSquare(QxTPC_Qvec_raw); - float QyTPC_Qvec = maybeSquare(QyTPC_Qvec_raw); - float QmodTPC_Qvec = std::hypot(QxTPC_Qvec, QyTPC_Qvec); + float QmodTPC_Qvec = maybeSquare(std::hypot(QxTPC_Qvec_raw, QyTPC_Qvec_raw)); std::array vec_Qmod[2] = {{QmodFT0C_EP, QmodFT0A_EP, QmodTPCl_EP, QmodTPCr_EP, QmodTPC_EP}, {QmodFT0C_Qvec, QmodFT0A_Qvec, QmodTPCl_Qvec, QmodTPCr_Qvec, QmodTPC_Qvec}}; std::array vec_Qpsi[2] = {{psiFT0C_EP, psiFT0A_EP, psiTPCl_EP, psiTPCr_EP, psiTPC_EP}, {psiFT0C_Qvec, psiFT0A_Qvec, psiTPCl_Qvec, psiTPCr_Qvec, psiTPC_Qvec}}; From f9e3173e7ec21dcfd0ee4cb3354338506f82e761 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Thu, 21 May 2026 16:42:04 +0200 Subject: [PATCH 255/449] [ALICE3] Update multicharm bdt histograms (#16339) --- ALICE3/Tasks/alice3Multicharm.cxx | 133 ++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 35 deletions(-) diff --git a/ALICE3/Tasks/alice3Multicharm.cxx b/ALICE3/Tasks/alice3Multicharm.cxx index 4c01b936698..a27f6f937ba 100644 --- a/ALICE3/Tasks/alice3Multicharm.cxx +++ b/ALICE3/Tasks/alice3Multicharm.cxx @@ -55,7 +55,6 @@ using MultiCharmTracksFull = soa::Join pdgToBin; o2::ml::OnnxModel bdtMCharm; std::map metadata; o2::ccdb::CcdbApi ccdbApi; @@ -83,6 +82,7 @@ struct Alice3Multicharm { ConfigurableAxis axisDecayLength{"axisDecayLength", {2000, 0, 2000}, "Decay lenght (#mum)"}; ConfigurableAxis axisDcaDaughters{"axisDcaDaughters", {200, 0, 100}, "DCA (mum)"}; ConfigurableAxis axisBDTScore{"axisBDTScore", {100, 0, 1}, "BDT Score"}; + ConfigurableAxis axisBDTScoreFine{"axisBDTScoreFine", {1000, 0, 1}, "BDT Score for 1D histogram"}; ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; Configurable xiMinDCAxy{"xiMinDCAxy", -1, "[0] in |DCAxy| > [0]+[1]/pT"}; @@ -117,6 +117,29 @@ struct Alice3Multicharm { void init(InitContext&) { + histos.add("CandidateQA/hDCAXicDaughters", "hDCAXicDaughters; DCA between Xic daughters (#mum)", kTH1D, {axisDcaDaughters}); + histos.add("CandidateQA/hDCAXiccDaughters", "hDCAXiccDaughters; DCA between Xicc daughters (#mum)", kTH1D, {axisDcaDaughters}); + histos.add("CandidateQA/hDCAxyXi", "hDCAxyXi; Xi DCAxy to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDCAzXi", "hDCAzXi; Xi DCAz to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDCAxyXic", "hDCAxyXic; Xic DCAxy to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDCAzXic", "hDCAzXic; Xic DCAz to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDCAxyXicc", "hDCAxyXicc; Xicc DCAxy to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDCAzXicc", "hDCAzXicc; Xicc DCAz to PV (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hDecayRadiusXic", "hDecayRadiusXic; Distance (#mum)", kTH1D, {axisRadius}); + histos.add("CandidateQA/hDecayRadiusXicc", "hDecayRadiusXicc; Distance (#mum)", kTH1D, {axisRadius}); + histos.add("CandidateQA/hDecayDistanceFromPVXic", "hDecayDistanceFromPVXic; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("CandidateQA/hProperLengthXic", "hProperLengthXic; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("CandidateQA/hProperLengthXicc", "hProperLengthXicc; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("CandidateQA/hPi1cDCAxy", "hPi1cDCAxy; Pi1c DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPi1cDCAz", "hPi1cDCAz; Pi1c DCAz (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPi2cDCAxy", "hPi2cDCAxy; Pi2c DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPi2cDCAz", "hPi2cDCAz; Pi2c DCAz (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPiccDCAxy", "hPiccDCAxy; Picc DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPiccDCAz", "hPiccDCAz; Picc DCAz (#mum)", kTH1D, {axisDCA}); + histos.add("CandidateQA/hPi1cPt", "hPi1cPt; Pi1c pT (Gev/#it(c))", kTH1D, {axisPt}); + histos.add("CandidateQA/hPi2cPt", "hPi2cPt; Pi2c pT (Gev/#it(c))", kTH1D, {axisPt}); + histos.add("CandidateQA/hPiccPt", "hPiccPt; Picc pT (Gev/#it(c))", kTH1D, {axisPt}); + histos.add("SelectionQA/hDCAXicDaughters", "hDCAXicDaughters; DCA between Xic daughters (#mum)", kTH1D, {axisDcaDaughters}); histos.add("SelectionQA/hDCAXiccDaughters", "hDCAXiccDaughters; DCA between Xicc daughters (#mum)", kTH1D, {axisDcaDaughters}); histos.add("SelectionQA/hDCAxyXi", "hDCAxyXi; Xi DCAxy to PV (#mum)", kTH1D, {axisDCA}); @@ -196,10 +219,17 @@ struct Alice3Multicharm { bdtMCharm.initModel(bdt.localPath.value, bdt.enableOptimizations.value); } - histos.add("BDT/hBDTScore", "hBDTScore", kTH1D, {axisBDTScore}); - histos.add("BDT/hBDTScoreVsXiccMass", "hBDTScoreVsXiccMass", kTH2D, {axisXiccMass, axisBDTScore}); - histos.add("BDT/hBDTScoreVsXiccPt", "hBDTScoreVsXiccPt", kTH2D, {axisPt, axisBDTScore}); - histos.add("BDT/h3dBDTScore", "h3dBDTScore", kTH3D, {axisPt, axisXiccMass, axisBDTScore}); + histos.add("BDT/hBDTScoreSignalFine", "hBDTScoreSignalFine", kTH1D, {axisBDTScoreFine}); + histos.add("BDT/hBDTScoreSignal", "hBDTScoreSignal", kTH1D, {axisBDTScore}); + histos.add("BDT/hBDTScoreVsXiccMassSignal", "hBDTScoreVsXiccMassSignal", kTH2D, {axisXiccMass, axisBDTScore}); + histos.add("BDT/hBDTScoreVsXiccPtSignal", "hBDTScoreVsXiccPtSignal", kTH2D, {axisPt, axisBDTScore}); + histos.add("BDT/h3dBDTScoreSignal", "h3dBDTScoreSignal", kTH3D, {axisPt, axisXiccMass, axisBDTScore}); + histos.add("BDT/hBDTScoreBackgroundFine", "hBDTScoreBackgroundFine", kTH1D, {axisBDTScoreFine}); + histos.add("BDT/hBDTScoreBackground", "hBDTScoreBackground", kTH1D, {axisBDTScore}); + histos.add("BDT/hBDTScoreVsXiccMassBackground", "hBDTScoreVsXiccMassBackground", kTH2D, {axisXiccMass, axisBDTScore}); + histos.add("BDT/hBDTScoreVsXiccPtBackground", "hBDTScoreVsXiccPtBackground", kTH2D, {axisPt, axisBDTScore}); + histos.add("BDT/h3dBDTScoreBackground", "h3dBDTScoreBackground", kTH3D, {axisPt, axisXiccMass, axisBDTScore}); + histos.add("BDT/hDCAXicDaughters", "hDCAXicDaughters", kTH2D, {{axisBDTScore, axisDcaDaughters}}); histos.add("BDT/hDCAXiccDaughters", "hDCAXiccDaughters", kTH2D, {{axisBDTScore, axisDcaDaughters}}); histos.add("BDT/hDCAxyXi", "hDCAxyXi", kTH2D, {{axisBDTScore, axisDCA}}); @@ -223,14 +253,40 @@ struct Alice3Multicharm { histos.add("BDT/hPi2cPt", "hPi2cPt", kTH2D, {{axisBDTScore, axisPt}}); histos.add("BDT/hPiccPt", "hPiccPt", kTH2D, {{axisBDTScore, axisPt}}); } + + histos.print(); } template void genericProcessXicc(TMCharmCands const& xiccCands) { for (const auto& xiccCand : xiccCands) { - int icfg = xiccCand.lutConfigId(); + const int icfg = xiccCand.lutConfigId(); histos.fill(HIST("hConfigId"), icfg); + + histos.fill(HIST("CandidateQA/hDCAXicDaughters"), xiccCand.xicDauDCA() * 1e+4); + histos.fill(HIST("CandidateQA/hDCAXiccDaughters"), xiccCand.xiccDauDCA() * 1e+4); + histos.fill(HIST("CandidateQA/hDCAxyXi"), std::fabs(xiccCand.xiDCAxy() * 1e+4)); + histos.fill(HIST("CandidateQA/hDCAzXi"), std::fabs(xiccCand.xiDCAz() * 1e+4)); + histos.fill(HIST("CandidateQA/hDCAxyXic"), std::fabs(xiccCand.xicDCAxy() * 1e+4)); + histos.fill(HIST("CandidateQA/hDCAzXic"), std::fabs(xiccCand.xicDCAz() * 1e+4)); + histos.fill(HIST("CandidateQA/hDCAxyXicc"), std::fabs(xiccCand.xiccDCAxy() * 1e+4)); + histos.fill(HIST("CandidateQA/hDCAzXicc"), std::fabs(xiccCand.xiccDCAz() * 1e+4)); + histos.fill(HIST("CandidateQA/hDecayRadiusXic"), xiccCand.xicDecayRadius2D() * 1e+4); + histos.fill(HIST("CandidateQA/hDecayRadiusXicc"), xiccCand.xiccDecayRadius2D() * 1e+4); + histos.fill(HIST("CandidateQA/hDecayDistanceFromPVXic"), xiccCand.xicDistanceFromPV() * 1e+4); + histos.fill(HIST("CandidateQA/hProperLengthXic"), xiccCand.xicProperLength() * 1e+4); + histos.fill(HIST("CandidateQA/hProperLengthXicc"), xiccCand.xiccProperLength() * 1e+4); + histos.fill(HIST("CandidateQA/hPi1cDCAxy"), xiccCand.pi1cDCAxy() * 1e+4); + histos.fill(HIST("CandidateQA/hPi1cDCAz"), xiccCand.pi1cDCAz() * 1e+4); + histos.fill(HIST("CandidateQA/hPi2cDCAxy"), xiccCand.pi2cDCAxy() * 1e+4); + histos.fill(HIST("CandidateQA/hPi2cDCAz"), xiccCand.pi2cDCAz() * 1e+4); + histos.fill(HIST("CandidateQA/hPiccDCAxy"), xiccCand.piccDCAxy() * 1e+4); + histos.fill(HIST("CandidateQA/hPiccDCAz"), xiccCand.piccDCAz() * 1e+4); + histos.fill(HIST("CandidateQA/hPi1cPt"), xiccCand.pi1cPt()); + histos.fill(HIST("CandidateQA/hPi2cPt"), xiccCand.pi2cPt()); + histos.fill(HIST("CandidateQA/hPiccPt"), xiccCand.piccPt()); + if (bdt.enableML) { std::vector inputFeatures{ xiccCand.xicDauDCA(), @@ -254,35 +310,42 @@ struct Alice3Multicharm { xiccCand.xiccProperLength()}; float* probabilityMCharm = bdtMCharm.evalModel(inputFeatures); - float bdtScore = probabilityMCharm[1]; - - histos.fill(HIST("BDT/hBDTScore"), bdtScore); - histos.fill(HIST("BDT/hBDTScoreVsXiccMass"), xiccCand.xiccMass(), bdtScore); - histos.fill(HIST("BDT/hBDTScoreVsXiccPt"), xiccCand.xiccPt(), bdtScore); - histos.fill(HIST("BDT/h3dBDTScore"), xiccCand.xiccPt(), xiccCand.xiccMass(), bdtScore); - - histos.fill(HIST("BDT/hDCAXicDaughters"), bdtScore, xiccCand.xicDauDCA() * 1e+4); - histos.fill(HIST("BDT/hDCAXiccDaughters"), bdtScore, xiccCand.xiccDauDCA() * 1e+4); - histos.fill(HIST("BDT/hDCAxyXi"), bdtScore, std::fabs(xiccCand.xiDCAxy() * 1e+4)); - histos.fill(HIST("BDT/hDCAzXi"), bdtScore, std::fabs(xiccCand.xiDCAz() * 1e+4)); - histos.fill(HIST("BDT/hDCAxyXic"), bdtScore, std::fabs(xiccCand.xicDCAxy() * 1e+4)); - histos.fill(HIST("BDT/hDCAzXic"), bdtScore, std::fabs(xiccCand.xicDCAz() * 1e+4)); - histos.fill(HIST("BDT/hDCAxyXicc"), bdtScore, std::fabs(xiccCand.xiccDCAxy() * 1e+4)); - histos.fill(HIST("BDT/hDCAzXicc"), bdtScore, std::fabs(xiccCand.xiccDCAz() * 1e+4)); - histos.fill(HIST("BDT/hDecayRadiusXic"), bdtScore, xiccCand.xicDecayRadius2D() * 1e+4); - histos.fill(HIST("BDT/hDecayRadiusXicc"), bdtScore, xiccCand.xiccDecayRadius2D() * 1e+4); - histos.fill(HIST("BDT/hDecayDistanceFromPVXic"), bdtScore, xiccCand.xicDistanceFromPV() * 1e+4); - histos.fill(HIST("BDT/hProperLengthXic"), bdtScore, xiccCand.xicProperLength() * 1e+4); - histos.fill(HIST("BDT/hProperLengthXicc"), bdtScore, xiccCand.xiccProperLength() * 1e+4); - histos.fill(HIST("BDT/hPi1cDCAxy"), bdtScore, xiccCand.pi1cDCAxy() * 1e+4); - histos.fill(HIST("BDT/hPi1cDCAz"), bdtScore, xiccCand.pi1cDCAz() * 1e+4); - histos.fill(HIST("BDT/hPi2cDCAxy"), bdtScore, xiccCand.pi2cDCAxy() * 1e+4); - histos.fill(HIST("BDT/hPi2cDCAz"), bdtScore, xiccCand.pi2cDCAz() * 1e+4); - histos.fill(HIST("BDT/hPiccDCAxy"), bdtScore, xiccCand.piccDCAxy() * 1e+4); - histos.fill(HIST("BDT/hPiccDCAz"), bdtScore, xiccCand.piccDCAz() * 1e+4); - histos.fill(HIST("BDT/hPi1cPt"), bdtScore, xiccCand.pi1cPt()); - histos.fill(HIST("BDT/hPi2cPt"), bdtScore, xiccCand.pi2cPt()); - histos.fill(HIST("BDT/hPiccPt"), bdtScore, xiccCand.piccPt()); + const float bdtPredictedBackground = probabilityMCharm[0]; + const float bdtPredictedSignal = probabilityMCharm[1]; + + histos.fill(HIST("BDT/hBDTScoreSignal"), bdtPredictedSignal); + histos.fill(HIST("BDT/hBDTScoreSignalFine"), bdtPredictedSignal); + histos.fill(HIST("BDT/hBDTScoreVsXiccMassSignal"), xiccCand.xiccMass(), bdtPredictedSignal); + histos.fill(HIST("BDT/hBDTScoreVsXiccPtSignal"), xiccCand.xiccPt(), bdtPredictedSignal); + histos.fill(HIST("BDT/h3dBDTScoreSignal"), xiccCand.xiccPt(), xiccCand.xiccMass(), bdtPredictedSignal); + histos.fill(HIST("BDT/hBDTScoreBackground"), bdtPredictedBackground); + histos.fill(HIST("BDT/hBDTScoreBackgroundFine"), bdtPredictedBackground); + histos.fill(HIST("BDT/hBDTScoreVsXiccMassBackground"), xiccCand.xiccMass(), bdtPredictedBackground); + histos.fill(HIST("BDT/hBDTScoreVsXiccPtBackground"), xiccCand.xiccPt(), bdtPredictedBackground); + histos.fill(HIST("BDT/h3dBDTScoreBackground"), xiccCand.xiccPt(), xiccCand.xiccMass(), bdtPredictedBackground); + + histos.fill(HIST("BDT/hDCAXicDaughters"), bdtPredictedSignal, xiccCand.xicDauDCA() * 1e+4); + histos.fill(HIST("BDT/hDCAXiccDaughters"), bdtPredictedSignal, xiccCand.xiccDauDCA() * 1e+4); + histos.fill(HIST("BDT/hDCAxyXi"), bdtPredictedSignal, std::fabs(xiccCand.xiDCAxy() * 1e+4)); + histos.fill(HIST("BDT/hDCAzXi"), bdtPredictedSignal, std::fabs(xiccCand.xiDCAz() * 1e+4)); + histos.fill(HIST("BDT/hDCAxyXic"), bdtPredictedSignal, std::fabs(xiccCand.xicDCAxy() * 1e+4)); + histos.fill(HIST("BDT/hDCAzXic"), bdtPredictedSignal, std::fabs(xiccCand.xicDCAz() * 1e+4)); + histos.fill(HIST("BDT/hDCAxyXicc"), bdtPredictedSignal, std::fabs(xiccCand.xiccDCAxy() * 1e+4)); + histos.fill(HIST("BDT/hDCAzXicc"), bdtPredictedSignal, std::fabs(xiccCand.xiccDCAz() * 1e+4)); + histos.fill(HIST("BDT/hDecayRadiusXic"), bdtPredictedSignal, xiccCand.xicDecayRadius2D() * 1e+4); + histos.fill(HIST("BDT/hDecayRadiusXicc"), bdtPredictedSignal, xiccCand.xiccDecayRadius2D() * 1e+4); + histos.fill(HIST("BDT/hDecayDistanceFromPVXic"), bdtPredictedSignal, xiccCand.xicDistanceFromPV() * 1e+4); + histos.fill(HIST("BDT/hProperLengthXic"), bdtPredictedSignal, xiccCand.xicProperLength() * 1e+4); + histos.fill(HIST("BDT/hProperLengthXicc"), bdtPredictedSignal, xiccCand.xiccProperLength() * 1e+4); + histos.fill(HIST("BDT/hPi1cDCAxy"), bdtPredictedSignal, xiccCand.pi1cDCAxy() * 1e+4); + histos.fill(HIST("BDT/hPi1cDCAz"), bdtPredictedSignal, xiccCand.pi1cDCAz() * 1e+4); + histos.fill(HIST("BDT/hPi2cDCAxy"), bdtPredictedSignal, xiccCand.pi2cDCAxy() * 1e+4); + histos.fill(HIST("BDT/hPi2cDCAz"), bdtPredictedSignal, xiccCand.pi2cDCAz() * 1e+4); + histos.fill(HIST("BDT/hPiccDCAxy"), bdtPredictedSignal, xiccCand.piccDCAxy() * 1e+4); + histos.fill(HIST("BDT/hPiccDCAz"), bdtPredictedSignal, xiccCand.piccDCAz() * 1e+4); + histos.fill(HIST("BDT/hPi1cPt"), bdtPredictedSignal, xiccCand.pi1cPt()); + histos.fill(HIST("BDT/hPi2cPt"), bdtPredictedSignal, xiccCand.pi2cPt()); + histos.fill(HIST("BDT/hPiccPt"), bdtPredictedSignal, xiccCand.piccPt()); } histos.fill(HIST("hMCharmBuilding"), 0); From c0e588b2fc68546258c7789ba38df03c4a71c01a Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 21 May 2026 18:42:06 +0200 Subject: [PATCH 256/449] [PWGEM/Dilepton] update taggingHFE (#16341) --- PWGEM/Dilepton/Utils/ElectronModule.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index b4b65f9beb5..d1283127ca8 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -189,17 +189,17 @@ struct hadronCut : o2::framework::ConfigurableGroup { o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3, "min n sigma pi in TPC"}; o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3, "max n sigma pi in TPC"}; - o2::framework::Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; - o2::framework::Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; + // o2::framework::Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -3, "min n sigma pi in TOF"}; + // o2::framework::Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +3, "max n sigma pi in TOF"}; o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3, "min n sigma ka in TPC"}; o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; - o2::framework::Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; - o2::framework::Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; - o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; - o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; - o2::framework::Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; - o2::framework::Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; - o2::framework::Configurable requirePiKaPr{"requirePiKaPr", true, "require hadron to be pion or kaon or proton"}; + // o2::framework::Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; + // o2::framework::Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; + // o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + // o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + // // o2::framework::Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + // // o2::framework::Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + o2::framework::Configurable requirePiKa{"requirePiKa", true, "require hadron to be pion or kaon"}; // protons are not involved in semileptonic decays of HF hadrons. }; struct v0Cut : o2::framework::ConfigurableGroup { @@ -1031,7 +1031,7 @@ class ElectronModule return false; } - if (fHadronCut.requirePiKaPr && !isPiKaPr(track)) { + if (fHadronCut.requirePiKa && !isPiKa(track)) { return false; } @@ -1154,12 +1154,12 @@ class ElectronModule } template - bool isPiKaPr(TTrack const& track) + bool isPiKa(TTrack const& track) { bool is_pi_included_TPC = fHadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < fHadronCut.cfg_max_TPCNsigmaPi; bool is_ka_included_TPC = fHadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < fHadronCut.cfg_max_TPCNsigmaKa; - bool is_pr_included_TPC = fHadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < fHadronCut.cfg_max_TPCNsigmaPr; - return is_pi_included_TPC || is_ka_included_TPC || is_pr_included_TPC; + // bool is_pr_included_TPC = fHadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < fHadronCut.cfg_max_TPCNsigmaPr; + return is_pi_included_TPC || is_ka_included_TPC; } template From ea1cf8845d9556cb98ab5fa2f7ebf43fc6903cb9 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Thu, 21 May 2026 22:40:30 +0200 Subject: [PATCH 257/449] [PWGCF] small fixes in V0 & cascade histograms (#16344) --- PWGCF/Femto/Core/cascadeHistManager.h | 39 +++++++++++++++++---------- PWGCF/Femto/Core/v0HistManager.h | 13 ++++++--- PWGCF/Femto/Tasks/femtoV0Qa.cxx | 4 +-- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeHistManager.h b/PWGCF/Femto/Core/cascadeHistManager.h index 9ee370b5c22..5180f60856e 100644 --- a/PWGCF/Femto/Core/cascadeHistManager.h +++ b/PWGCF/Femto/Core/cascadeHistManager.h @@ -48,6 +48,7 @@ enum CascadeHist { kPhi, kMass, kSign, + kPtVsMass, // nice to have during analysis // qa variables kMassXi, kMassOmega, @@ -109,6 +110,8 @@ template struct ConfCascadeQaBinning : o2::framework::ConfigurableGroup { std::string prefix = Prefix; o2::framework::Configurable plot2d{"plot2d", true, "Enable 2d Qa histograms"}; + o2::framework::Configurable plotOrigins{"plotOrigins", true, "MC ONLY: Plot pt vs cosPa for different particle origins"}; + o2::framework::Configurable> pdgCodesForMothersOfSecondary{"pdgCodesForMothersOfSecondary", {3312, 3334}, "MC ONLY: PDG codes of mothers of secondaries (Max 3 will be considered)"}; o2::framework::ConfigurableAxis cosPa{"cosPa", {{100, 0.9, 1}}, "Cosine of poiting angle"}; o2::framework::ConfigurableAxis dauDcaAtDecay{"dauDcaAtDecay", {{150, 0, 1.5}}, "Daughter DCA at decay vertex"}; o2::framework::ConfigurableAxis transRadius{"transRadius", {{100, 0, 100}}, "Transverse radius"}; @@ -123,8 +126,8 @@ struct ConfCascadeQaBinning : o2::framework::ConfigurableGroup { constexpr const char PrefixXiQaBinning[] = "XiQaBinning"; using ConfXiQaBinning = ConfCascadeQaBinning; -constexpr const char PrefixOmegatQaBinning[] = "OmegaQaBinning"; -using ConfOmegaQaBinning = ConfCascadeQaBinning; +constexpr const char PrefixOmegaQaBinning[] = "OmegaQaBinning"; +using ConfOmegaQaBinning = ConfCascadeQaBinning; // must be in sync with enum TrackVariables // the enum gives the correct index in the array @@ -134,6 +137,7 @@ constexpr std::array, kCascadeHistLast> HistT {kPhi, o2::framework::HistType::kTH1F, "hPhi", "Azimuthal angle; #varphi; Entries"}, {kMass, o2::framework::HistType::kTH1F, "hMass", "Invariant Mass; m_{Inv} (GeV/#it{c}^{2}); Entries"}, {kSign, o2::framework::HistType::kTH1F, "hSign", "Sign (-1 -> antiparticle, 0 -> self conjugate, +1 -> particle); sign; Entries"}, + {kPtVsMass, o2::framework::HistType::kTH2F, "hPtVsMass", "Transverse momentum vs invariant mass; p_{T} (GeV/#it{c}); m_{Inv} (GeV/#it{c}^{2})"}, {kMassXi, o2::framework::HistType::kTH1F, "hMassXi", "Mass #Xi; m_{#Lambda#pi} (GeV/#it{c}^{2}); Entries"}, {kMassOmega, o2::framework::HistType::kTH1F, "hMassOmega", "mass #Omega; m_{#LambdaK} (GeV/#it{c}^{2}); Entries"}, {kCosPa, o2::framework::HistType::kTH1F, "hCosPa", "Cosine of pointing angle; cos(#alpha); Entries"}, @@ -163,9 +167,9 @@ constexpr std::array, kCascadeHistLast> HistT {kFromMaterial, o2::framework::HistType::kTH2F, "hFromMaterial", "Particles from material; p_{T} (GeV/#it{c}); cos(#alpha)"}, {kMissidentified, o2::framework::HistType::kTH2F, "hMissidentified", "Missidentified particles (fake/wrong PDG code); p_{T} (GeV/#it{c}); cos(#alpha)"}, {kSecondary1, o2::framework::HistType::kTH2F, "hFromSecondary1", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondary2, o2::framework::HistType::kTH2F, "hFromSecondary2", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondary3, o2::framework::HistType::kTH2F, "hFromSecondary3", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondaryOther, o2::framework::HistType::kTH2F, "hFromSecondaryOther", "Particles from every other seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}}, + {kSecondary2, o2::framework::HistType::kTH2F, "hFromSecondary2", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondary3, o2::framework::HistType::kTH2F, "hFromSecondary3", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondaryOther, o2::framework::HistType::kTH2F, "hFromSecondaryOther", "Particles from every other secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}}, }; #define CASCADE_HIST_ANALYSIS_MAP(conf) \ @@ -173,7 +177,8 @@ constexpr std::array, kCascadeHistLast> HistT {kEta, {conf.eta}}, \ {kPhi, {conf.phi}}, \ {kMass, {conf.mass}}, \ - {kSign, {conf.sign}}, + {kSign, {conf.sign}}, \ + {kPtVsMass, {conf.pt, conf.mass}}, #define CASCADE_HIST_MC_MAP(conf) \ {kTruePtVsPt, {conf.pt, conf.pt}}, \ @@ -184,12 +189,7 @@ constexpr std::array, kCascadeHistLast> HistT {kPdgPartonicMother, {conf.pdgCodes}}, #define CASCADE_HIST_QA_MAP(confAnalysis, confQa) \ - {kPt, {confAnalysis.pt}}, \ - {kEta, {confAnalysis.eta}}, \ - {kPhi, {confAnalysis.phi}}, \ - {kMass, {confAnalysis.mass}}, \ - {kSign, {confAnalysis.sign}}, \ - {kCosPa, {confQa.cosPa}}, \ + {kCosPa, {confQa.cosPa}}, \ {kDecayDauDca, {confQa.dauDcaAtDecay}}, \ {kTransRadius, {confQa.transRadius}}, \ {kLambdaCosPa, {confQa.lambdaCosPa}}, \ @@ -349,9 +349,9 @@ class CascadeHistManager std::map> const& BachelorSpecs, T3 const& ConfBachelorQaBinning, std::map> const& PosDauSpecs, - T4& ConfPosDauQaBinning, + T4 const& ConfPosDauQaBinning, std::map> const& NegDauSpecs, - T5& ConfNegDauQaBinning) + T5 const& ConfNegDauQaBinning) { mHistogramRegistry = registry; mPdgCode = std::abs(ConfCascadeSelection.pdgCodeAbs.value); @@ -454,6 +454,15 @@ class CascadeHistManager void enableOptionalHistograms(T const& CascadeConfBinningQa) { mPlot2d = CascadeConfBinningQa.plot2d.value; + mPlotOrigins = CascadeConfBinningQa.plotOrigins.value; + mPlotNSecondaries = CascadeConfBinningQa.pdgCodesForMothersOfSecondary.value.size(); + for (std::size_t i = 0; i < MaxSecondary; i++) { + if (i < CascadeConfBinningQa.pdgCodesForMothersOfSecondary.value.size()) { + mPdgCodesSecondaryMother.at(i) = std::abs(CascadeConfBinningQa.pdgCodesForMothersOfSecondary.value.at(i)); + } else { + mPdgCodesSecondaryMother.at(i) = 0; + } + } } void initAnalysis(std::map> const& cascadeSpecs) @@ -464,6 +473,7 @@ class CascadeHistManager mHistogramRegistry->add(analysisDir + getHistNameV2(kPhi, HistTable), getHistDesc(kPhi, HistTable), getHistType(kPhi, HistTable), {cascadeSpecs.at(kPhi)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kMass, HistTable), getHistDesc(kMass, HistTable), getHistType(kMass, HistTable), {cascadeSpecs.at(kMass)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kSign, HistTable), getHistDesc(kSign, HistTable), getHistType(kSign, HistTable), {cascadeSpecs.at(kSign)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kPtVsMass, HistTable), getHistDesc(kPtVsMass, HistTable), getHistType(kPtVsMass, HistTable), {cascadeSpecs.at(kPtVsMass)}); } void initQa(std::map> const& cascadeSpecs) @@ -540,6 +550,7 @@ class CascadeHistManager mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(AnalysisDir) + HIST(getHistName(kPhi, HistTable)), cascadeCandidate.phi()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(AnalysisDir) + HIST(getHistName(kMass, HistTable)), cascadeCandidate.mass()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(AnalysisDir) + HIST(getHistName(kSign, HistTable)), cascadeCandidate.sign()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(AnalysisDir) + HIST(getHistName(kPtVsMass, HistTable)), cascadeCandidate.pt(), cascadeCandidate.mass()); } template diff --git a/PWGCF/Femto/Core/v0HistManager.h b/PWGCF/Femto/Core/v0HistManager.h index 3b9faba0a70..cdb87a09e8d 100644 --- a/PWGCF/Femto/Core/v0HistManager.h +++ b/PWGCF/Femto/Core/v0HistManager.h @@ -48,6 +48,7 @@ enum V0Hist { kPhi, kMass, kSign, + kPtVsMass, // nice to have during analysis // qa variables kMassLambda, kMassAntiLambda, @@ -148,6 +149,7 @@ constexpr std::array, kV0HistLast> HistTable = { {kPhi, o2::framework::HistType::kTH1F, "hPhi", "Azimuthal angle; #varphi; Entries"}, {kMass, o2::framework::HistType::kTH1F, "hMass", "Invariant Mass; m_{Inv} (GeV/#it{c}^{2}); Entries"}, {kSign, o2::framework::HistType::kTH1F, "hSign", "Sign (-1 -> antiparticle, 0 -> self conjugate, +1 -> particle); sign; Entries"}, + {kPtVsMass, o2::framework::HistType::kTH2F, "hPtVsMass", "Transverse momentum vs invariant mass; p_{T} (GeV/#it{c}); m_{Inv} (GeV/#it{c}^{2})"}, {kMassLambda, o2::framework::HistType::kTH1F, "hMassLambda", "#Lambda mass; m_{p#pi^{-}} (GeV/#it{c}^{2}); Entries"}, {kMassAntiLambda, o2::framework::HistType::kTH1F, "hMassAntiLambda", "#bar{#Lambda} mass; m_{#bar{p}#pi^{+}} (GeV/#it{c}^{2}); Entries"}, {kMassK0short, o2::framework::HistType::kTH1F, "hMassK0short", "K^{0}_{s} mass; m_{#pi^{+}#pi^{-}} (GeV/#it{c}^{2}); Entries"}, @@ -181,9 +183,9 @@ constexpr std::array, kV0HistLast> HistTable = { {kFromMaterial, o2::framework::HistType::kTH2F, "hFromMaterial", "Particles from material; p_{T} (GeV/#it{c}); cos(#alpha)"}, {kMissidentified, o2::framework::HistType::kTH2F, "hMissidentified", "Missidentified particles (fake/wrong PDG code); p_{T} (GeV/#it{c}); cos(#alpha)"}, {kSecondary1, o2::framework::HistType::kTH2F, "hFromSecondary1", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondary2, o2::framework::HistType::kTH2F, "hFromSecondary2", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondary3, o2::framework::HistType::kTH2F, "hFromSecondary3", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, - {kSecondaryOther, o2::framework::HistType::kTH2F, "hFromSecondaryOther", "Particles from every other seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}}, + {kSecondary2, o2::framework::HistType::kTH2F, "hFromSecondary2", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondary3, o2::framework::HistType::kTH2F, "hFromSecondary3", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondaryOther, o2::framework::HistType::kTH2F, "hFromSecondaryOther", "Particles from every other secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}}, }; #define V0_HIST_ANALYSIS_MAP(conf) \ @@ -191,7 +193,8 @@ constexpr std::array, kV0HistLast> HistTable = { {kEta, {conf.eta}}, \ {kPhi, {conf.phi}}, \ {kMass, {conf.mass}}, \ - {kSign, {conf.sign}}, + {kSign, {conf.sign}}, \ + {kPtVsMass, {conf.pt, conf.mass}}, #define V0_HIST_MC_MAP(conf) \ {kTruePtVsPt, {conf.pt, conf.pt}}, \ @@ -451,6 +454,7 @@ class V0HistManager mHistogramRegistry->add(analysisDir + getHistNameV2(kPhi, HistTable), getHistDesc(kPhi, HistTable), getHistType(kPhi, HistTable), {V0Specs.at(kPhi)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kMass, HistTable), getHistDesc(kMass, HistTable), getHistType(kMass, HistTable), {V0Specs.at(kMass)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kSign, HistTable), getHistDesc(kSign, HistTable), getHistType(kSign, HistTable), {V0Specs.at(kSign)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kPtVsMass, HistTable), getHistDesc(kPtVsMass, HistTable), getHistType(kPtVsMass, HistTable), {V0Specs.at(kPtVsMass)}); } void initQa(std::map> const& V0Specs) @@ -531,6 +535,7 @@ class V0HistManager mHistogramRegistry->fill(HIST(v0Prefix) + HIST(AnalysisDir) + HIST(getHistName(kEta, HistTable)), v0candidate.eta()); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(AnalysisDir) + HIST(getHistName(kPhi, HistTable)), v0candidate.phi()); mHistogramRegistry->fill(HIST(v0Prefix) + HIST(AnalysisDir) + HIST(getHistName(kMass, HistTable)), v0candidate.mass()); + mHistogramRegistry->fill(HIST(v0Prefix) + HIST(AnalysisDir) + HIST(getHistName(kPtVsMass, HistTable)), v0candidate.pt(), v0candidate.mass()); if constexpr (modes::isEqual(v0, modes::V0::kLambda) || modes::isEqual(v0, modes::V0::kAntiLambda)) { mHistogramRegistry->fill(HIST(v0Prefix) + HIST(AnalysisDir) + HIST(getHistName(kSign, HistTable)), v0candidate.sign()); diff --git a/PWGCF/Femto/Tasks/femtoV0Qa.cxx b/PWGCF/Femto/Tasks/femtoV0Qa.cxx index a8bf0fa91e5..9d8af3870bd 100644 --- a/PWGCF/Femto/Tasks/femtoV0Qa.cxx +++ b/PWGCF/Femto/Tasks/femtoV0Qa.cxx @@ -120,7 +120,7 @@ struct FemtoV0Qa { void init(o2::framework::InitContext&) { - if ((doprocessLambda + doprocessLambdaMc + doprocessK0short + doprocessK0shortMc) > 1) { + if ((doprocessLambda + doprocessLambdaMc + doprocessK0short + doprocessK0shortMc) != 1) { LOG(fatal) << "Only one process can be activated"; } bool processData = doprocessLambda || doprocessK0short; @@ -220,7 +220,7 @@ struct FemtoV0Qa { lambdaHistManager.fill(lambda, tracks, mcParticles, mcMothers, mcPartonicMothers); } } - PROCESS_SWITCH(FemtoV0Qa, processLambdaMc, "Process lambdas", false); + PROCESS_SWITCH(FemtoV0Qa, processLambdaMc, "Process lambdas with MC informaton", false); }; o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) From 96f2f791a5bae72cbe3eb631621b6444cc9ffd9b Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Fri, 22 May 2026 12:48:03 +0530 Subject: [PATCH 258/449] [PWGLF] Removed tpc crossed rows and tpc crfc conditions (#16315) --- .../Tasks/Resonances/higherMassResonances.cxx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index cdbdb01934d..0e7e636e4a6 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -177,8 +177,8 @@ struct HigherMassResonances { // Other cuts on Ks and glueball Configurable isapplyCompetingcut{"isapplyCompetingcut", false, "Competing cascade rejection cut"}; Configurable competingcascrejlambda{"competingcascrejlambda", 0.005, "rejecting competing cascade lambda"}; - Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; - Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; + // Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; + // Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; // // Mass and pT axis as configurables @@ -664,12 +664,12 @@ struct HigherMassResonances { return false; rEventSelection.fill(HIST("htrackscheck_v0_daughters"), 1.5); - if (track.tpcNClsCrossedRows() < config.tpcCrossedrows) - return false; + // if (track.tpcNClsCrossedRows() < config.tpcCrossedrows) + // return false; rEventSelection.fill(HIST("htrackscheck_v0_daughters"), 2.5); - if (track.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls) - return false; + // if (track.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls) + // return false; rEventSelection.fill(HIST("htrackscheck_v0_daughters"), 3.5); if (tpcNClsF < config.confDaughTPCnclsMin) { @@ -743,16 +743,16 @@ struct HigherMassResonances { return false; } - if (posTrackExtra.tpcNClsCrossedRows() < config.tpcCrossedrows || negTrackExtra.tpcNClsCrossedRows() < config.tpcCrossedrows) { - return false; - } + // if (posTrackExtra.tpcNClsCrossedRows() < config.tpcCrossedrows || negTrackExtra.tpcNClsCrossedRows() < config.tpcCrossedrows) { + // return false; + // } if (posTrackExtra.tpcNClsFound() < config.confDaughTPCnclsMin || negTrackExtra.tpcNClsFound() < config.confDaughTPCnclsMin) { return false; } - if (posTrackExtra.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls || negTrackExtra.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls) { - return false; - } + // if (posTrackExtra.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls || negTrackExtra.tpcCrossedRowsOverFindableCls() < config.tpcCrossedrowsOverfcls) { + // return false; + // } // check TPC PID if (((std::abs(posTrackExtra.tpcNSigmaPi()) > config.confDaughPIDCutTPC) || (std::abs(negTrackExtra.tpcNSigmaPi()) > config.confDaughPIDCutTPC))) { From 0b02ed24fde49df5cc16bca8273984caf701ee51 Mon Sep 17 00:00:00 2001 From: lgansbartl Date: Fri, 22 May 2026 09:46:57 +0200 Subject: [PATCH 259/449] [PWGEM/PhotonMeson] Include check for gamma gamma contamination in Dalitz decays (#16338) Co-authored-by: Laura Gansbartl --- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 2464ec82ec2..01a81068d43 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -92,6 +93,7 @@ struct Pi0EtaToGammaGammaMC { o2::framework::Configurable cfgAlphaMeson{"cfgAlphaMeson", 0.65, "photon energy asymmetry distribution parameter for specific value cut"}; o2::framework::Configurable cfgAlphaMesonA{"cfgAlphaMesonA", 0.65, "photon energy asymmetry distribution parameter A for pT dependent cut (A * tanh(B*pT))"}; o2::framework::Configurable cfgAlphaMesonB{"cfgAlphaMesonB", 1.2, "photon energy asymmetry distribution parameter B for pT dependent cut (A * tanh(B*pT))"}; + o2::framework::Configurable cfgGGContaCheck{"cfgGGContaCheck", false, "check gamma gamma contamination of dalitz"}; EMPhotonEventCut fEMEventCut; struct : o2::framework::ConfigurableGroup { @@ -252,6 +254,12 @@ struct Pi0EtaToGammaGammaMC { f1fd_k0s_to_pi0 = new TF1("f1fd_k0s_to_pi0", TString(fd_k0s_to_pi0), 0.f, 100.f); fRegistry.add("Event/hNrecPerMCCollision", "Nrec per mc collision;N_{rec} collisions per MC collision", o2::framework::HistType::kTH1F, {{21, -0.5f, 20.5f}}, false); + if (cfgGGContaCheck) { + fRegistry.add("Event/hNGGContamEta", "Number of Eta from etaToGammaGamma; p_{T, #eta} (GeV/#it{c}); N", o2::framework::HistType::kTH1F, {{40, -0.5f, 20.5f}}, false); + fRegistry.add("Event/hNGGContamPion", "Number of Pion from etaToGammaGamma; p_{T, #pi} (GeV/#it{c}); N", o2::framework::HistType::kTH1F, {{40, -0.5f, 20.5f}}, false); + } + fRegistry.add("Event/hNDalitzEtaPt", "Number of DalitzEta; p_{T, #eta} (GeV/#it{c}); N", o2::framework::HistType::kTH1F, {{40, -0.5f, 20.5f}}, false); + fRegistry.add("Event/hNDalitzPionPt", "Number of DalitzPion; p_{T, #pi} (GeV/#it{c}) ; N", o2::framework::HistType::kTH1F, {{40, -0.5f, 20.5f}}, false); mRunNumber = 0; d_bz = 0; @@ -720,9 +728,9 @@ struct Pi0EtaToGammaGammaMC { } if (g1mc.globalIndex() == g2mc.globalIndex()) { - if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 111) + if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == PDG_t::kPi0) fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); - else if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 221) + else if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == o2::constants::physics::Pdg::kEta) fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); continue; } @@ -792,6 +800,25 @@ struct Pi0EtaToGammaGammaMC { auto pos2mc = mcparticles.iteratorAt(pos2.emmcparticleId()); auto ele2mc = mcparticles.iteratorAt(ele2.emmcparticleId()); + if (cfgGGContaCheck) { + photonid2 = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); // check possible contamination + if (photonid2 > 0) { + auto photon2 = mcparticles.iteratorAt(photonid2); + int photon2pdg = photon2.pdgCode(); + int photon2mothid = photon2.mothersIds()[0]; + auto photon2moth = mcparticles.iteratorAt(photon2mothid); + if (photon2pdg == PDG_t::kGamma && (o2::aod::pwgem::photonmeson::utils::mcutil::isGammaGammaDecay(photon2moth, mcparticles))) { + int mothID = o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(photon2, mcparticles); + if (mothID == o2::constants::physics::Pdg::kEta) { + fRegistry.fill(HIST("Event/hNGGContamEta"), photon2moth.pt()); + } + if (mothID == PDG_t::kPi0) { + fRegistry.fill(HIST("Event/hNGGContamPion"), photon2moth.pt()); + } + } + } + } + pi0id = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 111, mcparticles); etaid = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 221, mcparticles); if (pi0id < 0 && etaid < 0) { @@ -805,12 +832,14 @@ struct Pi0EtaToGammaGammaMC { } if (pi0id > 0) { auto pi0mc = mcparticles.iteratorAt(pi0id); + fRegistry.fill(HIST("Event/hNDalitzPionPt"), pi0mc.pt()); if (cfgRequireTrueAssociation && (pi0mc.emmceventId() != collision.emmceventId())) { continue; } o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); + fRegistry.fill(HIST("Event/hNDalitzEtaPt"), etamc.pt()); if (cfgRequireTrueAssociation && (etamc.emmceventId() != collision.emmceventId())) { continue; } From 6b87cfc887ea40ddbf97f0546052d8606e47f0f4 Mon Sep 17 00:00:00 2001 From: blacwovie Date: Fri, 22 May 2026 16:36:25 +0800 Subject: [PATCH 260/449] [PWGCF] add CPR switch (#16345) Co-authored-by: ALICE Action Bot --- .../TableProducer/HadNucleiFemto.cxx | 109 +++++++++++++++++- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index 88540514c26..c132ac4c3bf 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -83,6 +83,7 @@ namespace { constexpr double betheBlochDefault[1][6]{{-136.71, 0.441, 0.2269, 1.347, 0.8035, 0.09}}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; +static constexpr std::array tmpRadiiTPC{{85.f, 105.f, 125.f, 145.f, 165.f, 185.f, 205.f, 225.f, 245.f}}; enum Selections { kNoCuts = 0, @@ -189,6 +190,8 @@ struct HadNucleiFemto { Configurable settingCutNsigTOFPrMin{"settingCutNsigTOFPrMin", 3.0f, "Minimum TOF Pr Nsigma cut for rejection"}; Configurable settingCutNsigTOFPiMin{"settingCutNsigTOFPiMin", 3.0f, "Minimum TOF Pi Nsigma cut for rejection"}; Configurable settingCutNsigTOFKaMin{"settingCutNsigTOFKaMin", 3.0f, "Minimum TOF Ka Nsigma cut for rejection"}; + Configurable settingEnablePionProtonRejection{"settingEnablePionProtonRejection", true, "If true, apply proton rejection in the pion PID"}; + Configurable settingEnablePionKaonRejection{"settingEnablePionKaonRejection", true, "If true, apply kaon rejection in the pion PID"}; Configurable settingUsePionReferencePIDCuts{"settingUsePionReferencePIDCuts", false, "If true, use the reference pion track/PID cuts from the pi-p study"}; // Deuteron purity and PID cuts Configurable settingCutPinMinDe{"settingCutPinMinDe", 0.0f, "Minimum Pin for De"}; @@ -199,6 +202,12 @@ struct HadNucleiFemto { Configurable settingCutNsigmaTPCDe{"settingCutNsigmaTPCDe", 2.5f, "Value of the TPC Nsigma cut on De"}; Configurable settingCutNsigmaITSDe{"settingCutNsigmaITSDe", 2.5f, "Value of the ITD Nsigma cut on De"}; Configurable settingCutNsigmaTOFTPCDe{"settingCutNsigmaTOFTPCDe", 2.5f, "Value of the De TOF TPC combNsigma cut"}; + Configurable settingUseProtonMassForKstarMt{"settingUseProtonMassForKstarMt", false, "If true, use proton mass instead of deuteron mass for kstar and mT"}; + Configurable settingEnableClosePairRejection{"settingEnableClosePairRejection", false, "Enable close pair rejection for deuteron-hadron track pairs"}; + Configurable settingClosePairDeltaPhiMax{"settingClosePairDeltaPhiMax", 0.01f, "Maximum delta phi star for close pair rejection"}; + Configurable settingClosePairDeltaEtaMax{"settingClosePairDeltaEtaMax", 0.01f, "Maximum delta eta for close pair rejection"}; + Configurable settingClosePairRadiusMode{"settingClosePairRadiusMode", 1, "Close pair rejection mode: 0 = PV, 1 = average phi star, 2 = specific TPC radius"}; + Configurable settingClosePairSpecificRadius{"settingClosePairSpecificRadius", 85.f, "TPC radius in cm used when close pair rejection mode is 2"}; // Hypertriton-specific cuts Configurable settingCutTPCChi2He{"settingCutTPCChi2He", 0.0f, "Minimum tpcChi2He for Hyper He3"}; Configurable settingCutAverClsSizeHe{"settingCutAverClsSizeHe", 0.0f, "Minimum averClusSizeHe for Hyper He3"}; @@ -278,6 +287,8 @@ struct HadNucleiFemto { {"hHadPin", "P distribution; #it{p} (GeV/#it{c})", {HistType::kTH1F, {{120, -4.0f, 4.0f}}}}, {"hHadEta", "eta distribution; #eta(had)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, {"hHadPhi", "phi distribution; phi(had)", {HistType::kTH1F, {{600, -4.0f, 4.0f}}}}, + {"h2CPRBefore", "Close pair rejection before cut; #Delta#eta; #Delta#phi^{*}", {HistType::kTH2F, {{160, -2.0f, 2.0f}, {160, -3.2f, 3.2f}}}}, + {"h2CPRAfter", "Close pair rejection after cut; #Delta#eta; #Delta#phi^{*}", {HistType::kTH2F, {{160, -2.0f, 2.0f}, {160, -3.2f, 3.2f}}}}, // dE/dx {"h2dEdxNucandidates", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, @@ -602,6 +613,85 @@ struct HadNucleiFemto { return true; } + template + float phiAtSpecificRadiiTPC(const Ttrack& track, float radius) const + { + const float absPt = std::abs(track.pt()); + if (absPt <= 0.f) { + return 999.f; + } + const float arg = 0.3f * static_cast(track.sign()) * 0.1f * mDbz * radius * 0.01f / (2.f * absPt); + if (std::fabs(arg) >= 1.f) { + return 999.f; + } + return track.phi() - std::asin(arg); + } + + float wrapDeltaPhi(float dphi) const + { + return std::atan2(std::sin(dphi), std::cos(dphi)); + } + + template + float averagePhiStar(const Ttrack1& track1, const Ttrack2& track2) const + { + constexpr float invalidPhiStar = 999.f; + float dPhiAvg = 0.f; + int meaningfulEntries = 0; + for (const auto& radius : tmpRadiiTPC) { + const float phi1 = phiAtSpecificRadiiTPC(track1, radius); + const float phi2 = phiAtSpecificRadiiTPC(track2, radius); + if (phi1 == invalidPhiStar || phi2 == invalidPhiStar) { + continue; + } + dPhiAvg += wrapDeltaPhi(phi1 - phi2); + meaningfulEntries++; + } + if (meaningfulEntries == 0) { + return invalidPhiStar; + } + return dPhiAvg / static_cast(meaningfulEntries); + } + + template + bool isClosePair(const Ttrack1& track1, const Ttrack2& track2) + { + constexpr int closePairRadiusModePv = 0; + constexpr int closePairRadiusModeSpecificTpc = 2; + constexpr float invalidPhiStar = 999.f; + if (!settingEnableClosePairRejection.value) { + return false; + } + if (track1.sign() != track2.sign()) { + return false; + } + + const float deta = track1.eta() - track2.eta(); + const float dphiAtPV = wrapDeltaPhi(track1.phi() - track2.phi()); + const float dphiAtSpecificRadius = wrapDeltaPhi(phiAtSpecificRadiiTPC(track1, settingClosePairSpecificRadius.value) - phiAtSpecificRadiiTPC(track2, settingClosePairSpecificRadius.value)); + const float dphiAvg = averagePhiStar(track1, track2); + + float dphiToCut = dphiAvg; + if (settingClosePairRadiusMode.value == closePairRadiusModePv) { + dphiToCut = dphiAtPV; + } else if (settingClosePairRadiusMode.value == closePairRadiusModeSpecificTpc) { + dphiToCut = dphiAtSpecificRadius; + } + + if (dphiToCut == invalidPhiStar) { + return false; + } + + mQaRegistry.fill(HIST("h2CPRBefore"), deta, dphiToCut); + const bool isRejected = std::pow(dphiToCut, 2.f) / std::pow(settingClosePairDeltaPhiMax.value, 2.f) + + std::pow(deta, 2.f) / std::pow(settingClosePairDeltaEtaMax.value, 2.f) < + 1.f; + if (!isRejected) { + mQaRegistry.fill(HIST("h2CPRAfter"), deta, dphiToCut); + } + return isRejected; + } + template bool selectionPIDKaon(const Ttrack& candidate) { @@ -700,15 +790,15 @@ struct HadNucleiFemto { if (std::abs(candidate.pt()) < settingCutHadptMin || std::abs(candidate.pt()) > settingCutHadptMax) return false; // reject protons and kaons - if (std::abs(candidate.tpcNSigmaPr()) < settingCutNsigTPCPrMin) + if (settingEnablePionProtonRejection && std::abs(candidate.tpcNSigmaPr()) < settingCutNsigTPCPrMin) return false; - if (std::abs(candidate.tpcNSigmaKa()) < settingCutNsigTPCKaMin) + if (settingEnablePionKaonRejection && std::abs(candidate.tpcNSigmaKa()) < settingCutNsigTPCKaMin) return false; mQaRegistry.fill(HIST("h2NsigmaHadPrTPC"), candidate.tpcNSigmaPr()); mQaRegistry.fill(HIST("h2NsigmaHadKaTPC"), candidate.tpcNSigmaKa()); - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < settingCutNsigTOFPrMin) + if (settingEnablePionProtonRejection && candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < settingCutNsigTOFPrMin) return false; - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < settingCutNsigTOFKaMin) + if (settingEnablePionKaonRejection && candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < settingCutNsigTOFKaMin) return false; mQaRegistry.fill(HIST("h2NsigmaHadPrTOF"), candidate.tofNSigmaPr()); if (candidate.hasTOF()) { @@ -967,8 +1057,9 @@ struct HadNucleiFemto { hadNucand.massTOFHad = trackHad.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); } - hadNucand.kstar = o2::analysis::femtoWorld::FemtoWorldMath::getkstar(trackHad, MassHad, trackDe, o2::constants::physics::MassDeuteron); - hadNucand.mT = o2::analysis::femtoWorld::FemtoWorldMath::getmT(trackHad, MassHad, trackDe, o2::constants::physics::MassDeuteron); + const float massLightNucleusForKstarMt = settingUseProtonMassForKstarMt ? static_cast(o2::constants::physics::MassProton) : static_cast(o2::constants::physics::MassDeuteron); + hadNucand.kstar = o2::analysis::femtoWorld::FemtoWorldMath::getkstar(trackHad, MassHad, trackDe, massLightNucleusForKstarMt); + hadNucand.mT = o2::analysis::femtoWorld::FemtoWorldMath::getmT(trackHad, MassHad, trackDe, massLightNucleusForKstarMt); return true; } @@ -1075,6 +1166,9 @@ struct HadNucleiFemto { if (!selectTrackHadron(track1) || !selectionPIDHadron(track1)) { continue; } + if (isClosePair(track0, track1)) { + continue; + } SVCand trackPair; trackPair.tr0Idx = track0.globalIndex(); @@ -1130,6 +1224,9 @@ struct HadNucleiFemto { if (!selectTrackHadron(hadCand) || !selectionPIDHadron(hadCand)) { continue; } + if (isClosePair(DeCand, hadCand)) { + continue; + } SVCand trackPair; trackPair.tr0Idx = DeCand.globalIndex(); From 68b761b8bbef53d68118ad5f18dbbac36e543372 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Fri, 22 May 2026 17:53:16 +0800 Subject: [PATCH 261/449] [PWGCF] initial commit on ese-dependent directed flow (#16342) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/CMakeLists.txt | 6 + PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx | 594 ++++++++++++++++++++++ 2 files changed, 600 insertions(+) create mode 100644 PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index a7cfbe3c95f..0f5f97f64fb 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -113,3 +113,9 @@ o2physics_add_dpl_workflow(pid-flow-pt-corr SOURCES pidFlowPtCorr.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flow-gpol-ese + SOURCES flowDirectedFlowTask.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx new file mode 100644 index 00000000000..28f32417010 --- /dev/null +++ b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx @@ -0,0 +1,594 @@ +// 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. + +/// \author Junlee Kim (jikim1290@gmail.com) +/// \file flowDirectedFlowTask.cxx +/// \brief Task for q1-dependent directed flow and global polarization +/// \since May 2026 + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.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 +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; +using namespace o2::constants::physics; + +struct flowDirectedFlowTask { + Configurable cfgUrl{"cfgUrl", "http://alice-ccdb.cern.ch", "CCDB URL"}; + Configurable nolaterthan{"nolaterthan", -1, "Latest acceptable CCDB timestamp; -1 = current"}; + + Configurable cfgPVSel{"cfgPVSel", true, "flag for the primary vertex selection"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgAddEvtSelPileup{"cfgAddEvtSelPileup", true, "flag for the pilup rejection"}; + Configurable cfgMaxOccupancy{"cfgMaxOccupancy", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgMinOccupancy{"cfgMinOccupancy", 0, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + + Configurable cfgq1mode{"cfgq1mode", 0, "0: |QC-QA|, 1: |QA|, 2: |QC|, 3: 0.5*(|QA|+|QC|)"}; + + Configurable cfgUseAccCorr{"cfgUseAccCorr", true, "Use acceptance correction profile"}; + Configurable cfgAccPathL{"cfgAccPathL", "Users/p/prottay/My/Object/acccorrL", "CCDB path to Lambda acceptance correction"}; + Configurable cfgAccPathAL{"cfgAccPathAL", "Users/p/prottay/My/Object/acccorrAL", "CCDB path to AntiLambda acceptance correction"}; + + Configurable cfgV0PtMin{"cfgV0PtMin", 0.f, "Minimum V0 pT"}; + Configurable cfgV0Rap{"cfgV0Rap", 0.8f, "V0 rapidity range"}; + Configurable cfgV0DCADaughMax{"cfgV0DCADaughMax", 0.2, "Maximum DCA between V0 daughters"}; + Configurable cfgV0CPAMin{"cfgV0CPAMin", 0.9998, "Minimum V0 CPA"}; + Configurable cfgV0TranRadV0Min{"cfgV0TranRadV0Min", 1.5f, "Minimum V0 transverse radius"}; + Configurable cfgV0TranRadV0Max{"cfgV0TranRadV0Max", 100.f, "Maximum V0 transverse radius"}; + Configurable cfgMaxV0DCA{"cfgMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; + Configurable cfgMinV0DCAPr{"cfgMinV0DCAPr", 0.05, "Minimum proton DCA to PV"}; + Configurable cfgMinV0DCAPi{"cfgMinV0DCAPi", 0.05, "Minimum pion DCA to PV"}; + Configurable cfgMaxV0LifeTime{"cfgMaxV0LifeTime", 20, "Maximum V0 lifetime"}; + + Configurable cfgCutPT{"cfgCutPT", 0.15, "PT cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + + Configurable cfgDaughEta{"cfgDaughEta", 0.8f, "Daughter eta range"}; + Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.4f, "Minimum daughter proton pT"}; + Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2f, "Minimum daughter pion pT"}; + Configurable cfgDaughTPCnclsMin{"cfgDaughTPCnclsMin", 50.f, "Minimum TPC found clusters"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Minimum TPC crossed rows"}; + Configurable cfgRcrfc{"cfgRcrfc", 0.8f, "TPC crossed rows / findable clusters"}; + Configurable cfgDaughPIDCuts{"cfgDaughPIDCuts", 3.f, "TPC PID nsigma cut"}; + + Configurable cfgTrackPtMin{"cfgTrackPtMin", 0.2f, "Minimum track pT for v1"}; + Configurable cfgTrackPtMax{"cfgTrackPtMax", 5.0f, "Maximum track pT for v1"}; + Configurable cfgTrackEtaMax{"cfgTrackEtaMax", 0.8f, "Maximum |eta| for v1"}; + Configurable cfgMinTPCClustersTrack{"cfgMinTPCClustersTrack", 70, "Minimum TPC clusters for v1 tracks"}; + + struct : ConfigurableGroup { + Configurable cfgRequireRCTFlagChecker{"cfgRequireRCTFlagChecker", true, "Check event quality in run condition table"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", true, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } rctCut; + + float massLambda = o2::constants::physics::MassLambda0; + float massPr = o2::constants::physics::MassProton; + float massPi = o2::constants::physics::MassPionCharged; + + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0., 5., 10., 20., 30., 40., 50., 80.}, "Centrality (%)"}; + ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.2, 0.5, 1., 1.5, 2., 2.5, 3., 4., 5., 6.5, 8., 10.}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis etaAxis{"etaAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0., 0.2, 0.4, 0.8}, "#eta"}; + ConfigurableAxis massAxis{"massAxis", {100, 1.0, 1.2}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis polAxis{"polAxis", {200, -1.0, 1.0}, "polarization observable"}; + ConfigurableAxis spAxis{"spAxis", {400, -10.0, 10.0}, "SP observable"}; + ConfigurableAxis q1Axis{"q1Axis", {VARIABLE_WIDTH, 0., 0.5, 1., 1.5, 2., 3., 5., 10.}, "q_{1}^{ZDC}"}; + ConfigurableAxis qAxis{"qAxis", {200, -10., 10.}, "Q"}; + ConfigurableAxis resAxis{"resAxis", {200, -1., 1.}, "resolution / correlation"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Service ccdb; + TProfile2D* accprofileL = nullptr; + TProfile2D* accprofileAL = nullptr; + int currentRunNumber = -999; + int lastRunNumber = -999; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + + RCTFlagsChecker rctChecker; + + using EventCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Filtered>; + using ResoV0s = aod::V0Datas; + using BCsRun3 = soa::Join; + + void init(InitContext&) + { + ccdb->setURL(cfgUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + histos.add("hCentrality", "Centrality", kTH1F, {{centAxis}}); + histos.add("hQ1ZDCvscent", "q1 vs centrality", kTH2F, {{centAxis}, {q1Axis}}); + histos.add("hQxAvscent", "Qx A vs centrality", kTH2F, {{centAxis}, {qAxis}}); + histos.add("hQyAvscent", "Qy A vs centrality", kTH2F, {{centAxis}, {qAxis}}); + histos.add("hQxCvscent", "Qx C vs centrality", kTH2F, {{centAxis}, {qAxis}}); + histos.add("hQyCvscent", "Qy C vs centrality", kTH2F, {{centAxis}, {qAxis}}); + + histos.add("hpResCosAC", "cos(#Psi_{A}-#Psi_{C}) vs centrality", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpResDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpQxAQxC", "QxA QxC", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpQyAQyC", "QyA QyC", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpQxAQyC", "QxA QyC", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpQxCQyA", "QxC QyA", kTH2F, {{centAxis}, {resAxis}}); + + std::vector axesV1SP = {centAxis, ptAxis, etaAxis, q1Axis, spAxis}; + std::vector axesV1EP = {centAxis, ptAxis, etaAxis, q1Axis, polAxis}; + + histos.add("hV1SPFullQ1", "charged v1 SP numerator u#upoint(QC-QA) vs q1", HistType::kTHnSparseF, axesV1SP, true); + histos.add("hV1SPAQ1", "charged v1 SP numerator u#upointQA vs q1", HistType::kTHnSparseF, axesV1SP, true); + histos.add("hV1SPCQ1", "charged v1 SP numerator u#upointQC vs q1", HistType::kTHnSparseF, axesV1SP, true); + histos.add("hV1EPFullQ1", "charged v1 EP QA cos(phi-PsiZDC) vs q1", HistType::kTHnSparseF, axesV1EP, true); + histos.add("hV1EPAQ1", "charged v1 EP QA cos(phi-PsiA) vs q1", HistType::kTHnSparseF, axesV1EP, true); + histos.add("hV1EPCQ1", "charged v1 EP QA cos(phi-PsiC) vs q1", HistType::kTHnSparseF, axesV1EP, true); + + std::vector axesPolSPQ1 = {massAxis, ptAxis, spAxis, centAxis, q1Axis}; + + histos.add("hSparseLambdaPolSPQ1", "Lambda SP polarization numerator vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolSPwgtQ1", "Lambda SP polarization numerator / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolSPAQ1", "Lambda SP polarization numerator A vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolSPCQ1", "Lambda SP polarization numerator C vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolSPAwgtQ1", "Lambda SP polarization numerator A / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolSPCwgtQ1", "Lambda SP polarization numerator C / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + + histos.add("hSparseAntiLambdaPolSPQ1", "AntiLambda SP polarization numerator vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolSPwgtQ1", "AntiLambda SP polarization numerator / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolSPAQ1", "AntiLambda SP polarization numerator A vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolSPCQ1", "AntiLambda SP polarization numerator C vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolSPAwgtQ1", "AntiLambda SP polarization numerator A / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolSPCwgtQ1", "AntiLambda SP polarization numerator C / acceptance vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + + histos.add("hSparseLambdaPolEPQ1", "Lambda EP QA sin(phi*-PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolEPAQ1", "Lambda EP QA sin(phi*-PsiA) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaPolEPCQ1", "Lambda EP QA sin(phi*-PsiC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolEPQ1", "AntiLambda EP QA sin(phi*-PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolEPAQ1", "AntiLambda EP QA sin(phi*-PsiA) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaPolEPCQ1", "AntiLambda EP QA sin(phi*-PsiC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + + histos.add("hSparseLambdaCosPsiQ1", "Lambda cos(PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaSinPsiQ1", "Lambda sin(PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaCosPsiQ1", "AntiLambda cos(PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaSinPsiQ1", "AntiLambda sin(PsiZDC) vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + + histos.add("hSparseLambdaCorrSinPhiStarQ1", "Lambda sin(phi*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaCorrCosPhiStarQ1", "Lambda cos(phi*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaCorrSinThetaStarQ1", "Lambda sin(theta*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaAvgUxQ1", "Lambda vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseLambdaAvgUyQ1", "Lambda vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + + histos.add("hSparseAntiLambdaCorrSinPhiStarQ1", "AntiLambda sin(phi*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaCorrCosPhiStarQ1", "AntiLambda cos(phi*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaCorrSinThetaStarQ1", "AntiLambda sin(theta*) acceptance correction vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaAvgUxQ1", "AntiLambda vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + histos.add("hSparseAntiLambdaAvgUyQ1", "AntiLambda vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); + } + + float getPhiInRange(float phi) + { + while (phi <= -o2::constants::math::PI) { + phi += o2::constants::math::TwoPI; + } + while (phi > o2::constants::math::PI) { + phi -= o2::constants::math::TwoPI; + } + return phi; + } + + template + bool eventSelected(TCollision collision) + { + if (!collision.sel8()) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return 0; + } + if (cfgPVSel && std::abs(collision.posZ()) > cfgCutVertex) { + return 0; + } + if (cfgAddEvtSelPileup && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return 0; + } + if (collision.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision.trackOccupancyInTimeRange() < cfgMinOccupancy) { + return 0; + } + if (rctCut.cfgRequireRCTFlagChecker && !rctChecker(collision)) { + return 0; + } + + return 1; + } + + template + bool getZDCQ1(Collision const& collision, float& qxA, float& qyA, float& qxC, float& qyC, + float& psiA, float& psiC, float& psiFull, float& q1) + { + const float rawQxA = collision.qxZDCA(); + const float rawQyA = collision.qyZDCA(); + const float rawQxC = collision.qxZDCC(); + const float rawQyC = collision.qyZDCC(); + + psiA = collision.psiZDCA(); + psiC = collision.psiZDCC(); + + const float magA = std::sqrt(rawQxA * rawQxA + rawQyA * rawQyA); + const float magC = std::sqrt(rawQxC * rawQxC + rawQyC * rawQyC); + qxA = magA * std::cos(psiA); + qyA = magA * std::sin(psiA); + qxC = magC * std::cos(psiC); + qyC = magC * std::sin(psiC); + + const float qxFull = qxC - qxA; + const float qyFull = qyC - qyA; + psiFull = std::atan2(qyFull, qxFull); + + const float q1A = std::sqrt(qxA * qxA + qyA * qyA); + const float q1C = std::sqrt(qxC * qxC + qyC * qyC); + const float q1Full = std::sqrt(qxFull * qxFull + qyFull * qyFull); + const float q1Mean = 0.5 * (q1A + q1C); + + if (cfgq1mode == 1) { + q1 = q1A; + } else if (cfgq1mode == 2) { + q1 = q1C; + } else if (cfgq1mode == 3) { + q1 = q1Mean; + } else { + q1 = q1Full; + } + + return std::isfinite(qxA) && std::isfinite(qyA) && std::isfinite(qxC) && std::isfinite(qyC) && std::isfinite(psiA) && std::isfinite(psiC) && std::isfinite(psiFull) && std::isfinite(q1); + } + + template + bool selectV1Track(Track const& track) + { + if (!track.isGlobalTrack()) { + return false; + } + if (track.pt() < cfgTrackPtMin || track.pt() > cfgTrackPtMax) { + return false; + } + if (std::abs(track.eta()) > cfgTrackEtaMax) { + return false; + } + if (track.tpcNClsFound() < cfgMinTPCClustersTrack) { + return false; + } + return true; + } + + template + bool isCompatible(V0 const& v0, int pid) + { + // pid = 0: Lambda, pid = 1: AntiLambda + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + + if (pid == 0 && (v0.positivept() < cfgDaughPrPt || v0.negativept() < cfgDaughPiPt)) { + return false; + } + if (pid == 1 && (v0.positivept() < cfgDaughPiPt || v0.negativept() < cfgDaughPrPt)) { + return false; + } + if (std::abs(v0.positiveeta()) > cfgDaughEta || std::abs(v0.negativeeta()) > cfgDaughEta) { + return false; + } + + if (posTrack.tpcNClsCrossedRows() < cfgTPCcluster || negTrack.tpcNClsCrossedRows() < cfgTPCcluster) { + return false; + } + if (posTrack.tpcNClsFound() < cfgDaughTPCnclsMin || negTrack.tpcNClsFound() < cfgDaughTPCnclsMin) { + return false; + } + if (posTrack.tpcCrossedRowsOverFindableCls() < cfgRcrfc || negTrack.tpcCrossedRowsOverFindableCls() < cfgRcrfc) { + return false; + } + + if (pid == 0 && (std::abs(posTrack.tpcNSigmaPr()) > cfgDaughPIDCuts || std::abs(negTrack.tpcNSigmaPi()) > cfgDaughPIDCuts)) { + return false; + } + if (pid == 1 && (std::abs(posTrack.tpcNSigmaPi()) > cfgDaughPIDCuts || std::abs(negTrack.tpcNSigmaPr()) > cfgDaughPIDCuts)) { + return false; + } + + if (pid == 0 && (std::abs(v0.dcapostopv()) < cfgMinV0DCAPr || std::abs(v0.dcanegtopv()) < cfgMinV0DCAPi)) { + return false; + } + if (pid == 1 && (std::abs(v0.dcapostopv()) < cfgMinV0DCAPi || std::abs(v0.dcanegtopv()) < cfgMinV0DCAPr)) { + return false; + } + return true; + } + + template + bool selectV0(Collision const& collision, V0 const& v0) + { + const float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda; + if (std::abs(v0.dcav0topv()) > cfgMaxV0DCA) { + return false; + } + if (v0.pt() < cfgV0PtMin) { + return false; + } + if (std::abs(v0.dcaV0daughters()) > cfgV0DCADaughMax) { + return false; + } + if (v0.v0cosPA() < cfgV0CPAMin) { + return false; + } + if (v0.v0radius() < cfgV0TranRadV0Min || v0.v0radius() > cfgV0TranRadV0Max) { + return false; + } + if (std::abs(ctauLambda) > cfgMaxV0LifeTime) { + return false; + } + if (std::abs(v0.yLambda()) > cfgV0Rap) { + return false; + } + if (std::abs(v0.eta()) > 0.8) { + return false; + } + return true; + } + + float acceptanceWeight(bool isLambda, float eta, float pt) + { + if (!cfgUseAccCorr) { + return 1.0; + } + TProfile2D* prof = isLambda ? accprofileL : accprofileAL; + if (!prof) { + return 1.0; + } + const int binx = prof->GetXaxis()->FindBin(eta); + const int biny = prof->GetYaxis()->FindBin(pt); + const float acc = prof->GetBinContent(binx, biny); + if (acc <= 0.0 || !std::isfinite(acc)) { + return 1.0; + } + return 1.0 / acc; + } + + template + void fillPolarization(bool isLambda, V0 const& v0, float centrality, float q1, float psiA, float psiC, float psiFull, float qxA, float qyA, float qxC, float qyC) + { + ROOT::Math::PxPyPzMVector daughter; + ROOT::Math::PxPyPzMVector pion; + float mass = 0.0; + + if (isLambda) { + daughter = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); + pion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + mass = v0.mLambda(); + } else { + daughter = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); + pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + mass = v0.mAntiLambda(); + } + + const auto hyperon = daughter + pion; + ROOT::Math::Boost boostToRest(hyperon.BoostToCM()); + const auto daughterStar = boostToRest(daughter); + + float phiStar = std::atan2(daughterStar.Py(), daughterStar.Px()); + const float ux = std::cos(phiStar); + const float uy = std::sin(phiStar); + + const float cosThetaStar = daughterStar.Pz() / daughterStar.P(); + const float sinThetaStar = std::sqrt(std::max(0.0, 1.0 - cosThetaStar * cosThetaStar)); + const float sinPhiStar = std::sin(getPhiInRange(phiStar)); + const float cosPhiStar = std::cos(getPhiInRange(phiStar)); + + float polEP_A = std::sin(getPhiInRange(phiStar - psiA)); + float polEP_C = std::sin(getPhiInRange(phiStar - psiC)); + float polEP = std::sin(getPhiInRange(phiStar - psiFull)); + + const float qxFull = qxC - qxA; + const float qyFull = qyC - qyA; + + float polSP = uy * qxFull - ux * qyFull; + float polSP_A = uy * qxA - ux * qyA; + float polSP_C = uy * qxC - ux * qyC; + + float accDen = acceptanceWeight(isLambda, v0.eta(), v0.pt()); + float wgt = 1.0; // efficiency + + polSP /= accDen; + polSP_A /= accDen; + polSP_C /= accDen; + + polEP /= accDen; + polEP_A /= accDen; + polEP_C /= accDen; + + const float cosPsi = std::cos(getPhiInRange(psiFull)); + const float sinPsi = std::sin(getPhiInRange(psiFull)); + + if (isLambda) { + histos.fill(HIST("hSparseLambdaPolSPQ1"), mass, v0.pt(), polSP, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaPolSPAQ1"), mass, v0.pt(), polSP_A, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaPolSPCQ1"), mass, v0.pt(), polSP_C, centrality, q1, wgt); + + histos.fill(HIST("hSparseLambdaPolEPQ1"), mass, v0.pt(), polEP, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaPolEPAQ1"), mass, v0.pt(), polEP_A, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaPolEPCQ1"), mass, v0.pt(), polEP_C, centrality, q1, wgt); + + histos.fill(HIST("hSparseLambdaCosPsiQ1"), mass, v0.pt(), cosPsi, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaSinPsiQ1"), mass, v0.pt(), sinPsi, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaCorrSinPhiStarQ1"), mass, v0.pt(), sinPhiStar, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaCorrCosPhiStarQ1"), mass, v0.pt(), cosPhiStar, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaCorrSinThetaStarQ1"), mass, v0.pt(), sinThetaStar, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaAvgUxQ1"), mass, v0.pt(), ux, centrality, q1, wgt); + histos.fill(HIST("hSparseLambdaAvgUyQ1"), mass, v0.pt(), uy, centrality, q1, wgt); + } else { + histos.fill(HIST("hSparseAntiLambdaPolSPQ1"), mass, v0.pt(), polSP, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaPolSPAQ1"), mass, v0.pt(), polSP_A, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaPolSPCQ1"), mass, v0.pt(), polSP_C, centrality, q1, wgt); + + histos.fill(HIST("hSparseAntiLambdaPolEPQ1"), mass, v0.pt(), polEP, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaPolEPAQ1"), mass, v0.pt(), polEP_A, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaPolEPCQ1"), mass, v0.pt(), polEP_C, centrality, q1, wgt); + + histos.fill(HIST("hSparseAntiLambdaCosPsiQ1"), mass, v0.pt(), cosPsi, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaSinPsiQ1"), mass, v0.pt(), sinPsi, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaCorrSinPhiStarQ1"), mass, v0.pt(), sinPhiStar, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaCorrCosPhiStarQ1"), mass, v0.pt(), cosPhiStar, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaCorrSinThetaStarQ1"), mass, v0.pt(), sinThetaStar, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaAvgUxQ1"), mass, v0.pt(), ux, centrality, q1, wgt); + histos.fill(HIST("hSparseAntiLambdaAvgUyQ1"), mass, v0.pt(), uy, centrality, q1, wgt); + } + } + + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& tracks, ResoV0s const& v0s, BCsRun3 const&) + { + if (!eventSelected(collision)) { + return; + } + const float centrality = collision.centFT0C(); + + if (cfgUseAccCorr) { + auto bc = collision.bc_as(); + currentRunNumber = bc.runNumber(); + if (currentRunNumber != lastRunNumber) { + accprofileL = ccdb->getForTimeStamp(cfgAccPathL.value, bc.timestamp()); + accprofileAL = ccdb->getForTimeStamp(cfgAccPathAL.value, bc.timestamp()); + lastRunNumber = currentRunNumber; + } + } + + float qxA = 0.0, qyA = 0.0, qxC = 0.0, qyC = 0.0; + float psiA = 0.0, psiC = 0.0, psiFull = 0.0, q1 = 0.0; + if (!getZDCQ1(collision, qxA, qyA, qxC, qyC, psiA, psiC, psiFull, q1)) { + return; + } + + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hQ1ZDCvscent"), centrality, q1); + histos.fill(HIST("hQxAvscent"), centrality, qxA); + histos.fill(HIST("hQyAvscent"), centrality, qyA); + histos.fill(HIST("hQxCvscent"), centrality, qxC); + histos.fill(HIST("hQyCvscent"), centrality, qyC); + + float magA = std::sqrt(qxA * qxA + qyA * qyA); + float magC = std::sqrt(qxC * qxC + qyC * qyC); + float qxFull = qxC - qxA; + float qyFull = qyC - qyA; + float dotAC = qxA * qxC + qyA * qyC; + float resDot = dotAC / (magA * magC); + + histos.fill(HIST("hpResCosAC"), centrality, std::cos(getPhiInRange(psiA - psiC))); + histos.fill(HIST("hpResDotAC"), centrality, resDot); + histos.fill(HIST("hpQxAQxC"), centrality, qxA * qxC); + histos.fill(HIST("hpQyAQyC"), centrality, qyA * qyC); + histos.fill(HIST("hpQxAQyC"), centrality, qxA * qyC); + histos.fill(HIST("hpQxCQyA"), centrality, qxC * qyA); + + for (const auto& track : tracks) { + if (!selectV1Track(track)) { + continue; + } + + float phi = track.phi(); + float ux = std::cos(phi); + float uy = std::sin(phi); + + float v1SPFull = ux * qxFull + uy * qyFull; + float v1SPA = ux * qxA + uy * qyA; + float v1SPC = ux * qxC + uy * qyC; + + histos.fill(HIST("hV1SPFullQ1"), centrality, track.pt(), track.eta(), q1, v1SPFull); + histos.fill(HIST("hV1SPAQ1"), centrality, track.pt(), track.eta(), q1, v1SPA); + histos.fill(HIST("hV1SPCQ1"), centrality, track.pt(), track.eta(), q1, v1SPC); + + histos.fill(HIST("hV1EPFullQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiFull))); + histos.fill(HIST("hV1EPAQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiA))); + histos.fill(HIST("hV1EPCQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiC))); + } + + for (const auto& v0 : v0s) { + bool lambdaTag = isCompatible(v0, 0); + bool antiLambdaTag = isCompatible(v0, 1); + if (!lambdaTag && !antiLambdaTag) { + continue; + } + if (!selectV0(collision, v0)) { + continue; + } + if (lambdaTag) { + fillPolarization(true, v0, centrality, q1, psiA, psiC, psiFull, qxA, qyA, qxC, qyC); + } + if (antiLambdaTag) { + fillPolarization(false, v0, centrality, q1, psiA, psiC, psiFull, qxA, qyA, qxC, qyC); + } + } + } + PROCESS_SWITCH(flowDirectedFlowTask, processData, "Process for data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 170b8575bc7e5319a23ffdedf1af2307bf7d649e Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Fri, 22 May 2026 12:16:10 +0200 Subject: [PATCH 262/449] [PWGCF] Adding PID QA plots (#16348) Co-authored-by: Sushanta Tripathy --- .../Tasks/nucleibalance.cxx | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx index f4ad2949422..64059ba5e9e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -1959,6 +1959,8 @@ struct Lambdastarproxy { AxisSpec dEdxAxis{400, 0., 200., "TPC dE/dx (arb. units)"}; AxisSpec betaAxis{160, 0., 1.6, "#beta_{TOF}"}; + AxisSpec dcaXYAxis{200, -0.2, 0.2, "DCA_{xy} (cm)"}; + AxisSpec dcaZAxis{200, -0.2, 0.2, "DCA_{z} (cm)"}; // Invariant-mass spectra histos.add("hInvMassPKUnlike", @@ -2112,6 +2114,78 @@ struct Lambdastarproxy { histos.add("hNsigmaTOFKaonVsP", "TOF n#sigma_{K} vs p; p (GeV/c); n#sigma^{TOF}_{K};Counts", HistType::kTH2F, {pAxis, nsAxis}); + + // --- Additional pT-based PID QA for the final selected K/p/d candidates --- + // These histograms are needed for PID studies in the same pT intervals used by the analysis. + histos.add("hTOFBetaVsPt_K", + "TOF #beta vs p_{T} for selected K;p_{T} (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {ptAxis, betaAxis}); + histos.add("hTOFBetaVsPt_P", + "TOF #beta vs p_{T} for selected p;p_{T} (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {ptAxis, betaAxis}); + histos.add("hTOFBetaVsPt_D", + "TOF #beta vs p_{T} for selected d;p_{T} (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {ptAxis, betaAxis}); + + histos.add("hNsigmaTPCKaonVsPt", + "TPC n#sigma_{K} vs p_{T};p_{T} (GeV/c);n#sigma^{TPC}_{K};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + histos.add("hNsigmaTOFKaonVsPt", + "TOF n#sigma_{K} vs p_{T};p_{T} (GeV/c);n#sigma^{TOF}_{K};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + + histos.add("hNsigmaTPCProtonVsP", + "TPC n#sigma_{p} vs p;p (GeV/c);n#sigma^{TPC}_{p};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTOFProtonVsP", + "TOF n#sigma_{p} vs p;p (GeV/c);n#sigma^{TOF}_{p};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTPCProtonVsPt", + "TPC n#sigma_{p} vs p_{T};p_{T} (GeV/c);n#sigma^{TPC}_{p};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + histos.add("hNsigmaTOFProtonVsPt", + "TOF n#sigma_{p} vs p_{T};p_{T} (GeV/c);n#sigma^{TOF}_{p};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + + histos.add("hNsigmaTPCDeuteronVsPt", + "TPC n#sigma_{d} vs p_{T};p_{T} (GeV/c);n#sigma^{TPC}_{d};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + histos.add("hNsigmaTOFDeuteronVsPt", + "TOF n#sigma_{d} vs p_{T};p_{T} (GeV/c);n#sigma^{TOF}_{d};Counts", + HistType::kTH2F, {ptAxis, nsAxis}); + + histos.add("hTPCvsTOFNsigma_K", + "TPC vs TOF n#sigma for selected K;n#sigma^{TPC}_{K};n#sigma^{TOF}_{K};Counts", + HistType::kTH2F, {nsAxis, nsAxis}); + histos.add("hTPCvsTOFNsigma_P", + "TPC vs TOF n#sigma for selected p;n#sigma^{TPC}_{p};n#sigma^{TOF}_{p};Counts", + HistType::kTH2F, {nsAxis, nsAxis}); + histos.add("hTPCvsTOFNsigma_D", + "TPC vs TOF n#sigma for selected d;n#sigma^{TPC}_{d};n#sigma^{TOF}_{d};Counts", + HistType::kTH2F, {nsAxis, nsAxis}); + + // --- DCA QA for final selected K/p/d candidates --- + // Filled only when lstarEnablePidQA = 1. + histos.add("hDCAxyVsPt_K", + "DCA_{xy} vs p_{T} distribution for selected K;p_{T} (GeV/c);DCA_{xy} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaXYAxis}); + histos.add("hDCAzVsPt_K", + "DCA_{z} vs p_{T} distribution for selected K;p_{T} (GeV/c);DCA_{z} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaZAxis}); + + histos.add("hDCAxyVsPt_P", + "DCA_{xy} vs p_{T} distribution for selected p;p_{T} (GeV/c);DCA_{xy} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaXYAxis}); + histos.add("hDCAzVsPt_P", + "DCA_{z} vs p_{T} distribution for selected p;p_{T} (GeV/c);DCA_{z} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaZAxis}); + + histos.add("hDCAxyVsPt_D", + "DCA_{xy} vs p_{T} distribution for selected d;p_{T} (GeV/c);DCA_{xy} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaXYAxis}); + histos.add("hDCAzVsPt_D", + "DCA_{z} vs p_{T} distribution for selected d;p_{T} (GeV/c);DCA_{z} (cm);Counts", + HistType::kTH2F, {ptAxis, dcaZAxis}); } // AO2D-MC QA: truth primaries + reco-to-MC matching sanity plots @@ -2531,6 +2605,21 @@ struct Lambdastarproxy { histos.fill(HIST("hNsigmaTOFDeuteron"), nsTOFDe); histos.fill(HIST("hNsigmaTPCDeuteronVsP"), pD, nsTPCDe); histos.fill(HIST("hNsigmaTOFDeuteronVsP"), pD, nsTOFDe); + histos.fill(HIST("hNsigmaTPCDeuteronVsPt"), ptD, nsTPCDe); + histos.fill(HIST("hNsigmaTOFDeuteronVsPt"), ptD, nsTOFDe); + if (hasTofDe) { + histos.fill(HIST("hTPCvsTOFNsigma_D"), nsTPCDe, nsTOFDe); + } + if constexpr (requires { trkD.beta(); }) { + const float beta = trkD.beta(); + if (hasTofDe && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsPt_D"), ptD, beta); + } + } + if constexpr (requires { trkD.dcaXY(); trkD.dcaZ(); }) { + histos.fill(HIST("hDCAxyVsPt_D"), ptD, trkD.dcaXY()); + histos.fill(HIST("hDCAzVsPt_D"), ptD, trkD.dcaZ()); + } } // build proton-proxy momentum from deuteron: p_p ≈ p_d / 2 @@ -2565,6 +2654,27 @@ struct Lambdastarproxy { const float ptP = trkP.pt(); const float etaP = trkP.eta(); const float phiP = trkP.phi(); + const double pP = static_cast(ptP) * std::cosh(static_cast(etaP)); + + if (lstarEnablePidQA.value != 0) { + histos.fill(HIST("hNsigmaTPCProtonVsP"), pP, nsTPCPr); + histos.fill(HIST("hNsigmaTOFProtonVsP"), pP, nsTOFPr); + histos.fill(HIST("hNsigmaTPCProtonVsPt"), ptP, nsTPCPr); + histos.fill(HIST("hNsigmaTOFProtonVsPt"), ptP, nsTOFPr); + if (hasTofPr) { + histos.fill(HIST("hTPCvsTOFNsigma_P"), nsTPCPr, nsTOFPr); + } + if constexpr (requires { trkP.beta(); }) { + const float beta = trkP.beta(); + if (hasTofPr && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsPt_P"), ptP, beta); + } + } + if constexpr (requires { trkP.dcaXY(); trkP.dcaZ(); }) { + histos.fill(HIST("hDCAxyVsPt_P"), ptP, trkP.dcaXY()); + histos.fill(HIST("hDCAzVsPt_P"), ptP, trkP.dcaZ()); + } + } const float pxP = ptP * std::cos(phiP); const float pyP = ptP * std::sin(phiP); @@ -2610,6 +2720,21 @@ struct Lambdastarproxy { histos.fill(HIST("hNsigmaTOFKaon"), nsTOFK); histos.fill(HIST("hNsigmaTPCKaonVsP"), pK, nsTPCK); histos.fill(HIST("hNsigmaTOFKaonVsP"), pK, nsTOFK); + histos.fill(HIST("hNsigmaTPCKaonVsPt"), ptK, nsTPCK); + histos.fill(HIST("hNsigmaTOFKaonVsPt"), ptK, nsTOFK); + if (hasTofK) { + histos.fill(HIST("hTPCvsTOFNsigma_K"), nsTPCK, nsTOFK); + } + if constexpr (requires { trkK.beta(); }) { + const float beta = trkK.beta(); + if (hasTofK && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsPt_K"), ptK, beta); + } + } + if constexpr (requires { trkK.dcaXY(); trkK.dcaZ(); }) { + histos.fill(HIST("hDCAxyVsPt_K"), ptK, trkK.dcaXY()); + histos.fill(HIST("hDCAzVsPt_K"), ptK, trkK.dcaZ()); + } } const float pxK = ptK * std::cos(phiK); From 99f15c99232ccb9b089328ab2bbc5ff6e12e8b99 Mon Sep 17 00:00:00 2001 From: sarjeetagami <162087855+sarjeetagami@users.noreply.github.com> Date: Fri, 22 May 2026 16:30:29 +0530 Subject: [PATCH 263/449] [PWGLF] Minor fixes in phi analysis (#16349) Co-authored-by: sarjeeta gami --- PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx index 803a534fca0..f3acbe51ff3 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3pbpb.cxx @@ -232,7 +232,7 @@ struct Phianalysisrun3pbpb { histos.add("h3PhifinalRec", "Phi meson Rec", kTH3F, {ptAxisphi, centAxisphi, massAxisphi}); histos.add("h1PhifinalGen", "Phi meson Gen", kTH1F, {ptAxisphi}); histos.add("h2PhifinalGen", "Phi meson Gen", kTH2F, {ptAxisphi, centAxisphi}); - histos.add("hMC1", "MC Event statistics", kTH1F, {{15, 0.0f, 15.0f}}); + histos.add("hMC1", "MC Event statistics", kTH1F, {{20, 0.0f, 20.0f}}); histos.add("Centrec1", "MC Centrality", kTH1F, {centAxisphi}); histos.add("Centsame", "MC Centrality", kTH1F, {centAxisphi}); histos.add("Centmc", "MC Centrality", kTH1F, {centAxisphi}); @@ -1719,7 +1719,7 @@ struct Phianalysisrun3pbpb { } histos.fill(HIST("hMC1"), 5.5); if (selectionConfig.cutvz && - std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { + std::abs(collision.posZ()) > selectionConfig.cfgCutVertex) { continue; } @@ -1817,7 +1817,7 @@ struct Phianalysisrun3pbpb { } PROCESS_SWITCH(Phianalysisrun3pbpb, processGen1, "Process Generated", false); - void processRec1(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) + void processRec1(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, McCollisionMults const& /*mcCollisions*/) { if (!collision.has_mcCollision()) { return; @@ -1826,7 +1826,7 @@ struct Phianalysisrun3pbpb { return; } if (selectionConfig.cutvz && - std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { + std::abs(collision.posZ()) > selectionConfig.cfgCutVertex) { return; } if (selectionConfig.additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { From 053b8299cd4daa9316e1417f4370bd4f211a7e21 Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Fri, 22 May 2026 20:13:32 +0800 Subject: [PATCH 264/449] [PWGCF] Add phi-invmass histo for V0 and casc NUA (#16347) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 138 ++++++++++++++++++---------- 1 file changed, 92 insertions(+), 46 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index ef5619c13aa..ad9ae6e0280 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -110,8 +110,11 @@ struct FlowGfwOmegaXi { std::string prefix = "v0BuilderOpts"; // topological cut for V0 O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum decay radius") + O2_DEFINE_CONFIGURABLE(cfgv0_radiusmax, float, 100.0f, "maximum decay radius") O2_DEFINE_CONFIGURABLE(cfgv0_v0cospa, float, 0.995f, "minimum cosine of pointing angle") - O2_DEFINE_CONFIGURABLE(cfgv0_dcadautopv, float, 0.1f, "minimum daughter DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgv0_dcak0daupitopv, float, 0.01f, "minimum daughter pion DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgv0_dcadaupitopv, float, 0.01f, "minimum daughter pion DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgv0_dcadauprtopv, float, 0.1f, "minimum daughter proton DCA to PV") O2_DEFINE_CONFIGURABLE(cfgv0_dcav0dau, float, 0.5f, "maximum DCA among V0 daughters") O2_DEFINE_CONFIGURABLE(cfgv0_mk0swindow, float, 0.1f, "Invariant mass window of K0s") O2_DEFINE_CONFIGURABLE(cfgv0_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") @@ -198,6 +201,7 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgLocDenParaLambda, std::vector, (std::vector{-0.000510948, -4.4846, -0.000460629, -4.14465, -0.000433729, -3.94173, -0.000412751, -3.81839, -0.000411211, -3.72502, -0.000401511, -3.68426, -0.000407461, -3.67005, -0.000379371, -3.71153, -0.000392828, -3.73214, -0.000403996, -3.80717, -0.000403376, -3.90917, -0.000354624, -4.34629, -0.000477606, -4.66307, -0.000541139, -4.61364}), "Local density efficiency function parameter for Lambda, exp(Ax + B)") O2_DEFINE_CONFIGURABLE(cfgRunNumbers, std::vector, (std::vector{544095, 544098, 544116, 544121, 544122, 544123, 544124}), "Preconfigured run numbers") O2_DEFINE_CONFIGURABLE(cfgEtagapEdge, std::vector, (std::vector{-0.8, -0.4, 0.4, 0.8}), "sub-event eta range A: ([0], [1]) and C: ([2], [3])") + O2_DEFINE_CONFIGURABLE(cfgEtagapEdgeREF, std::vector, (std::vector{-0.8, -0.4, 0.4, 0.8}), "sub-event eta range for REF. A: ([0], [1]) and C: ([2], [3])") // switch O2_DEFINE_CONFIGURABLE(cfgDoAccEffCorr, bool, false, "do acc and eff corr") O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") @@ -259,7 +263,8 @@ struct FlowGfwOmegaXi { std::vector cfgMultPVCutPara; std::vector cfgmassbins; std::vector runNumbers; - std::vector EtagapEdge; + std::vector etagapEdge; + std::vector etagapEdgeREF; std::map>> th1sList; std::map>> th3sList; enum OutputTH1Names { @@ -332,7 +337,8 @@ struct FlowGfwOmegaXi { cfgNSigma = cfgNSigmapid; cfgmassbins = cfgMassBins; cfgMultPVCutPara = evtSeleOpts.cfgMultPVCut; - EtagapEdge = cfgEtagapEdge; + etagapEdge = cfgEtagapEdge; + etagapEdgeREF = cfgEtagapEdgeREF; // Set the pt, mult and phi Axis; o2::framework::AxisSpec axisPt = cfgaxisPt; @@ -367,6 +373,11 @@ struct FlowGfwOmegaXi { fLambdaMass = new TAxis(cfgmassbins[1], 1.08, 1.16); + AxisSpec axisOmegaMass = {80, 1.63f, 1.71f, "Inv. Mass (GeV)"}; + AxisSpec axisXiMass = {80, 1.29f, 1.37f, "Inv. Mass (GeV)"}; + AxisSpec axisK0sMass = {400, 0.4f, 0.6f, "Inv. Mass (GeV)"}; + AxisSpec axisLambdaMass = {160, 1.08f, 1.16f, "Inv. Mass (GeV)"}; + // Add some output objects to the histogram registry registry.add("hPhi", "", {HistType::kTH1D, {cfgaxisPhi}}); registry.add("hPhicorr", "", {HistType::kTH1D, {cfgaxisPhi}}); @@ -418,6 +429,10 @@ struct FlowGfwOmegaXi { registry.get(HIST("correction/hRunNumberPhiEtaVertexXi"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); registry.get(HIST("correction/hRunNumberPhiEtaVertexOmega"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); } + registry.add("correction/hPhiEtaInvmassK0s", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, axisK0sMass}}); + registry.add("correction/hPhiEtaInvmassLambda", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, axisLambdaMass}}); + registry.add("correction/hPhiEtaInvmassXi", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, axisXiMass}}); + registry.add("correction/hPhiEtaInvmassOmega", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, axisOmegaMass}}); } registry.add("hEventCount", "", {HistType::kTH1D, {{14, 0, 14}}}); @@ -591,10 +606,6 @@ struct FlowGfwOmegaXi { registry.add("MC/Lambdac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtLambda, axisMultiplicity}}); } // InvMass(GeV) of casc and v0 - AxisSpec axisOmegaMass = {80, 1.63f, 1.71f, "Inv. Mass (GeV)"}; - AxisSpec axisXiMass = {80, 1.29f, 1.37f, "Inv. Mass (GeV)"}; - AxisSpec axisK0sMass = {400, 0.4f, 0.6f, "Inv. Mass (GeV)"}; - AxisSpec axisLambdaMass = {160, 1.08f, 1.16f, "Inv. Mass (GeV)"}; if (cfgOutputCasc) { registry.add("InvMassXi_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassOmega_all", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); @@ -631,46 +642,46 @@ struct FlowGfwOmegaXi { } // Data - fGFW->AddRegion("reffull", EtagapEdge[0], EtagapEdge[3], 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 + fGFW->AddRegion("reffull", etagapEdgeREF[0], etagapEdgeREF[3], 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 int nK0sptMassBins = nK0sPtBins * cfgmassbins[0]; int nLambdaptMassBins = nLambdaPtBins * cfgmassbins[1]; int nXiptMassBins = nXiPtBins * cfgmassbins[2]; int nOmegaptMassBins = nXiPtBins * cfgmassbins[3]; - fGFW->AddRegion("refN10", EtagapEdge[0], EtagapEdge[1], 1, 1); - fGFW->AddRegion("refP10", EtagapEdge[2], EtagapEdge[3], 1, 1); + fGFW->AddRegion("refN10", etagapEdgeREF[0], etagapEdgeREF[1], 1, 1); + fGFW->AddRegion("refP10", etagapEdgeREF[2], etagapEdgeREF[3], 1, 1); - fGFW->AddRegion("poiN10dpt", EtagapEdge[0], EtagapEdge[1], nPtBins, 32); - fGFW->AddRegion("poiP10dpt", EtagapEdge[2], EtagapEdge[3], nPtBins, 32); - fGFW->AddRegion("poifulldpt", EtagapEdge[0], EtagapEdge[3], nPtBins, 32); - fGFW->AddRegion("poioldpt", EtagapEdge[0], EtagapEdge[3], nPtBins, 1); + fGFW->AddRegion("poiN10dpt", etagapEdge[0], etagapEdge[1], nPtBins + 1, 32); + fGFW->AddRegion("poiP10dpt", etagapEdge[2], etagapEdge[3], nPtBins + 1, 32); + fGFW->AddRegion("poifulldpt", etagapEdge[0], etagapEdge[3], nPtBins + 1, 32); + fGFW->AddRegion("poioldpt", etagapEdge[0], etagapEdge[3], nPtBins + 1, 1); - fGFW->AddRegion("poiXiPdpt", EtagapEdge[2], EtagapEdge[3], nXiptMassBins, 2); - fGFW->AddRegion("poiXiNdpt", EtagapEdge[0], EtagapEdge[1], nXiptMassBins, 2); - fGFW->AddRegion("poiXifulldpt", EtagapEdge[0], EtagapEdge[3], nXiptMassBins, 2); + fGFW->AddRegion("poiXiPdpt", etagapEdge[2], etagapEdge[3], nXiptMassBins + 1, 2); + fGFW->AddRegion("poiXiNdpt", etagapEdge[0], etagapEdge[1], nXiptMassBins + 1, 2); + fGFW->AddRegion("poiXifulldpt", etagapEdge[0], etagapEdge[3], nXiptMassBins + 1, 2); - fGFW->AddRegion("poiOmegaPdpt", EtagapEdge[2], EtagapEdge[3], nOmegaptMassBins, 4); - fGFW->AddRegion("poiOmegaNdpt", EtagapEdge[0], EtagapEdge[1], nOmegaptMassBins, 4); - fGFW->AddRegion("poiOmegafulldpt", EtagapEdge[0], EtagapEdge[3], nOmegaptMassBins, 4); + fGFW->AddRegion("poiOmegaPdpt", etagapEdge[2], etagapEdge[3], nOmegaptMassBins + 1, 4); + fGFW->AddRegion("poiOmegaNdpt", etagapEdge[0], etagapEdge[1], nOmegaptMassBins + 1, 4); + fGFW->AddRegion("poiOmegafulldpt", etagapEdge[0], etagapEdge[3], nOmegaptMassBins + 1, 4); - fGFW->AddRegion("poiK0sPdpt", EtagapEdge[2], EtagapEdge[3], nK0sptMassBins, 8); - fGFW->AddRegion("poiK0sNdpt", EtagapEdge[0], EtagapEdge[1], nK0sptMassBins, 8); - fGFW->AddRegion("poiK0sfulldpt", EtagapEdge[0], EtagapEdge[3], nK0sptMassBins, 8); + fGFW->AddRegion("poiK0sPdpt", etagapEdge[2], etagapEdge[3], nK0sptMassBins + 1, 8); + fGFW->AddRegion("poiK0sNdpt", etagapEdge[0], etagapEdge[1], nK0sptMassBins + 1, 8); + fGFW->AddRegion("poiK0sfulldpt", etagapEdge[0], etagapEdge[3], nK0sptMassBins + 1, 8); - fGFW->AddRegion("poiLambdaPdpt", EtagapEdge[2], EtagapEdge[3], nLambdaptMassBins, 16); - fGFW->AddRegion("poiLambdaNdpt", EtagapEdge[0], EtagapEdge[1], nLambdaptMassBins, 16); - fGFW->AddRegion("poiLambdafulldpt", EtagapEdge[0], EtagapEdge[3], nLambdaptMassBins, 16); + fGFW->AddRegion("poiLambdaPdpt", etagapEdge[2], etagapEdge[3], nLambdaptMassBins + 1, 16); + fGFW->AddRegion("poiLambdaNdpt", etagapEdge[0], etagapEdge[1], nLambdaptMassBins + 1, 16); + fGFW->AddRegion("poiLambdafulldpt", etagapEdge[0], etagapEdge[3], nLambdaptMassBins + 1, 16); // MC - fGFW->AddRegion("refN10MC", EtagapEdge[0], EtagapEdge[1], 1, 64); - fGFW->AddRegion("refP10MC", EtagapEdge[2], EtagapEdge[3], 1, 64); - fGFW->AddRegion("poiXiPdptMC", EtagapEdge[2], EtagapEdge[3], nXiptMassBins, 128); - fGFW->AddRegion("poiXiNdptMC", EtagapEdge[0], EtagapEdge[1], nXiptMassBins, 128); - fGFW->AddRegion("poiOmegaPdptMC", EtagapEdge[2], EtagapEdge[3], nOmegaptMassBins, 256); - fGFW->AddRegion("poiOmegaNdptMC", EtagapEdge[0], EtagapEdge[1], nOmegaptMassBins, 256); - fGFW->AddRegion("poiK0sPdptMC", EtagapEdge[2], EtagapEdge[3], nK0sptMassBins, 512); - fGFW->AddRegion("poiK0sNdptMC", EtagapEdge[0], EtagapEdge[1], nK0sptMassBins, 512); - fGFW->AddRegion("poiLambdaPdptMC", EtagapEdge[2], EtagapEdge[3], nLambdaptMassBins, 1024); - fGFW->AddRegion("poiLambdaNdptMC", EtagapEdge[0], EtagapEdge[1], nLambdaptMassBins, 1024); + fGFW->AddRegion("refN10MC", etagapEdgeREF[0], etagapEdgeREF[1], 1, 64); + fGFW->AddRegion("refP10MC", etagapEdgeREF[2], etagapEdgeREF[3], 1, 64); + fGFW->AddRegion("poiXiPdptMC", etagapEdge[2], etagapEdge[3], nXiptMassBins, 128); + fGFW->AddRegion("poiXiNdptMC", etagapEdge[0], etagapEdge[1], nXiptMassBins, 128); + fGFW->AddRegion("poiOmegaPdptMC", etagapEdge[2], etagapEdge[3], nOmegaptMassBins, 256); + fGFW->AddRegion("poiOmegaNdptMC", etagapEdge[0], etagapEdge[1], nOmegaptMassBins, 256); + fGFW->AddRegion("poiK0sPdptMC", etagapEdge[2], etagapEdge[3], nK0sptMassBins, 512); + fGFW->AddRegion("poiK0sNdptMC", etagapEdge[0], etagapEdge[1], nK0sptMassBins, 512); + fGFW->AddRegion("poiLambdaPdptMC", etagapEdge[2], etagapEdge[3], nLambdaptMassBins, 1024); + fGFW->AddRegion("poiLambdaNdptMC", etagapEdge[0], etagapEdge[1], nLambdaptMassBins, 1024); // pushback // Data // v2 @@ -1255,27 +1266,40 @@ struct FlowGfwOmegaXi { float ctau = 0; if (isK0s) { ctau = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; - if (ctau < v0BuilderOpts.cfgv0_ctauK0s.value) + if (ctau > v0BuilderOpts.cfgv0_ctauK0s.value) isK0s = false; + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcak0daupitopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcak0daupitopv.value) + continue; } if (isLambda || isALambda) { ctau = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; - if (ctau < v0BuilderOpts.cfgv0_ctauLambda.value) { + if (ctau > v0BuilderOpts.cfgv0_ctauLambda.value) { isLambda = false; isALambda = false; } + if (isLambda) { + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadauprtopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadaupitopv.value) + continue; + } else { + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadaupitopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadauprtopv.value) + continue; + } } // // topological cut if (v0.v0radius() < v0BuilderOpts.cfgv0_radius.value) continue; + if (v0.v0radius() > v0BuilderOpts.cfgv0_radiusmax.value) + continue; if (v0.v0cosPA() < v0BuilderOpts.cfgv0_v0cospa.value) continue; if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) continue; - if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) - continue; - if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) - continue; if (isK0s && std::fabs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0BuilderOpts.cfgv0_compmassrejLambda.value) isK0s = false; if (isK0s && std::fabs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < v0BuilderOpts.cfgv0_compmassrejLambda.value) @@ -1340,6 +1364,7 @@ struct FlowGfwOmegaXi { th1sList[runNumber][hPhiK0scorr]->Fill(v0.phi(), wacc); } registry.fill(HIST("correction/hRunNumberPhiEtaVertexK0s"), matchedPosition, v0.phi(), v0.eta(), vtxz); + registry.fill(HIST("correction/hPhiEtaInvmassK0s"), v0.phi(), v0.eta(), v0.mK0Short()); } } if (isLambda || isALambda) { @@ -1373,6 +1398,10 @@ struct FlowGfwOmegaXi { th1sList[runNumber][hPhiLambdacorr]->Fill(v0.phi(), wacc); } registry.fill(HIST("correction/hRunNumberPhiEtaVertexLambda"), matchedPosition, v0.phi(), v0.eta(), vtxz); + if (isLambda) + registry.fill(HIST("correction/hPhiEtaInvmassLambda"), matchedPosition, v0.phi(), v0.eta(), v0.mLambda()); + if (isALambda) + registry.fill(HIST("correction/hPhiEtaInvmassLambda"), matchedPosition, v0.phi(), v0.eta(), v0.mAntiLambda()); } } } @@ -1607,6 +1636,7 @@ struct FlowGfwOmegaXi { th1sList[runNumber][hPhiOmegacorr]->Fill(casc.phi(), wacc); } registry.fill(HIST("correction/hRunNumberPhiEtaVertexOmega"), matchedPosition, casc.phi(), casc.eta(), vtxz); + registry.fill(HIST("correction/hPhiEtaInvmassOmega"), casc.phi(), casc.eta(), casc.mOmega()); } } if (isXi) { @@ -1636,6 +1666,7 @@ struct FlowGfwOmegaXi { th1sList[runNumber][hPhiXicorr]->Fill(casc.phi(), wacc); } registry.fill(HIST("correction/hRunNumberPhiEtaVertexXi"), matchedPosition, casc.phi(), casc.eta(), vtxz); + registry.fill(HIST("correction/hPhiEtaInvmassXi"), casc.phi(), casc.eta(), casc.mXi()); } } } @@ -2163,10 +2194,25 @@ struct FlowGfwOmegaXi { continue; if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) continue; - if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) - continue; - if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) - continue; + if (pdgCode == kK0Short) { + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcak0daupitopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcak0daupitopv.value) + continue; + } + if (pdgCode == kLambda0 || pdgCode == kLambda0Bar) { + if (pdgCode == kLambda0) { + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadauprtopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadaupitopv.value) + continue; + } else { + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadaupitopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadauprtopv.value) + continue; + } + } // fill QA after cut if (cfgOutputQA) { if (pdgCode == kK0Short) { From 246528c443227738e847eda9d592bfa8fef0d1f8 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 22 May 2026 15:02:06 +0200 Subject: [PATCH 265/449] [PWGDQ] make matching QA table filling more flexible (#16325) --- PWGDQ/Tasks/qaMatching.cxx | 248 +++++++++++++++---------------------- 1 file changed, 99 insertions(+), 149 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 4ca6f69ecd4..6f2056d9c24 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -100,6 +100,7 @@ DECLARE_SOA_COLUMN(MatchRanking, matchRanking, int32_t); DECLARE_SOA_COLUMN(MftMultiplicity, mftMultiplicity, int32_t); DECLARE_SOA_COLUMN(TrackType, trackType, int8_t); DECLARE_SOA_COLUMN(MftMatchAttempts, mftMatchAttempts, int32_t); +DECLARE_SOA_COLUMN(IsTagged, isTagged, bool); DECLARE_SOA_COLUMN(XAtVtx, xAtVtx, float); DECLARE_SOA_COLUMN(YAtVtx, yAtVtx, float); DECLARE_SOA_COLUMN(ZAtVtx, zAtVtx, float); @@ -138,6 +139,7 @@ DECLARE_SOA_TABLE(QaMatchingMCHTrack, "AOD", "QAMCHTRK", qamatching::Eta, qamatching::Phi, qamatching::MftMatchAttempts, + qamatching::IsTagged, qamatching::XAtVtx, qamatching::YAtVtx, qamatching::ZAtVtx, @@ -261,6 +263,10 @@ struct QaMatching { Configurable cfgMuonTaggingRabsLow{"cfgMuonTaggingRabsLow", 17.6f, ""}; Configurable cfgMuonTaggingRabsUp{"cfgMuonTaggingRabsUp", 89.5f, ""}; Configurable cfgMuonTaggingPdcaUp{"cfgMuonTaggingPdcaUp", 4.f, ""}; + Configurable cfgMuonTaggingRadiusAtMftFrontLow{"cfgMuonTaggingRadiusAtMftFrontLow", 3.f, ""}; + Configurable cfgMuonTaggingRadiusAtMftFrontUp{"cfgMuonTaggingRadiusAtMftFrontUp", 9.f, ""}; + Configurable cfgMuonTaggingRadiusAtMftBackLow{"cfgMuonTaggingRadiusAtMftBackLow", 5.f, ""}; + Configurable cfgMuonTaggingRadiusAtMftBackUp{"cfgMuonTaggingRadiusAtMftBackUp", 12.f, ""}; Configurable cfgMuonTaggingChi2DiffLow{"cfgMuonTaggingChi2DiffLow", 100.f, ""}; //// Variables for ccdb @@ -422,6 +428,8 @@ struct QaMatching { struct CollisionInfo { int64_t index{0}; + // internal index of this collision in the derived table + int64_t reducedEventId{0}; uint64_t bc{0}; // z position of the collision double zVertex{0}; @@ -778,7 +786,7 @@ struct QaMatching { AxisSpec chi2Axis = {100, 0, 100, "matching #chi^{2}/NDF"}; AxisSpec scoreAxis = {100, 0, 1, "matching score"}; int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; - AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; + AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), ""}; histName = path + "matchType"; histTitle = "Match type"; fMatchType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {matchTypeAxis}}); @@ -911,7 +919,6 @@ struct QaMatching { std::map> fMatchingHistogramRegistries; std::map> fMatchingPlotters; std::unique_ptr fTaggedMuonsMatchingPlotter; - std::unique_ptr fSelectedMuonsMatchingPlotter; CollisionInfos fCollisionInfos; @@ -971,7 +978,6 @@ struct QaMatching { } fTaggedMuonsMatchingPlotter = std::make_unique(histPath + "Tagged/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); - fSelectedMuonsMatchingPlotter = std::make_unique(histPath + "Selected/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); } void createDimuonHistos() @@ -1127,6 +1133,8 @@ struct QaMatching { ccdbManager->get(geoPath); } + std::vector matchMethodLabels{"Prod"}; + // Matching functions initMatchingFunctions(); for (size_t funcId = 0; funcId < Chi2FunctionsNum; funcId++) { @@ -1137,13 +1145,15 @@ struct QaMatching { auto extrapMethod = configChi2MatchingOptions.matchingExtrapMethods[funcId]->value; if (label == "" || funcName == "") - break; + continue; matchingChi2Functions[label] = funcName; matchingScoreCuts[label] = scoreMin; matchingPlanesZ[label] = matchingPlaneZ; matchingExtrapMethod[label] = extrapMethod; + + matchMethodLabels.push_back(label); } // Matching ML models @@ -1163,7 +1173,7 @@ struct QaMatching { auto extrapMethod = configMlOptions.matchingExtrapMethods[modelId]->value; if (label == "" || modelPath == "" || inputFeatures.empty() || modelName == "") - break; + continue; matchingMlResponses[label].configure(binsPtMl, mycutsMl, cutDirMl, 1); matchingMlResponses[label].setModelPathsCCDB(std::vector{modelName}, fCCDBApi, std::vector{modelPath}, configCcdb.cfgCcdbNoLaterThan.value); @@ -1173,6 +1183,8 @@ struct QaMatching { matchingScoreCuts[label] = scoreMin; matchingPlanesZ[label] = matchingPlaneZ; matchingExtrapMethod[label] = extrapMethod; + + matchMethodLabels.push_back(label); } int nTrackTypes = static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MCHStandaloneTrack) + 1; @@ -1183,6 +1195,14 @@ struct QaMatching { registry.add("tracksMultiplicityMFT", "MFT tracks multiplicity", {HistType::kTH1F, {tracksMultiplicityAxis}}); registry.add("tracksMultiplicityMCH", "MCH tracks multiplicity", {HistType::kTH1F, {tracksMultiplicityAxis}}); + // Histogram for storing the index and label of the matching methods in the horizontal axis. + // This is needed in order to associate the proper label to the match method index in the derived tables. + AxisSpec matchMethodAxis = {static_cast(matchMethodLabels.size()), 0.0, static_cast(matchMethodLabels.size()), ""}; + auto matchMethodsHist = registry.add("matchMethods", "Match methods", {HistType::kTH1F, {matchMethodAxis}}); + for (size_t iLabel = 0; iLabel < matchMethodLabels.size(); iLabel++) { + std::get>(matchMethodsHist)->GetXaxis()->SetBinLabel(iLabel + 1, matchMethodLabels[iLabel].c_str()); + } + createMatchingHistosMc(); createDimuonHistos(); } @@ -1726,7 +1746,7 @@ struct QaMatching { } template - bool IsMuon(const TMCH& mchTrack, + bool isMuon(const TMCH& mchTrack, const TMFT& mftTrack) { // skip tracks that do not have an associated MC particle @@ -1748,7 +1768,7 @@ struct QaMatching { } template - bool IsMuon(const TMUON& muonTrack, + bool isMuon(const TMUON& muonTrack, TMUONS const& /*muonTracks*/, TMFTS const& /*mftTracks*/) { @@ -1758,7 +1778,7 @@ struct QaMatching { auto const& mchTrack = muonTrack.template matchMCHTrack_as(); auto const& mftTrack = muonTrack.template matchMFTTrack_as(); - return IsMuon(mchTrack, mftTrack); + return isMuon(mchTrack, mftTrack); } template @@ -1793,14 +1813,14 @@ struct QaMatching { return result; } - // for each MCH standalone track, collect the associated matching candidates + // tag muons based on the track quality and the track position at the front and back MFT planes template - void getSelectedMuons(const CollisionInfo& collisionInfo, - C const& collisions, - TMUON const& muonTracks, - std::vector& selectedMuons) + void getTaggedMuons(const CollisionInfo& collisionInfo, + C const& collisions, + TMUON const& muonTracks, + std::vector& taggedMuons) { - selectedMuons.clear(); + taggedMuons.clear(); for (const auto& muonTrack : muonTracks) { // only consider MCH-MID matches @@ -1833,52 +1853,17 @@ struct QaMatching { // propagate the track from the vertex to the first MFT plane const auto& extrapToMFTfirst = propagateToZMch(mchTrackAtVertex, o2::mft::constants::mft::LayerZCoordinate()[0]); double rFront = std::sqrt(extrapToMFTfirst.getX() * extrapToMFTfirst.getX() + extrapToMFTfirst.getY() * extrapToMFTfirst.getY()); - double rMinFront = 3.f; - double rMaxFront = 9.f; - if (rFront < rMinFront || rFront > rMaxFront) + if (rFront < cfgMuonTaggingRadiusAtMftFrontLow.value || rFront > cfgMuonTaggingRadiusAtMftFrontUp.value) continue; // propagate the track from the vertex to the last MFT plane const auto& extrapToMFTlast = propagateToZMch(mchTrackAtVertex, o2::mft::constants::mft::LayerZCoordinate()[9]); double rBack = std::sqrt(extrapToMFTlast.getX() * extrapToMFTlast.getX() + extrapToMFTlast.getY() * extrapToMFTlast.getY()); - double rMinBack = 5.f; - double rMaxBack = 12.f; - if (rBack < rMinBack || rBack > rMaxBack) + if (rBack < cfgMuonTaggingRadiusAtMftBackLow.value || rBack > cfgMuonTaggingRadiusAtMftBackUp.value) continue; int64_t muonTrackIndex = muonTrack.globalIndex(); - selectedMuons.emplace_back(muonTrackIndex); - } - } - - // for each MCH standalone track, collect the associated matching candidates - template - void getTaggedMuons(const CollisionInfo& collisionInfo, - TMUON const& muonTracks, - const std::vector& selectedMuons, - std::vector& taggedMuons) - { - taggedMuons.clear(); - for (const auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { - - // check if the current muon is selected - if (std::find(selectedMuons.begin(), selectedMuons.end(), mchIndex) == selectedMuons.end()) - continue; - - // if there is only one candidate, mark the muon as select - if (globalTracksVector.size() == 1) { - taggedMuons.emplace_back(mchIndex); - continue; - } - - auto const& muonTrack0 = muonTracks.rawIteratorAt(globalTracksVector[0].globalTrackId); - auto const& muonTrack1 = muonTracks.rawIteratorAt(globalTracksVector[1].globalTrackId); - - double chi2diff = muonTrack1.chi2MatchMCHMFT() - muonTrack0.chi2MatchMCHMFT(); - if (chi2diff < cfgMuonTaggingChi2DiffLow) - continue; - - taggedMuons.emplace_back(mchIndex); + taggedMuons.emplace_back(muonTrackIndex); } } @@ -2103,18 +2088,18 @@ struct QaMatching { return (track1.matchChi2 < track2.matchChi2); }; - for (auto collisionInfoIt = collisionInfos.begin(); collisionInfoIt != collisionInfos.end(); ++collisionInfoIt) { - auto& collisionInfo = collisionInfoIt->second; - for (auto matchingCandidatesIt = collisionInfo.matchingCandidates.begin(); matchingCandidatesIt != collisionInfo.matchingCandidates.end(); ++matchingCandidatesIt) { - auto& mchIndex = matchingCandidatesIt->first; - auto& globalTracksVector = matchingCandidatesIt->second; + int64_t reducedEventCounter{0}; + for (auto& [collisionIndex, collisionInfo] : collisionInfos) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) + // set the internal collision index + collisionInfo.reducedEventId = reducedEventCounter; + reducedEventCounter += 1; + for (auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingChi2); const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); auto mftMchMatchAttempts = getMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; - for (auto candidateIt = globalTracksVector.begin(); candidateIt != globalTracksVector.end(); ++candidateIt) { - auto& candidate = *candidateIt; + for (auto& candidate : globalTracksVector) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; @@ -2635,16 +2620,13 @@ struct QaMatching { return (track1.matchChi2 < track2.matchChi2); }; - for (auto matchingCandidatesIt = newMatchingCandidates.begin(); matchingCandidatesIt != newMatchingCandidates.end(); ++matchingCandidatesIt) { - auto& mchIndex = matchingCandidatesIt->first; - auto& globalTracksVector = matchingCandidatesIt->second; + for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingChi2); const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); auto mftMchMatchAttempts = getMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; - for (auto candidateIt = globalTracksVector.begin(); candidateIt != globalTracksVector.end(); ++candidateIt) { - auto& candidate = *candidateIt; + for (auto& candidate : globalTracksVector) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; @@ -2783,16 +2765,13 @@ struct QaMatching { return (track1.matchScore > track2.matchScore); }; - for (auto matchingCandidatesIt = newMatchingCandidates.begin(); matchingCandidatesIt != newMatchingCandidates.end(); ++matchingCandidatesIt) { - auto& mchIndex = matchingCandidatesIt->first; - auto& globalTracksVector = matchingCandidatesIt->second; + for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); auto mftMchMatchAttempts = getMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; - for (auto candidateIt = globalTracksVector.begin(); candidateIt != globalTracksVector.end(); ++candidateIt) { - auto& candidate = *candidateIt; + for (auto& candidate : globalTracksVector) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop) const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; @@ -2813,33 +2792,25 @@ struct QaMatching { { auto collision = collisions.rawIteratorAt(collisionInfo.index); - registry.get(HIST("tracksMultiplicityMFT"))->Fill(collisionInfo.mftTracks.size()); - registry.get(HIST("tracksMultiplicityMCH"))->Fill(collisionInfo.mchTracks.size()); - - // Chi2-based matching analysis - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); - for (const auto& [label, func] : matchingChi2Functions) { - MatchingCandidates matchingCandidates; - runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + std::vector taggedMuons; + getTaggedMuons(collisionInfo, collisions, muonTracks, taggedMuons); - auto* plotter = fMatchingPlotters.at(label).get(); - double matchingScoreCut = matchingScoreCuts.at(label); + int debugCounter{0}; + fillQaMatchingAodEventForCollision(collisionInfo, collision, collisionInfo.reducedEventId, debugCounter); + fillQaMatchingMchTracksForCollision(collisionInfo, collisions, collision, muonTracks, mftTracks, bcs, taggedMuons, collisionInfo.reducedEventId); - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); - } + registry.get(HIST("tracksMultiplicityMFT"))->Fill(collisionInfo.mftTracks.size()); + registry.get(HIST("tracksMultiplicityMCH"))->Fill(collisionInfo.mchTracks.size()); - // ML-based matching analysis - for (const auto& [label, mlResponse] : matchingMlResponses) { - MatchingCandidates matchingCandidates; - runMlMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + int matchingMethodCounter{0}; - auto* plotter = fMatchingPlotters.at(label).get(); - double matchingScoreCut = matchingScoreCuts.at(label); - - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); - } + //------------------------------- + // Chi2-based matching from production + fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); - // Muons tagging + //------------------------------- + // Tagged muons for (const auto& [mchIndex, mftIndex] : collisionInfo.matchablePairs) { auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); if (!mchTrack.has_collision()) @@ -2863,28 +2834,44 @@ struct QaMatching { registry.get(HIST("matching/MC/pairedMFTTracksAtMFT"))->Fill(mftTrackProp.getX(), mftTrackProp.getY()); } - std::vector selectedMuons; - getSelectedMuons(collisionInfo, collisions, muonTracks, selectedMuons); - - MatchingCandidates selectedMatchingCandidates; - for (const auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { - if (std::find(selectedMuons.begin(), selectedMuons.end(), mchIndex) != selectedMuons.end()) { - selectedMatchingCandidates[mchIndex] = globalTracksVector; - } - } - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, selectedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fSelectedMuonsMatchingPlotter.get()); - - std::vector taggedMuons; - getTaggedMuons(collisionInfo, muonTracks, selectedMuons, taggedMuons); - MatchingCandidates taggedMatchingCandidates; for (const auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { if (std::find(taggedMuons.begin(), taggedMuons.end(), mchIndex) != taggedMuons.end()) { taggedMatchingCandidates[mchIndex] = globalTracksVector; } } + matchingMethodCounter += 1; + fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fTaggedMuonsMatchingPlotter.get()); + //------------------------------- + // Custom chi2-based matching methods + for (const auto& [label, func] : matchingChi2Functions) { + MatchingCandidates matchingCandidates; + runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + + auto* plotter = fMatchingPlotters.at(label).get(); + double matchingScoreCut = matchingScoreCuts.at(label); + + matchingMethodCounter += 1; + fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); + } + + // ML-based matching analysis + for (const auto& [label, mlResponse] : matchingMlResponses) { + MatchingCandidates matchingCandidates; + runMlMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + + auto* plotter = fMatchingPlotters.at(label).get(); + double matchingScoreCut = matchingScoreCuts.at(label); + + matchingMethodCounter += 1; + fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); + } + + //------------------------------- // Di-muon analysis fillDimuonPlotsMc(collisionInfo, collisions, muonTracks, mftTracks); } @@ -2956,6 +2943,7 @@ struct QaMatching { TMUON const& muonTracks, TMFT const& mftTracks, TBC const& bcs, + const std::vector& taggedMuons, int32_t reducedEventId) { std::vector mchIds; @@ -2975,6 +2963,10 @@ struct QaMatching { auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); int mftMchMatchAttempts = getMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); auto mchTrackAtVertex = VarManager::PropagateMuon(mchTrack, collision, VarManager::kToVertex); + bool isTagged = false; + if (std::find(taggedMuons.begin(), taggedMuons.end(), mchIndex) != taggedMuons.end()) { + isTagged = true; + } qaMatchingMCHTrack( reducedEventId, mchIndex, @@ -2984,6 +2976,7 @@ struct QaMatching { static_cast(mchTrack.eta()), static_cast(mchTrack.phi()), static_cast(mftMchMatchAttempts), + isTagged, static_cast(mchTrackAtVertex.getX()), static_cast(mchTrackAtVertex.getY()), static_cast(mchTrackAtVertex.getZ()), @@ -3007,55 +3000,12 @@ struct QaMatching { registry.get(HIST("nTracksPerType"))->Fill(static_cast(muon.trackType())); } - fillCollisions(collisions, bcs, muonTracks, mftTracks, fCollisionInfos); - mftTrackCovs.clear(); for (const auto& mftTrackCov : mftCovs) { mftTrackCovs[mftTrackCov.matchMFTTrackId()] = mftTrackCov.globalIndex(); } - std::unordered_map reducedEventIds; - int32_t reducedEventCounter = 0; - for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - reducedEventIds.emplace(collisionInfo.index, reducedEventCounter); - reducedEventCounter += 1; - } - - int debugCounter = 0; - for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - auto it = reducedEventIds.find(collisionInfo.index); - if (it == reducedEventIds.end()) { - continue; - } - int32_t reducedEventId = it->second; - auto collision = collisions.rawIteratorAt(collisionInfo.index); - fillQaMatchingAodEventForCollision(collisionInfo, collision, reducedEventId, debugCounter); - fillQaMatchingMchTracksForCollision(collisionInfo, collisions, collision, muonTracks, mftTracks, bcs, reducedEventId); - } - - struct AodLabel { - const char* name; - int8_t id; - }; - std::array aodLabels{{{"ProdAll", 0}, {"MatchXYPhiTanl", 1}, {"MatchXYPhiTanlMom", 2}}}; - for (const auto& aodLabel : aodLabels) { - if (matchingChi2Functions.find(aodLabel.name) == matchingChi2Functions.end()) { - LOGF(warn, "[AO2D] Chi2 label not found: %s", aodLabel.name); - continue; - } - debugCounter = 0; - for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - auto it = reducedEventIds.find(collisionInfo.index); - if (it == reducedEventIds.end()) { - continue; - } - int32_t reducedEventId = it->second; - MatchingCandidates matchingCandidates; - runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, aodLabel.name, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); - auto collision = collisions.rawIteratorAt(collisionInfo.index); - fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, aodLabel.id, reducedEventId); - } - } + fillCollisions(collisions, bcs, muonTracks, mftTracks, fCollisionInfos); for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { processCollisionMc(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); From 9df703eb5b2d812d6908b4848a4b300107aaa937 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Fri, 22 May 2026 16:42:27 +0200 Subject: [PATCH 266/449] [PWGCF] Add secondary decay for resonance efficiencies (#16329) --- PWGCF/Flow/Tasks/flowMc.cxx | 51 ++++++++++- .../Tasks/flowGenericFramework.cxx | 91 +++++++++++++------ 2 files changed, 110 insertions(+), 32 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index 847da3642fb..ed371aa5a3a 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -100,6 +100,8 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgCentVsIPTruth, std::string, "", "CCDB path to centrality vs IP truth") O2_DEFINE_CONFIGURABLE(cfgIsGlobalTrack, bool, false, "Use global tracks instead of hasTPC&&hasITS") O2_DEFINE_CONFIGURABLE(cfgK0Lambda0Enabled, bool, false, "Add K0 and Lambda0, for bulk particle efficiency please keep off") + O2_DEFINE_CONFIGURABLE(cfgAcceptSecondaries, bool, false, "Accept secondary particles produced from decays") + O2_DEFINE_CONFIGURABLE(cfgRequireTOF, bool, false, "Require that reconstructed tracks have TOF for resonance decays") O2_DEFINE_CONFIGURABLE(cfgFlowCumulantEnabled, bool, false, "switch of calculating flow") O2_DEFINE_CONFIGURABLE(cfgFlowCumulantNbootstrap, int, 30, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") @@ -238,6 +240,12 @@ struct FlowMc { histos.add("hPtNchGlobalK0", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); histos.add("hPtNchGeneratedLambda", "Reco production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); histos.add("hPtNchGlobalLambda", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGeneratedK0Pions", "Reco production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGlobalK0Pions", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGeneratedLambdaPions", "Reco production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGlobalLambdaPions", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGeneratedLambdaProtons", "Reco production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); + histos.add("hPtNchGlobalLambdaProtons", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); histos.add("hPtMCGen", "Monte Carlo Truth; pT (GeV/c);", {HistType::kTH1D, {axisPt}}); histos.add("hEtaPtVtxzMCGen", "Monte Carlo Truth; #eta; p_{T} (GeV/c); V_{z} (cm);", {HistType::kTH3D, {axisEta, axisPt, axisVertex}}); histos.add("hPtMCGlobal", "Monte Carlo Global; pT (GeV/c);", {HistType::kTH1D, {axisPt}}); @@ -599,8 +607,13 @@ struct FlowMc { if (extraPDGType && pdgCode != PDG_t::kElectron && pdgCode != PDG_t::kMuonMinus && pdgCode != PDG_t::kPiPlus && pdgCode != kKPlus && pdgCode != PDG_t::kProton) continue; - if (!mcParticle.isPhysicalPrimary()) + bool isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + const int producedByDecay = 4; + bool isSecondary = (mcParticle.has_mothers() && mcParticle.getProcess() == producedByDecay); + bool isAcceptedSecondary = (cfgAcceptSecondaries) ? isSecondary : false; + if (!isPhysicalPrimary && !isAcceptedSecondary) continue; + if (std::fabs(mcParticle.eta()) > cfgCutEta) // main acceptance continue; @@ -621,11 +634,23 @@ struct FlowMc { histos.fill(HIST("hPtNchGeneratedK0"), mcParticle.pt(), nChGlobal); if (pdgCode == PDG_t::kLambda0) histos.fill(HIST("hPtNchGeneratedLambda"), mcParticle.pt(), nChGlobal); - + if (mcParticle.has_daughters()) { + for (const auto& d : mcParticle.template daughters_as()) { + if (std::abs(d.pdgCode()) == PDG_t::kPiPlus) { + if (pdgCode == PDG_t::kK0Short) + histos.fill(HIST("hPtNchGeneratedK0Pions"), d.pt(), nChGlobal); + if (pdgCode == PDG_t::kLambda0) + histos.fill(HIST("hPtNchGeneratedLambdaPions"), d.pt(), nChGlobal); + } + if (pdgCode == PDG_t::kLambda0 && std::abs(d.pdgCode()) == PDG_t::kProton) + histos.fill(HIST("hPtNchGeneratedLambdaProtons"), d.pt(), nChGlobal); + } + } nCh++; bool validGlobal = false; bool validTrack = false; + bool validTOFTrack = false; bool validTPCTrack = false; bool validITSTrack = false; bool validITSABTrack = false; @@ -643,6 +668,9 @@ struct FlowMc { if (!cfgIsGlobalTrack && track.hasTPC() && track.hasITS()) { validGlobal = true; } + if (track.hasTOF() && validGlobal) { + validTOFTrack = true; + } if (track.hasTPC() || track.hasITS()) { validTrack = true; } @@ -657,7 +685,6 @@ struct FlowMc { } } } - bool withinPtRef = (cfgCutPtRefMin < mcParticle.pt()) && (mcParticle.pt() < cfgCutPtRefMax); // within RF pT range bool withinPtPOI = (cfgCutPtPOIMin < mcParticle.pt()) && (mcParticle.pt() < cfgCutPtPOIMax); // within POI pT range if (cfgOutputNUAWeights && withinPtRef) @@ -723,6 +750,24 @@ struct FlowMc { histos.fill(HIST("hPtNchGlobalK0"), mcParticle.pt(), nChGlobal); if (pdgCode == PDG_t::kLambda0) histos.fill(HIST("hPtNchGlobalLambda"), mcParticle.pt(), nChGlobal); + if (!cfgRequireTOF || (cfgRequireTOF && validTOFTrack)) { + if (mcParticle.has_mothers()) { + for (const auto& m : mcParticle.template mothers_as()) { + if (!m.isPhysicalPrimary()) + continue; + if (pdgCode == PDG_t::kPiPlus) { + if (m.pdgCode() == PDG_t::kK0Short) { + histos.fill(HIST("hPtNchGlobalK0Pions"), mcParticle.pt(), nChGlobal); + } + if (m.pdgCode() == PDG_t::kLambda0) { + histos.fill(HIST("hPtNchGlobalLambdaPions"), mcParticle.pt(), nChGlobal); + } + } + if (pdgCode == PDG_t::kProton && m.pdgCode() == PDG_t::kLambda0) + histos.fill(HIST("hPtNchGlobalLambdaProtons"), mcParticle.pt(), nChGlobal); + } + } + } } // if any track present, fill if (validTrack) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 7135225d44d..6f25a702eea 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -157,7 +157,10 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgUsePID, bool, true, "Enable PID information") O2_DEFINE_CONFIGURABLE(cfgUseGapMethod, bool, false, "Use gap method in vn-pt calculations") - O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFractionWeights, bool, false, "Enable or disable the use of multiplicity-based event weighting for the spectral fraction"); + } cfgEventWeight; O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgUsePIDEfficiencies, bool, false, "Use species dependent efficiencies") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") @@ -172,6 +175,7 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0105 + 0.0350/(x^1.1))", "Functional form of pt-dependent 7 sigma DCAxy cut"); O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 50, "Cut on number of TPC clusters found"); O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); @@ -447,6 +451,9 @@ struct FlowGenericFramework { TF1* fPhiCutLow = nullptr; TF1* fPhiCutHigh = nullptr; + // Track selection - DCA xy function + TF1* fPtDepDCAxy = nullptr; + void init(InitContext const&) { LOGF(info, "FlowGenericFramework::init()"); @@ -773,6 +780,10 @@ struct FlowGenericFramework { fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); fFCpt->initialiseSubevent(multAxis, cfgMpar, o2::analysis::gfw::etagapsPtPt.size(), cfgNbootstrap); + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgTrackCuts.cfgDCAxy->c_str()), 0.001, 100); + fPtDepDCAxy->SetParameter(0, cfgTrackCuts.cfgDCAxyNSigma / 7.); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgTrackCuts.cfgDCAxy->c_str())); + // Multiplicity correlation cuts if (cfgMultCut) { fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrCuts.cfgMultCorrLowCutFunction->c_str(), 0, 100); @@ -1198,7 +1209,7 @@ struct FlowGenericFramework { if (cfgFill.cfgFillQA) registryQA.fill(HIST("trackQA/after/pt_phi"), track.pt(), phimodn); } - if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgTrackCuts.cfgDCAxyNSigma / 7. * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1)))) + if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > fPtDepDCAxy->Eval(track.pt()))) return false; return ((track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgNTPCXrows) && (track.tpcNClsFound() >= cfgTrackCuts.cfgNTPCCls) && (track.itsNCls() >= cfgTrackCuts.cfgMinNITSCls)); } @@ -1206,7 +1217,9 @@ struct FlowGenericFramework { template bool nchSelected(TTrack track) { - if (std::fabs(track.dcaXY()) > (0.0105f + 0.035f / std::pow(track.pt(), 1.1))) + // Renormalise to default cut + const float defaultNsigma = 7; + if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > defaultNsigma / cfgTrackCuts.cfgDCAxyNSigma * fPtDepDCAxy->Eval(track.pt()))) return false; int tpcNClsCrossedRowsDefault = 70; int tpcNClsFoundDefault = 50; @@ -1333,7 +1346,9 @@ struct FlowGenericFramework { continue; auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; if (std::abs(val) < 1) { - (dt == Gen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + if (corrconfigs.at(l_ind).Head.find("3pcW") != std::string::npos && cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= histosNpt[ChargedID]->Integral(); + (dt == Gen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); if (cfgUseGapMethod) { fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); } @@ -1346,16 +1361,17 @@ struct FlowGenericFramework { continue; auto val = fGFW->Calculate(corrconfigs.at(l_ind), i - 1, kFALSE).real() / dnx; if (std::abs(val) < 1) - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); } } - if (histosNpt[ChargedID]->Integral() <= 0) + double dnCh = histosNpt[ChargedID]->Integral(); + if (dnCh <= 0) return; - double dnPi = histosNpt[ChargedID]->Integral(); - double dnKa = histosNpt[ChargedID]->Integral(); - double dnPr = histosNpt[ChargedID]->Integral(); + double dnPi = dnCh; + double dnKa = dnCh; + double dnPr = dnCh; if (cfgUsePIDTotal) { dnPi = histosNpt[PionID]->Integral(); @@ -1364,20 +1380,20 @@ struct FlowGenericFramework { } for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { - registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ChargedID]->GetBinContent(i) / histosNpt[ChargedID]->Integral()); + registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ChargedID]->GetBinContent(i) / dnCh, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnCh : 1.0); if (dnPi > 0) - registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PionID]->GetBinContent(i) / dnPi); + registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PionID]->GetBinContent(i) / dnPi, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnPi : 1.0); if (dnKa > 0) - registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i), centmult, histosNpt[KaonID]->GetBinContent(i) / dnKa); + registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i), centmult, histosNpt[KaonID]->GetBinContent(i) / dnKa, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnKa : 1.0); if (dnPr > 0) - registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ProtonID]->GetBinContent(i) / dnPr); + registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ProtonID]->GetBinContent(i) / dnPr, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnPr : 1.0); } if (corrconfigsV02.size() < SpeciesCount) return; // For alternative normalisation with integrated pid spectra - std::vector dns = {histosNpt[ChargedID]->Integral(), dnPi, dnKa, dnPr}; + std::vector dns = {dnCh, dnPi, dnKa, dnPr}; for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { @@ -1385,8 +1401,11 @@ struct FlowGenericFramework { if (dnx == 0) continue; auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; - if (std::abs(val) < 1 && dns[l_ind] > 0) - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + if (std::abs(val) < 1 && dns[l_ind] > 0) { + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + } } } @@ -1394,15 +1413,18 @@ struct FlowGenericFramework { return; double mpt = 0; + double dnx = 0; if (cfgEtaPtPt->first * cfgEtaPtPt->second >= 0) { if (fFCpt->corrDen[1] == 0.) return; - mpt = fFCpt->corrNum[1] / fFCpt->corrDen[1]; + dnx = fFCpt->corrDen[1]; + mpt = fFCpt->corrNum[1] / dnx; } else { if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) return; double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; + dnx = 0.5 * (fFCpt->corrDenSub[0][1] + fFCpt->corrDenSub[1][1]); mpt = 0.5 * (mptSub1 + mptSub2); } if (std::isnan(mpt)) @@ -1410,8 +1432,11 @@ struct FlowGenericFramework { for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - if (dns[l_ind] > 0) - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], 1., rndm); + if (dns[l_ind] > 0) { + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], (cfgEventWeight.cfgUseMultiplicityFlowWeights) ?: 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], (cfgEventWeight.cfgUseMultiplicityFlowWeights) ?: 1., rndm); + } } } return; @@ -1589,17 +1614,17 @@ struct FlowGenericFramework { for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { if (dnK0SB1 > 0) - registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband1]->GetBinContent(i) / dnK0SB1); + registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband1]->GetBinContent(i) / dnK0SB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB1 : 1.); if (dnK0Sig > 0) - registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Signal]->GetBinContent(i) / dnK0Sig); + registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Signal]->GetBinContent(i) / dnK0Sig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0Sig : 1.); if (dnK0SB2 > 0) - registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband2]->GetBinContent(i) / dnK0SB2); + registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband2]->GetBinContent(i) / dnK0SB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB2 : 1.); if (dnLambdaSB1 > 0) - registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband1]->GetBinContent(i) / dnLambdaSB1); + registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband1]->GetBinContent(i) / dnLambdaSB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB1 : 1.); if (dnLambdaSig > 0) - registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSignal]->GetBinContent(i) / dnLambdaSig); + registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSignal]->GetBinContent(i) / dnLambdaSig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSig : 1.); if (dnLambdaSB2 > 0) - registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband2]->GetBinContent(i) / dnLambdaSB2); + registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband2]->GetBinContent(i) / dnLambdaSB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB2 : 1.); } std::vector dns = {dnK0SB1, dnK0Sig, dnK0SB2, dnLambdaSB1, dnLambdaSig, dnLambdaSB2}; @@ -1610,8 +1635,11 @@ struct FlowGenericFramework { if (dnx == 0) continue; auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; - if (std::abs(val) < 1 && dns[l_ind - 4] > 0) - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom); + if (std::abs(val) < 1 && dns[l_ind - 4] > 0) { + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind - 4]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom); + } } } @@ -1619,15 +1647,18 @@ struct FlowGenericFramework { return; double mpt = 0; + double dnx = 0; if (cfgEtaPtPt->first * cfgEtaPtPt->second >= 0) { if (fFCpt->corrDen[1] == 0.) return; - mpt = fFCpt->corrNum[1] / fFCpt->corrDen[1]; + dnx = fFCpt->corrDen[1]; + mpt = fFCpt->corrNum[1] / dnx; } else { if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) return; double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; + dnx = 0.5 * (fFCpt->corrDenSub[0][1] + fFCpt->corrDenSub[1][1]); mpt = 0.5 * (mptSub1 + mptSub2); } @@ -1637,7 +1668,9 @@ struct FlowGenericFramework { for (uint l_ind = 4; l_ind < corrconfigsV0.size(); ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { if (dns[l_ind] > 0) - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom); + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind - 4]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom); } } } From d9435517f31d3c60f00029fa98b4b0a9006e4317 Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Fri, 22 May 2026 23:42:55 +0200 Subject: [PATCH 267/449] [PWGLF] Fix rapidity cut to use asymmetric range (#16353) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/chk892LI.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chk892LI.cxx b/PWGLF/Tasks/Resonances/chk892LI.cxx index 16f96d876b8..6fcf8f03b42 100644 --- a/PWGLF/Tasks/Resonances/chk892LI.cxx +++ b/PWGLF/Tasks/Resonances/chk892LI.cxx @@ -963,7 +963,7 @@ struct Chk892LI { continue; if (std::abs(part.pdgCode()) != kKstarPlus) continue; - if (std::abs(part.y()) > KstarCuts.cfgKstarMaxRap) + if (part.y() < KstarCuts.cfgKstarMinRap || part.y() > KstarCuts.cfgKstarMaxRap) continue; const int pionWanted = (part.pdgCode() > 0) ? +kPiPlus : -kPiPlus; @@ -1079,7 +1079,7 @@ struct Chk892LI { const double ptreco = lResoKstar.Pt(); const double yreco = lResoKstar.Rapidity(); - if (std::abs(yreco) > KstarCuts.cfgKstarMaxRap) + if (yreco < KstarCuts.cfgKstarMinRap || yreco > KstarCuts.cfgKstarMaxRap) continue; double ptgen = 0, ygen = 0; @@ -1102,7 +1102,7 @@ struct Chk892LI { continue; if (std::abs(part.pdgCode()) != kKstarPlus) continue; - if (std::abs(part.y()) > KstarCuts.cfgKstarMaxRap) + if (part.y() < KstarCuts.cfgKstarMinRap || part.y() > KstarCuts.cfgKstarMaxRap) continue; const auto mcid = part.mcCollisionId(); @@ -1141,7 +1141,7 @@ struct Chk892LI { continue; if (std::abs(part.pdgCode()) != kKstarPlus) continue; - if (std::abs(part.y()) > KstarCuts.cfgKstarMaxRap) + if (part.y() < KstarCuts.cfgKstarMinRap || part.y() > KstarCuts.cfgKstarMaxRap) continue; const auto mcid = part.mcCollisionId(); From 6de9312b0ca315d963a6444c74a01a9b5838f610 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Fri, 22 May 2026 23:46:50 +0200 Subject: [PATCH 268/449] [PWGEM/PhotonMeson] Add histograms for resolution studies (#16355) Co-authored-by: jokonig --- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 264808e451a..b8824222deb 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -90,6 +90,7 @@ struct PCMQCMC { Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + Configurable cfgResolDetailPlots{"cfgResolDetailPlots", false, "flag to enable detailed resolution plots"}; EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { @@ -248,6 +249,9 @@ struct PCMQCMC { fRegistry.add("Generated/hRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); fRegistry.add("Generated/hRPhi", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, o2::constants::math::TwoPI}, {400, 0, 100}}, true); fRegistry.add("Generated/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, true); + if (cfgResolDetailPlots) { + fRegistry.add("Generated/hPtEtaPhi", "Photon pt vs eta, and phi;p_{T, gen} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } } // event info @@ -297,8 +301,8 @@ struct PCMQCMC { fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); fRegistry.add("V0/primary/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); fRegistry.add("V0/primary/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); @@ -306,6 +310,12 @@ struct PCMQCMC { fRegistry.add("V0/primary/hXY_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); fRegistry.add("V0/primary/hRZ_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); + if (cfgResolDetailPlots) { + fRegistry.add("V0/primary/hEtaPhiResol", "Photon eta-phi resolution;p_{T} (GeV/c);#eta-diff;#phi-diff", kTH3F, {{200, 0., 20.}, {99, -0.049, 0.049}, {99, -0.049, 0.049}}, false); + fRegistry.add("V0/primary/hPtResolPtEtaPhi", "Photon resolution vs. pt, eta, and phi;p_{T_rec} - p_{T true} / p_{T true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hMomResolPtEtaPhi", "Photon momentum resolution vs. p, eta, and phi;p_{rec} - p_{true} / p_{true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hPtEtaPhi", "pt, eta, and phi;p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } if (pcmcuts.cfg_apply_ml_cuts) { if (pcmcuts.cfg_nclasses_ml == 2) { fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); @@ -514,6 +524,16 @@ struct PCMQCMC { fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY_MC"), mcleg.vx(), mcleg.vy()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ_MC"), mcleg.vz(), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); + if (cfgResolDetailPlots) { + // Resolution vs. pt, eta and phi + float resolPt = (v0.pt() - mcphoton.pt()) / mcphoton.pt(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolPtEtaPhi"), resolPt, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + float resolMom = (v0.p() - mcphoton.p()) / mcphoton.p(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMomResolPtEtaPhi"), resolMom, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtEtaPhi"), mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhiResol"), mcphoton.pt(), v0.eta() - mcphoton.eta(), v0.phi() - mcphoton.phi()); + } + float phi_cp = std::atan2(v0.vy(), v0.vx()); o2::math_utils::bringTo02Pi(phi_cp); float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); @@ -751,6 +771,9 @@ struct PCMQCMC { } if (std::abs(mctrack.pdgCode()) == PDG_t::kGamma && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + if (cfgResolDetailPlots) { + fRegistry.fill(HIST("Generated/hPtEtaPhi"), mctrack.pt(), mctrack.eta(), mctrack.phi()); // fill for all generated photons before any kinematic cut + } auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); float phi_cp = std::atan2(daughter.vy(), daughter.vx()); From 018a4b68f35ba0d62034d251a7b96d4aaec73319 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 23 May 2026 12:30:34 +0200 Subject: [PATCH 269/449] [PWGEM/Dilepton] reject diquarks for taggingHFE (#16357) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 24 ++++++++++++------------ PWGEM/Dilepton/Utils/MCUtilities.h | 10 ++++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 24d3d72165a..28b186210c1 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -169,11 +169,11 @@ struct taggingHFE { Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3, "max n sigma ka in TPC"}; Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -3, "min n sigma ka in TOF"}; Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +3, "max n sigma ka in TOF"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; - Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; - Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; - Configurable requirePiKaPr{"requirePiKaPr", true, "require hadron to be pion or kaon or proton"}; + // Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3, "min n sigma pr in TPC"}; + // Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3, "max n sigma pr in TPC"}; + // Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -3, "min n sigma pr in TOF"}; + // Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +3, "max n sigma pr in TOF"}; + Configurable requirePiKa{"requirePiKa", true, "require hadron to be pion or kaon or proton"}; Configurable applyTOFif{"applyTOFif", false, "apply TOFif for hadron identification"}; } hadronCut; @@ -477,23 +477,23 @@ struct taggingHFE { } template - bool isPiKaPr(TCollision const& collision, TTrack const& track) + bool isPiKa(TCollision const& collision, TTrack const& track) { float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; - float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + // float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; bool is_pi_included_TPC = hadronCut.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < hadronCut.cfg_max_TPCNsigmaPi; bool is_pi_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < hadronCut.cfg_max_TOFNsigmaPi) : true; bool is_ka_included_TPC = hadronCut.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < hadronCut.cfg_max_TPCNsigmaKa; bool is_ka_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < hadronCut.cfg_max_TOFNsigmaKa) : true; - bool is_pr_included_TPC = hadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < hadronCut.cfg_max_TPCNsigmaPr; - bool is_pr_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < hadronCut.cfg_max_TOFNsigmaPr) : true; + // bool is_pr_included_TPC = hadronCut.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < hadronCut.cfg_max_TPCNsigmaPr; + // bool is_pr_included_TOF = track.hasTOF() ? (hadronCut.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < hadronCut.cfg_max_TOFNsigmaPr) : true; if (!hadronCut.applyTOFif) { is_pi_included_TOF = true; is_ka_included_TOF = true; - is_pr_included_TOF = true; + // is_pr_included_TOF = true; } - return (is_pi_included_TPC && is_pi_included_TOF) || (is_ka_included_TPC && is_ka_included_TOF) || (is_pr_included_TPC && is_pr_included_TOF); + return (is_pi_included_TPC && is_pi_included_TOF) || (is_ka_included_TPC && is_ka_included_TOF) /* || (is_pr_included_TPC && is_pr_included_TOF)*/; } template @@ -730,7 +730,7 @@ struct taggingHFE { return false; } - if (hadronCut.requirePiKaPr && !isPiKaPr(collision, track)) { + if (hadronCut.requirePiKa && !isPiKa(collision, track)) { return false; } diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index 7b28d713aa5..b7c00447a35 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -130,6 +130,11 @@ bool isCharmBaryon(T const& track) return false; } + // reject diquarks + if (std::abs(track.pdgCode()) == 4101 || std::abs(track.pdgCode()) == 4103 || std::abs(track.pdgCode()) == 4201 || std::abs(track.pdgCode()) == 4203 || std::abs(track.pdgCode()) == 4301 || std::abs(track.pdgCode()) == 4303 || std::abs(track.pdgCode()) == 4403) { + return false; + } + if (4000 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 5000) { return true; } else { @@ -193,6 +198,11 @@ bool isBeautyBaryon(T const& track) return false; } + // reject diquarks + if (std::abs(track.pdgCode()) == 5101 || std::abs(track.pdgCode()) == 5103 || std::abs(track.pdgCode()) == 5201 || std::abs(track.pdgCode()) == 5203 || std::abs(track.pdgCode()) == 5301 || std::abs(track.pdgCode()) == 5303 || std::abs(track.pdgCode()) == 5401 || std::abs(track.pdgCode()) == 5403 || std::abs(track.pdgCode()) == 5503) { + return false; + } + if (5000 < std::abs(track.pdgCode()) && std::abs(track.pdgCode()) < 6000) { return true; } else { From 3531108d1c7396d410c2f9e410e5c6819b4aaea9 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 23 May 2026 22:43:52 +0200 Subject: [PATCH 270/449] [PWGEM/Dilepton] add eventTable for taggingHFE (#16359) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 19 +++++++++++------ PWGEM/Dilepton/Tasks/taggingHFE.cxx | 27 ++++++++++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index dd9001ab964..77245cee69d 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -199,8 +199,15 @@ namespace emmlevent { DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of mc collision } // namespace emmlevent + +DECLARE_SOA_TABLE(EMMLEvents, "AOD", "EMMLEVENT", //! + o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange); +// iterators +using EMMLEvent = EMMLEvents::iterator; + namespace emmltrack { +DECLARE_SOA_INDEX_COLUMN(EMMLEvent, emmlevent); //! index to event table DECLARE_SOA_COLUMN(IsMotherFromBeauty, isMotherFromBeauty, bool); //! is b quark included in decay history DECLARE_SOA_COLUMN(Signed1PtL, signedPtL, float); //! sign/pT of lepton DECLARE_SOA_COLUMN(EtaL, etaL, float); //! eta of lepton @@ -215,8 +222,8 @@ DECLARE_SOA_COLUMN(IsCorrectCollision, isCorrectCollision, bool); //! LH pair is } // namespace emmltrack DECLARE_SOA_TABLE(EMMLLeptons, "AOD", "EMMLLEPTON", //! - o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmlevent::SubGeneratorId, - emmltrack::Signed1PtL, emmltrack::EtaL, + o2::soa::Index<>, emmltrack::EMMLEventId, emmlevent::SubGeneratorId, + emmltrack::Signed1PtL, emmltrack::EtaL, emmltrack::PhiL, emmltrack::ImpParXYL, emmltrack::ImpParZL, emmltrack::ImpParCYYL, emmltrack::ImpParCZYL, emmltrack::ImpParCZZL, emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother, emmltrack::IsCorrectCollision); // iterators @@ -224,7 +231,7 @@ using EMMLLepton = EMMLLeptons::iterator; namespace emmllhpair { -DECLARE_SOA_INDEX_COLUMN(EMMLLepton, emmllepton); //! most propable emeventId +DECLARE_SOA_INDEX_COLUMN(EMMLLepton, emmllepton); //! index to lepton table DECLARE_SOA_COLUMN(Signed1PtH, signedPtH, float); //! sign/pT of associated hadron DECLARE_SOA_COLUMN(PtH, ptH, float); //! pT of associated hadron @@ -276,7 +283,7 @@ DECLARE_SOA_COLUMN(PdgCodeIM, pdgCodeIM, int); //! pdg code of DECLARE_SOA_COLUMN(FoundCommonMother, foundCommonMother, bool); //! decay length resolution of LH pair } // namespace emmllhpair -DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! +DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! emmllhpair::EMMLLeptonId, emmllhpair::Signed1PtH, emmllhpair::EtaH, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, @@ -288,7 +295,7 @@ DECLARE_SOA_TABLE(EMMLLHPairs, "AOD", "EMMLLHPAIR", //! emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators -using EMMLLHPair = EMMLLHPairs::iterator; +using EMMLLTPair = EMMLLTPairs::iterator; DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::EMMLLeptonId, emmllhpair::V0Type, @@ -302,7 +309,7 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! // iterators using EMMLLV0Pair = EMMLLV0Pairs::iterator; -DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCAPAIR", //! +DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::EMMLLeptonId, emmllhpair::CascadeType, emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 28b186210c1..ac395fbe2fc 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -87,8 +87,9 @@ struct taggingHFE { using MyV0s = soa::Join; using MyCascades = soa::Join; + Produces eventTable; Produces leptonTable; - Produces emmllhpair; + Produces emmlltpair; Produces emmllv0pair; Produces emmllcascpair; @@ -1621,6 +1622,7 @@ struct taggingHFE { } } // end of cascade loop + int npos = 0; for (const auto& positronId : positronIds) { auto pos = tracks.rawIteratorAt(positronId); mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -1648,8 +1650,9 @@ struct taggingHFE { continue; } - leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision_mcpos.getSubGeneratorId(), - leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), + npos++; + leptonTable(eventTable.lastIndex() + 1, mcCollision_mcpos.getSubGeneratorId(), + leptonParCov.getQ2Pt(), leptonParCov.getEta(), RecoDecay::constrainAngle(leptonParCov.getPhi(), 0, 1U), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), isMotherFromB, mcMother.pdgCode(), isCorrectCollision); // D0 -> e+ nu_e K-, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 @@ -1701,7 +1704,7 @@ struct taggingHFE { float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - emmllhpair(leptonTable.lastIndex(), + emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, @@ -1760,7 +1763,7 @@ struct taggingHFE { float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - emmllhpair(leptonTable.lastIndex(), + emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, @@ -2044,6 +2047,7 @@ struct taggingHFE { } // end of main positron sample + int nele = 0; for (const auto& electronId : electronIds) { auto ele = tracks.rawIteratorAt(electronId); mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -2071,8 +2075,9 @@ struct taggingHFE { continue; } - leptonTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), mcCollision_mcele.getSubGeneratorId(), - leptonParCov.getQ2Pt(), leptonParCov.getEta(), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), + nele++; + leptonTable(eventTable.lastIndex() + 1, mcCollision_mcele.getSubGeneratorId(), + leptonParCov.getQ2Pt(), leptonParCov.getEta(), RecoDecay::constrainAngle(leptonParCov.getPhi(), 0, 1U), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), isMotherFromB, mcMother.pdgCode(), isCorrectCollision); for (const auto& kaonId : kaonMinusIds) { @@ -2123,7 +2128,7 @@ struct taggingHFE { float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - emmllhpair(leptonTable.lastIndex(), + emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, @@ -2183,7 +2188,7 @@ struct taggingHFE { float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - emmllhpair(leptonTable.lastIndex(), + emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, @@ -2466,6 +2471,10 @@ struct taggingHFE { } // end of main electron sample + if (npos + nele > 0) { // fill eventTable only if at least 1 electron or positron exists. + eventTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + } + electronIds.clear(); electronIds.shrink_to_fit(); positronIds.clear(); From 8f4c85b5128b1d70060e62f9acad16e7ed0c82be Mon Sep 17 00:00:00 2001 From: Florian Eisenhut <53603353+feisenhu@users.noreply.github.com> Date: Sat, 23 May 2026 23:46:13 +0200 Subject: [PATCH 271/449] [PWGEM] Add b2cc2ll signal to generated output (#16360) --- PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx index b6e0118bd15..bbd9f9b77f6 100644 --- a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -454,6 +454,7 @@ struct checkMCPairTemplate { fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2l_diffb/"); // LS fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2cc2l_b2c2l/"); fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2cc2l_b2cc2l/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2cc2ll/"); // for charmed hadrons // create 28 combinations static constexpr std::string_view charmed_mesons[] = {"Dplus", "D0", "Dsplus"}; // 411, 421, 431 @@ -2518,6 +2519,9 @@ struct checkMCPairTemplate { case static_cast(EM_HFeeType::kBCCe_BCCe): fillGenHistograms<21>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2cc2l_b2cc2l break; + case static_cast(EM_HFeeType::kBCCee): + fillGenHistograms<22>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2cc2ll + break; default: break; } From 10282dfc1d82737a4801524df88900cb838e6963 Mon Sep 17 00:00:00 2001 From: ynishida-style Date: Sun, 24 May 2026 07:05:14 +0900 Subject: [PATCH 272/449] [PWGJE] Add the pt axis to event counting histogram in jetShape.cxx (#16354) --- PWGJE/Tasks/jetShape.cxx | 47 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index f0f8c6f4574..0df2ae24253 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -145,11 +145,6 @@ struct JetShapeTask { registry.add("trackTpcNClsFound", "trackTpcNClsFound", HistType::kTH1F, {{100, 0, 200}}); registry.add("trackItsNCls", "trackItsNCls", HistType::kTH1F, {{10, 0, 10}}); - registry.add("jetTpcTofPi", "jetTpcTofPi", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("jetTpcTofPr", "jetTpcTofPr", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("tpcTofPiPerpJet", "tpcTofPiPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("tpcTofPrPerpJet", "tpcTofPrPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("jetTpcPi", "jetTpcPi", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); registry.add("jetTofPi", "jetTofPi", HistType::kTH2F, {{nBinsPt.value, 0, ptMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); registry.add("jetTpcPr", "jetTpcPr", HistType::kTH2F, {{nBinsP.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}}); @@ -159,22 +154,29 @@ struct JetShapeTask { registry.add("tpcDedxPerpJet", "tpcDedxPerpJet", HistType::kTH2F, {{nBinsPForDedx.value, 0, pMax.value}, {nBinsTpcDedx.value, 0, 1000}}); registry.add("jetTofBeta", "jetTofBeta", HistType::kTH2F, {{nBinsPForBeta.value, 0, pMax.value}, {nBinsTofBeta.value, 0.4, 1.1}}); + // Jet (in Cone) + registry.add("jetTpcTofPi", "jetTpcTofPi", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("jetTpcTofPr", "jetTpcTofPr", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("jetpVsPtForPr", "jetpVsPtForPr", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("jetpVsPtForPi", "jetpVsPtPi", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("pVsPtForPrPerpJet", "pVsPtForPrPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("pVsPtForPiPerpJet", "pVsPtPionPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("jetDcaPr", "jetDcaPr", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("jetDcaPi", "jetDcaPi", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + + // Perp Cone + registry.add("tpcTofPiPerpJet", "tpcTofPiPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPrPerpJet", "tpcTofPrPerpJet", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPrPerpJet", "pVsPtForPrPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPiPerpJet", "pVsPtPionPerpJet", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("dcaPrPerpJet", "dcaPrPerpJet", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("dcaPiPerpJet", "dcaPiPerpJet", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("tpcTofPiRandCone", "tpcTofPiRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("tpcTofPrRandCone", "tpcTofPrRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("pVsPtForPrRandCone", "pVsPtForPrRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("pVsPtForPiRandCone", "pVsPtPionRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("dcaPrRandCone", "dcaPrRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("dcaPiRandCone", "dcaPiRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + // Random Cone + registry.add("tpcTofPiRandCone", "tpcTofPiRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("tpcTofPrRandCone", "tpcTofPrRandCone", HistType::kTHnSparseD, {{nBinsPForCut.value, 0, pMax.value}, {nBinsNSigma.value, nSigmaMin.value, nSigmaMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPrRandCone", "pVsPtForPrRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("pVsPtForPiRandCone", "pVsPtPionRandCone", HistType::kTHnSparseD, {{nBinsP.value, 0, pMax.value}, {nBinsPt.value, 0, ptMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPrRandCone", "dcaPrRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("dcaPiRandCone", "dcaPiRandCone", HistType::kTHnSparseD, {{nBinsPtForDca.value, 0, ptMax.value}, {nBinsDcaxyForData.value, dcaxyMin.value, dcaxyMax.value}, {nBinsDistance.value, 0, distanceMax.value}, {nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("jetPt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", HistType::kTH2F, {{200, 0., 200.}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("jetPtMc", "MC jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", HistType::kTH2F, {{200, 0., 200.}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); @@ -193,7 +195,7 @@ struct JetShapeTask { registry.add("eventCounterJetShape", "eventCounterJetShape", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("eventCounterJet", "eventCounterJet", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("eventCounterInc", "eventCounterInc", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); - registry.add("eventCounterRandCone", "Number of Random Cones;Centrality (%);Count", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); + registry.add("eventCounterRandCone", "Number of Random Cones;Centrality (%);Count", HistType::kTH2F, {{nBinsJetPt.value, jetPtMinForCut.value, jetPtMaxForCut.value}, {nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("eventCounterMc", "eventCounterMc", HistType::kTH1F, {{nBinsCentrality.value, centralityMinForCut.value, centralityMaxForCut.value}}); registry.add("ptVsCentrality", "ptvscentrality", HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}); @@ -545,7 +547,8 @@ struct JetShapeTask { } if (isValidRC) { - registry.fill(HIST("eventCounterRandCone"), centrality); + const auto& leadJet = cachedJets[0]; + registry.fill(HIST("eventCounterRandCone"), leadJet.ptCorr, centrality); } } @@ -659,23 +662,23 @@ struct JetShapeTask { // dcaXY if (track.hasTOF()) { if (hasTofPr && isTpcPrRange) { - registry.fill(HIST("dcaPrRandCone"), trkPt, track.dcaXY(), leadJet.ptCorr, centrality); + registry.fill(HIST("dcaPrRandCone"), trkPt, track.dcaXY(), distRC, leadJet.ptCorr, centrality); } if (hasTofPi && isTpcPiRange) { - registry.fill(HIST("dcaPiRandCone"), trkPt, track.dcaXY(), leadJet.ptCorr, centrality); + registry.fill(HIST("dcaPiRandCone"), trkPt, track.dcaXY(), distRC, leadJet.ptCorr, centrality); } } if (hasTofPi) { - registry.fill(HIST("tpcTofPiRandCone"), trkP, tpcPi, leadJet.ptCorr, centrality); + registry.fill(HIST("tpcTofPiRandCone"), trkP, tpcPi, distRC, leadJet.ptCorr, centrality); if (isTpcPiRange) { - registry.fill(HIST("pVsPtForPiRandCone"), trkP, trkPt, leadJet.ptCorr, centrality); + registry.fill(HIST("pVsPtForPiRandCone"), trkP, trkPt, distRC, leadJet.ptCorr, centrality); } } if (hasTofPr) { - registry.fill(HIST("tpcTofPrRandCone"), trkP, tpcPr, leadJet.ptCorr, centrality); + registry.fill(HIST("tpcTofPrRandCone"), trkP, tpcPr, distRC, leadJet.ptCorr, centrality); if (isTpcPrRange) { - registry.fill(HIST("pVsPtForPrRandCone"), trkP, trkPt, leadJet.ptCorr, centrality); + registry.fill(HIST("pVsPtForPrRandCone"), trkP, trkPt, distRC, leadJet.ptCorr, centrality); } } } From 2b561db278a159e1c73173d2c003e68c1690ad30 Mon Sep 17 00:00:00 2001 From: Changhwan Choi <157435123+choich08365@users.noreply.github.com> Date: Sun, 24 May 2026 07:05:27 +0900 Subject: [PATCH 273/449] [PWGJE] GNN b-jet MCP jet spectrum and response matrix revised (#16346) Co-authored-by: Changhwan Choi Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/bjetTaggingGnn.cxx | 160 ++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 54 deletions(-) diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index e72fba2ccef..314e99a77fa 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -namespace BjetTaggingGnnEvtSel +namespace bjet_tagging_gnn_evtsel { enum class EvtSelFlag : uint8_t { kNone = 0, @@ -116,8 +117,8 @@ enum class EvtSel { INELgt0, INELgt0rec }; -}; // namespace BjetTaggingGnnEvtSel -using namespace BjetTaggingGnnEvtSel; +}; // namespace bjet_tagging_gnn_evtsel +using namespace bjet_tagging_gnn_evtsel; struct BjetTaggingGnn { @@ -282,6 +283,7 @@ struct BjetTaggingGnn { registry.add("h_trackphi", "", {HistType::kTH1F, {{100, 0.0, 2.0 * M_PI, "#it{#phi}"}}}, callSumw2); registry.add("h_dcaXY", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); } if (doprocessMCDTracks) { @@ -308,6 +310,15 @@ struct BjetTaggingGnn { registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); registry.add("h_dcaZ_npp_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_fake", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_fake", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_matched", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_matched_b", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_matched_c", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_matched_lf", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_coll_mismatched", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_npp", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h3_dca_pt_npp_mismatched", "", {HistType::kTH3F, {{1000, 0., 100., "#it{p}_{T} (GeV/#it{c})"}, {200, 0., 4., "|DCA_{#it{z}}| (cm)"}, {200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); } if (doprocessDataJetsSel || doprocessMCDJetsSel) { @@ -352,6 +363,9 @@ struct BjetTaggingGnn { registry.add("h_jetpT_particle_matched", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_b_matched", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_b_matched", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); + // pTHat study + registry.add("h3_pthat_jetpT", "", {HistType::kTH3F, {{300, 0., 300., "#hat{#it{p}}_{T} (GeV/#it{c})"}, axisJetpT, axisJetpT}}, callSumw2); + registry.add("h3_pthat_jetpT_b", "b-jet", {HistType::kTH3F, {{300, 0., 300., "#hat{#it{p}}_{T} (GeV/#it{c})"}, axisJetpT, axisJetpT}}, callSumw2); } if (doprocessMCDJetsSel) { @@ -466,9 +480,7 @@ struct BjetTaggingGnn { using AnalysisCollisionsMCD = soa::Join; using FilteredCollisionsMCD = soa::Filtered; - Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; using AnalysisCollisionsMCP = soa::Join; - using FilteredCollisionsMCP = soa::Filtered; using MCPJets = soa::Join; using FilteredMCPJets = soa::Filtered; @@ -507,17 +519,20 @@ struct BjetTaggingGnn { return nTracks; } + const float largeNegativeNumber = -98.0f; + const float largePositiveNumber = 9999.0f; + template bool isAcceptedJet(AnalysisJet const& jet) { - if (jetAreaFractionMin > -98.0) { + if (jetAreaFractionMin > largeNegativeNumber) { if (jet.area() < jetAreaFractionMin * M_PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { return false; } } bool checkConstituentPt = true; - bool checkConstituentMinPt = (leadingConstituentPtMin > -98.0); - bool checkConstituentMaxPt = (leadingConstituentPtMax < 9998.0); + bool checkConstituentMinPt = (leadingConstituentPtMin > largeNegativeNumber); + bool checkConstituentMaxPt = (leadingConstituentPtMax < largePositiveNumber); if (!checkConstituentMinPt && !checkConstituentMaxPt) { checkConstituentPt = false; } @@ -684,15 +699,16 @@ struct BjetTaggingGnn { } // Check if the collision is INEL>0 + const int nPartInel0 = 3; template bool isTrueINEL0(MCColl const& /*mccoll*/, MCPart const& mcparts) { - for (auto const& mcparticle : mcparts) { + for (const auto& mcparticle : mcparts) { if (!mcparticle.isPhysicalPrimary()) continue; - auto p = pdg->GetParticle(mcparticle.pdgCode()); + const auto p = pdg->GetParticle(mcparticle.pdgCode()); if (p != nullptr) { - if (std::abs(p->Charge()) >= 3) { + if (std::abs(p->Charge()) >= nPartInel0) { if (std::abs(mcparticle.eta()) < 1) return true; } @@ -779,7 +795,7 @@ struct BjetTaggingGnn { void processDataJetsTrig(FilteredCollisionsTriggered::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, aod::JBCs const& /*bcInfo*/) { // Get BC info associated with the collision before applying any event selections - auto bc = collision.bc_as(); + const auto& bc = collision.bc_as(); // Initialize CCDB objects using the BC info initCCDB(bc); // If SoftwareTriggerSelection (i.e. skimming) is enabled, skip this event unless it passes Zorro selection @@ -841,12 +857,15 @@ struct BjetTaggingGnn { if (track.pt() >= trackPtMin) { registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY())); registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ())); + registry.fill(HIST("h3_dca_pt"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY())); } } } PROCESS_SWITCH(BjetTaggingGnn, processDataTracks, "track information in Data", false); - void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, FilteredMCPJets const& /*MCPjets*/, aod::JetParticles const& /*mcParticles*/, FilteredCollisionsMCP const& /*mcCollisions*/) + Preslice mcpjetsPerMCPCollision = aod::jet::mcCollisionId; + + void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, FilteredMCPJets const& MCPjets, aod::JetParticles const& /*mcParticles*/, AnalysisCollisionsMCP const& /*mcCollisions*/) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -855,7 +874,8 @@ struct BjetTaggingGnn { if (collision.isOutlier()) { return; } - if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + bool matchedMcColl = collision.has_mcCollision(); + if (matchedMcColl && collision.template mcCollision_as().isOutlier()) { return; } // Uses only collisionId % trainingDatasetRaioParam != 0 for evaluation dataset @@ -864,12 +884,14 @@ struct BjetTaggingGnn { } float weightEvt = useEventWeight ? collision.weight() : 1.f; - bool matchedMcColl = collision.has_mcCollision() && std::fabs(collision.template mcCollision_as().posZ()) < vertexZCut; registry.fill(HIST("h_event_counter"), 0.0, weightEvt); registry.fill(HIST("h_vertexZ"), collision.posZ(), weightEvt); + // Store matched particle jet indices to avoid double-counting in mcpjets loop + std::unordered_set matchedMcpJetIndices; + for (const auto& analysisJet : MCDjets) { if (!isAcceptedJet(analysisJet)) { continue; @@ -880,31 +902,74 @@ struct BjetTaggingGnn { if (!matchedMcColl) { continue; } + bool matchedJet = false; for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + // matchedJetGeo_as is not Filtered. + if (mcpjet.pt() < jetPtMin || mcpjet.pt() >= jetPtMax || mcpjet.eta() >= jetEtaMax - mcpjet.r() / 100.f || mcpjet.eta() <= jetEtaMin + mcpjet.r() / 100.f) { + continue; + } + matchedJet = true; + matchedMcpJetIndices.insert(mcpjet.globalIndex()); registry.fill(HIST("h2_Response_DetjetpT_PartjetpT"), analysisJet.pt(), mcpjet.pt(), weightEvt); registry.fill(HIST("h_jetpT_matched"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_jetpT_particle_matched"), mcpjet.pt(), weightEvt); + registry.fill(HIST("h3_pthat_jetpT"), collision.template mcCollision_as().ptHard(), analysisJet.pt(), mcpjet.pt(), weightEvt); // Matched jets if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_b"), analysisJet.pt(), mcpjet.pt(), weightEvt); registry.fill(HIST("h_jetpT_b_matched"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_jetpT_particle_b_matched"), mcpjet.pt(), weightEvt); + registry.fill(HIST("h3_pthat_jetpT_b"), collision.template mcCollision_as().ptHard(), analysisJet.pt(), mcpjet.pt(), weightEvt); // Matched b-jets } else if (jetFlavor == JetTaggingSpecies::charm) { registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_c"), analysisJet.pt(), mcpjet.pt(), weightEvt); } else { registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_lf"), analysisJet.pt(), mcpjet.pt(), weightEvt); } } + if (!matchedJet) { + registry.fill(HIST("h3_pthat_jetpT"), collision.template mcCollision_as().ptHard(), analysisJet.pt(), -1.f, weightEvt); // Fake jets, overflow-pTpart jets + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h3_pthat_jetpT_b"), collision.template mcCollision_as().ptHard(), analysisJet.pt(), -1.f, weightEvt); // Overflow-pTpart b-jets + } + } + } + + if (!matchedMcColl) { + return; + } + + // Fill histograms for jets matched to the analysis event selection + const auto& mcpjetspermcpcollision = MCPjets.sliceBy(mcpjetsPerMCPCollision, collision.mcCollisionId()); + for (const auto& mcpjet : mcpjetspermcpcollision) { + registry.fill(HIST("h_jetpT_particle"), mcpjet.pt(), weightEvt); + + // Fill h3_pthat_jetpT only for unmatched particle jets (reco pT = -1) + if (matchedMcpJetIndices.find(mcpjet.globalIndex()) == matchedMcpJetIndices.end()) { + registry.fill(HIST("h3_pthat_jetpT"), collision.template mcCollision_as().ptHard(), -1.f, mcpjet.pt(), weightEvt); // Missing jets, overflow-pTreco jets + if (mcpjet.origin() == JetTaggingSpecies::beauty) { + registry.fill(HIST("h3_pthat_jetpT_b"), collision.template mcCollision_as().ptHard(), -1.f, mcpjet.pt(), weightEvt); // Missing b-jets, overflow-pTpart b-jets + } + } + + int8_t jetFlavor = mcpjet.origin(); + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_b"), mcpjet.pt(), weightEvt); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_c"), mcpjet.pt(), weightEvt); + } else { + registry.fill(HIST("h_jetpT_particle_lf"), mcpjet.pt(), weightEvt); + } } } PROCESS_SWITCH(BjetTaggingGnn, processMCDJets, "jet information in MC", false); - void processMCDJetsSel(AnalysisCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& /*allTracks*/, FilteredMCPJets const& /*MCPjets*/, FilteredCollisionsMCP const& /*mcCollisions*/) + void processMCDJetsSel(AnalysisCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& /*allTracks*/, FilteredMCPJets const& /*MCPjets*/, AnalysisCollisionsMCP const& /*mcCollisions*/) { // Reject outlier MC collisions if (collision.isOutlier()) { return; } - if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { return; } @@ -941,7 +1006,6 @@ struct BjetTaggingGnn { PROCESS_SWITCH(BjetTaggingGnn, processMCDJetsSel, "jet information in MC (event selection)", false); PresliceUnsorted collisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; - Preslice mcpjetsPerMCPCollision = aod::jet::mcCollisionId; void processMCPJets(AnalysisCollisionsMCP const& mcCollisions, FilteredMCPJets const& mcpjets, AnalysisCollisionsMCD const& collisions, aod::JetParticles const& mcParticles) { @@ -950,8 +1014,13 @@ struct BjetTaggingGnn { if (mcCollision.isOutlier()) { continue; } + const auto& matchedCollisions = collisions.sliceBy(collisionsPerMCPCollision, mcCollision.mcCollisionId()); + if (matchedCollisions.size() >= 1) { + if (matchedCollisions.begin().isOutlier()) { + continue; + } + } float weightEvt = useEventWeight ? mcCollision.weight() : 1.f; - auto matchedCollisions = collisions.sliceBy(collisionsPerMCPCollision, mcCollision.mcCollisionId()); EvtSelFlag evtselCode = EvtSelFlag::INEL; registry.fill(HIST("hMcCollCounter"), static_cast(EvtSel::INEL), weightEvt); // INEL @@ -970,8 +1039,6 @@ struct BjetTaggingGnn { } } - bool isMatchedToAnalysisSelection = false; - if (matchedCollisions.size() >= 1) { zvtxMatched = std::fabs(matchedCollisions.begin().posZ()) < vertexZCut; evtselCode |= EvtSelFlag::kColl; @@ -1007,24 +1074,12 @@ struct BjetTaggingGnn { } } if (jetderiveddatautilities::selectCollision(matchedCollisions.begin(), eventSelectionBits) && zvtxMatched) { - isMatchedToAnalysisSelection = true; registry.fill(HIST("h_event_counter_mcp"), 0.0, weightEvt); } } - auto mcpjetspermcpcollision = mcpjets.sliceBy(mcpjetsPerMCPCollision, mcCollision.mcCollisionId()); + const auto& mcpjetspermcpcollision = mcpjets.sliceBy(mcpjetsPerMCPCollision, mcCollision.mcCollisionId()); for (const auto& mcpjet : mcpjetspermcpcollision) { - bool jetIncluded = false; - for (const auto& jetR : jetRadiiValues) { - if (mcpjet.r() == static_cast(jetR * 100)) { - jetIncluded = true; - break; - } - } - - if (!jetIncluded) { - continue; - } int8_t jetFlavor = mcpjet.origin(); @@ -1064,19 +1119,6 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetpT_particle_c_sel8_zvtx"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::Sel8Zvtx) ? weightEvt : 0.0); registry.fill(HIST("h_jetpT_particle_c_inelgt0"), mcpjet.pt(), hasAll(evtselCode, EvtSelFlag::INELgt0) ? weightEvt : 0.0); } - - // Fill histograms for jets matched to the analysis event selection - if (isMatchedToAnalysisSelection) { - registry.fill(HIST("h_jetpT_particle"), mcpjet.pt(), weightEvt); - - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_b"), mcpjet.pt(), weightEvt); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_c"), mcpjet.pt(), weightEvt); - } else { - registry.fill(HIST("h_jetpT_particle_lf"), mcpjet.pt(), weightEvt); - } - } } } } @@ -1084,7 +1126,7 @@ struct BjetTaggingGnn { Preslice mcparticlesPerMCPCollision = aod::jmcparticle::mcCollisionId; - void processMCDTracks(FilteredCollisionsMCD::iterator const& collision, AnalysisTracksMCD const& tracks, FilteredCollisionsMCP const& /*mcCollisions*/, aod::JetParticles const& allParticles) + void processMCDTracks(FilteredCollisionsMCD::iterator const& collision, AnalysisTracksMCD const& tracks, AnalysisCollisionsMCP const& /*mcCollisions*/, aod::JetParticles const& allParticles) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -1093,7 +1135,8 @@ struct BjetTaggingGnn { if (collision.isOutlier()) { return; } - if (collision.has_mcCollision() && collision.template mcCollision_as().isOutlier()) { + bool matchedMcColl = collision.has_mcCollision(); + if (matchedMcColl && collision.template mcCollision_as().isOutlier()) { return; } // Uses only collisionId % trainingDatasetRaioParam != 0 for evaluation dataset @@ -1102,7 +1145,6 @@ struct BjetTaggingGnn { } float weightEvt = useEventWeight ? collision.weight() : 1.f; - bool matchedMcColl = collision.has_mcCollision() && std::fabs(collision.template mcCollision_as().posZ()) < vertexZCut; for (const auto& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelectionBits) || track.eta() <= trackEtaMin || track.eta() >= trackEtaMax) { @@ -1114,12 +1156,14 @@ struct BjetTaggingGnn { if (track.pt() >= trackPtMin) { registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } if (!matchedMcColl) { if (track.pt() >= trackPtMin) { registry.fill(HIST("h_dcaXY_coll_fake"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_coll_fake"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_fake"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } continue; } @@ -1127,10 +1171,11 @@ struct BjetTaggingGnn { if (track.pt() >= trackPtMin) { registry.fill(HIST("h_dcaXY_fake"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_fake"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_fake"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } continue; } - auto particle = track.template mcParticle_as(); + const auto& particle = track.template mcParticle_as(); if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { if (particle.isPhysicalPrimary()) { registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); @@ -1142,28 +1187,35 @@ struct BjetTaggingGnn { if (particle.mcCollisionId() == collision.mcCollisionId()) { registry.fill(HIST("h_dcaXY_coll_matched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from the same MC collision registry.fill(HIST("h_dcaZ_coll_matched"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_matched"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); int origin = RecoDecay::getParticleOrigin(allParticles, particle, false); if (origin == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("h_dcaXY_coll_matched_b"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_coll_matched_b"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_matched_b"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } else if (origin == RecoDecay::OriginType::Prompt) { registry.fill(HIST("h_dcaXY_coll_matched_c"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_coll_matched_c"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_matched_c"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } else { registry.fill(HIST("h_dcaXY_coll_matched_lf"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_coll_matched_lf"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_matched_lf"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } } else { registry.fill(HIST("h_dcaXY_coll_mismatched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from a different MC collision registry.fill(HIST("h_dcaZ_coll_mismatched"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_coll_mismatched"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } } else { if (particle.mcCollisionId() == collision.mcCollisionId()) { registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_npp"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } else { registry.fill(HIST("h_dcaXY_npp_mismatched"), std::fabs(track.dcaXY()), weightEvt); registry.fill(HIST("h_dcaZ_npp_mismatched"), std::fabs(track.dcaZ()), weightEvt); + registry.fill(HIST("h3_dca_pt_npp_mismatched"), track.pt(), std::fabs(track.dcaZ()), std::fabs(track.dcaXY()), weightEvt); } } } @@ -1174,10 +1226,10 @@ struct BjetTaggingGnn { return; } - auto const particles = allParticles.sliceBy(mcparticlesPerMCPCollision, collision.mcCollisionId()); + const auto& particles = allParticles.sliceBy(mcparticlesPerMCPCollision, collision.mcCollisionId()); for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + const auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle || pdgParticle->Charge() == 0.0) { continue; } @@ -1207,7 +1259,7 @@ struct BjetTaggingGnn { } } } - auto collisionsInBC = collisions.sliceBy(perFoundBC, bc.globalIndex()); + const auto& collisionsInBC = collisions.sliceBy(perFoundBC, bc.globalIndex()); for (const auto& collision : collisionsInBC) { registry.fill(HIST("hBCCounter"), 4.5); // CollinBC if (collision.sel8()) { From 648df8533670533d43658e2dff85c9abfcc5d8f1 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Sat, 23 May 2026 23:06:13 +0100 Subject: [PATCH 274/449] [PWGJE] jetSpectraCharged: FT0CVariant1 option, mcdmcpetaconstraint match hists (#16331) --- PWGJE/Tasks/jetSpectraCharged.cxx | 64 ++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index adc4fde7839..6e19be7a128 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -84,6 +84,7 @@ struct JetSpectraCharged { Configurable isMCGenOnly{"isMCGenOnly", false, "analysis is run over mcGen only"}; Configurable kappa{"kappa", 1.0, "angularity kappa"}; Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable useFT0CVariant{"useFT0CVariant", false, "IF checkCentFT0M is false: false -> use standard FT0C centrality selection; true -> use FT0CVariant1"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -92,6 +93,9 @@ struct JetSpectraCharged { float configSwitchLow = -98.0; float configSwitchHigh = 9998.0; + + float ptHardCalcMethodSwitch = 999.0; + enum AcceptSplitCollisionsOptions { NonSplitOnly = 0, SplitOkCheckAnyAssocColl, // 1 @@ -233,6 +237,7 @@ struct JetSpectraCharged { if (checkGeoMatched) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcpetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcpmcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_eta_mcd_jet_eta_mcp_matchedgeo", "Eta mcd vs. Eta mcp;#eta_{jet}^{mcd};#eta_{jet}^{mcp}", {HistType::kTH2F, {jetEtaAxis, jetEtaAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgeo_mcdetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgeo_mcpetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); @@ -246,6 +251,7 @@ struct JetSpectraCharged { if (checkPtMatched) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcpetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcpmcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_eta_mcd_jet_eta_mcp_matchedpt", "Eta mcd vs. Eta mcp;#eta_{jet}^{mcd};#eta_{jet}^{mcp}", {HistType::kTH2F, {jetEtaAxis, jetEtaAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgpt_mcdetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgpt_mcpetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); @@ -259,6 +265,7 @@ struct JetSpectraCharged { if (checkGeoPtMatched) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcpetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcpmcdetaconstraint", "pT mcd vs. pT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}, doSumw2); registry.add("h2_jet_eta_mcd_jet_eta_mcp_matchedgeopt", "Eta mcd vs. Eta mcp;#eta_{jet}^{mcd};#eta_{jet}^{mcp}", {HistType::kTH2F, {jetEtaAxis, jetEtaAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgeopt_mcdetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); registry.add("h2_jet_phi_mcd_jet_phi_mcp_matchedgeopt_mcpetaconstraint", "Phi mcd vs. Phi mcp;#varphi_{jet}^{mcd};#varphi_{jet}^{mcp}", {HistType::kTH2F, {phiAxis, phiAxis}}, doSumw2); @@ -274,6 +281,7 @@ struct JetSpectraCharged { if (doprocessJetsMatchedAreaSub || doprocessJetsMatchedAreaSubWeighted) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcdetaconstraint", "corr pT mcd vs. corr cpT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcpetaconstraint", "corr pT mcd vs. corr cpT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}, doSumw2); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcpmcdetaconstraint", "corr pT mcd vs. corr cpT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}, doSumw2); registry.add("h2_jet_pt_mcd_rhoareasubtracted_jet_pt_mcp_matchedgeo_mcdetaconstraint", "UEsub pT mcd vs. raw pT mcp;#it{p}_{T,jet}^{mcd} - #rho#it{A} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxis}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcp corr pT vs. corr delta pT / jet mcp corr pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcd corr pT vs. corr delta pT / jet mcd corr pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); @@ -393,7 +401,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C()); if ((centralityMin < centrality) && (centrality < centralityMax)) { centralityIsGood = true; } @@ -437,7 +445,7 @@ struct JetSpectraCharged { bool applyCollisionCuts(TColl const& collision, bool fillHistograms = false, bool isWeighted = false, float eventWeight = 1.0) { float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); if (fillHistograms) { registry.fill(HIST("h_collisions"), 0.5); @@ -610,12 +618,15 @@ struct JetSpectraCharged { if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { double dpt = jetMCD.pt() - jetMCP.pt(); float angularityMcd = 0.; - for (auto& constituent : jetMCD.template tracks_as()) { + for (const auto& constituent : jetMCD.template tracks_as()) { angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); } angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_mcpmcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + } registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeo_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedgeo"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); @@ -646,12 +657,15 @@ struct JetSpectraCharged { if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { double dpt = jetMCD.pt() - jetMCP.pt(); float angularityMcd = 0.; - for (auto& constituent : jetMCD.template tracks_as()) { + for (const auto& constituent : jetMCD.template tracks_as()) { angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); } angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedpt_mcpmcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + } registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedpt_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedpt"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedpt"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); @@ -682,12 +696,15 @@ struct JetSpectraCharged { if (jetMCD.template matchedJetGeo_first_as>().globalIndex() == jetMCD.template matchedJetPt_first_as>().globalIndex()) { // not a good way to do this double dpt = jetMCD.pt() - jetMCP.pt(); float angularityMcd = 0.; - for (auto& constituent : jetMCD.template tracks_as()) { + for (const auto& constituent : jetMCD.template tracks_as()) { angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); } angularityMcd /= (jetMCD.pt() * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeopt_mcpmcdetaconstraint"), jetMCD.pt(), jetMCP.pt(), weight); + } registry.fill(HIST("h2_jet_phi_mcd_jet_phi_mcp_matchedgeopt_mcdetaconstraint"), jetMCD.phi(), jetMCP.phi(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeopt"), jetMCD.pt(), dpt / jetMCD.pt(), weight); registry.fill(HIST("h2_jet_ntracks_mcd_jet_ntracks_mcp_matchedgeopt"), jetMCD.tracksIds().size(), jetMCP.tracksIds().size(), weight); @@ -723,12 +740,15 @@ struct JetSpectraCharged { double corrBasejetpt = jetMCD.pt() - (rho * jetMCD.area()); double dcorrpt = corrBasejetpt - corrTagjetpt; float angularityMcd = 0.; - for (auto& constituent : jetMCD.template tracks_as()) { + for (const auto& constituent : jetMCD.template tracks_as()) { angularityMcd += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jetMCD, constituent), alpha); } angularityMcd /= (corrBasejetpt * (jetMCD.r() / 100.f)); if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcpmcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + } registry.fill(HIST("h2_jet_pt_mcd_rhoareasubtracted_jet_pt_mcp_matchedgeo_mcdetaconstraint"), corrBasejetpt, jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted"), corrBasejetpt, dcorrpt / corrBasejetpt, weight); registry.fill(HIST("h3_jet_pt_mcd_jet_pt_mcp_jet_mcd_angularity_matchedgeo_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, angularityMcd, weight); @@ -815,7 +835,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -838,7 +858,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -861,7 +881,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -884,7 +904,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -909,9 +929,9 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -936,9 +956,9 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -1009,7 +1029,7 @@ struct JetSpectraCharged { occupancyIsGood = true; } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); if ((centralityMin < centrality) && (centrality < centralityMax)) { centralityIsGood = true; } @@ -1092,7 +1112,7 @@ struct JetSpectraCharged { occupancyIsGood = true; } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); if ((centralityMin < centrality) && (centrality < centralityMax)) { centralityIsGood = true; } @@ -1179,7 +1199,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = mccollision.ptHard() < ptHardCalcMethodSwitch ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1211,7 +1231,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = mccollision.ptHard() < ptHardCalcMethodSwitch ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_mccollisions_rho"), mccollision.rho(), eventWeight); for (auto const& jet : jets) { @@ -1235,7 +1255,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -1258,7 +1278,7 @@ struct JetSpectraCharged { } float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -1302,7 +1322,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (const auto& mcdjet : mcdjets) { if (!isAcceptedJet(mcdjet)) { continue; @@ -1345,7 +1365,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); double mcrho = collision.has_mcCollision() ? collision.mcCollision_as().rho() : -1; From 38e06061bd4f601ba111a7d04998ac1643df447b Mon Sep 17 00:00:00 2001 From: baasingh <142407539+baasingh@users.noreply.github.com> Date: Sun, 24 May 2026 12:06:53 +0530 Subject: [PATCH 275/449] [PWGCF] fix multiplicity calcultion funcation and include tpcsignal plot (#16358) --- .../Tasks/FactorialMomentsTask.cxx | 172 +++++++++++------- 1 file changed, 106 insertions(+), 66 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index fca2ef50d8f..035f457193f 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -53,24 +53,29 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; TH1D* tmpFqErr[6][5][52]; - +float collisionZ = 0.f; struct FactorialMomentsTask { Configurable useITS{"useITS", false, "Select tracks with ITS"}; Configurable useTPC{"useTPC", false, "Select tracks with TPC"}; Configurable useGlobal{"useGlobal", true, "Select global tracks"}; Configurable applyCheckPtForRec{"applyCheckPtForRec", false, "Apply checkpT for reconstructed tracks"}; Configurable applyCheckPtForMC{"applyCheckPtForMC", true, "Apply checkpT for MC-generated tracks"}; + Configurable cfgEvSelkNoITSROFrameBorder{"cfgEvSelkNoITSROFrameBorder", true, "ITSROFrame border event selection cut"}; + Configurable cfgEvSelkNoTimeFrameBorder{"cfgEvSelkNoTimeFrameBorder", true, "TimeFrame border event selection cut"}; Configurable centralEta{"centralEta", 0.9, "eta limit for tracks"}; Configurable numPt{"numPt", 5, "number of pT bins"}; Configurable ptMin{"ptMin", 0.2f, "lower pT cut"}; - Configurable dcaXY{"dcaXY", 2.4f, "DCA xy cut"}; - Configurable dcaZ{"dcaZ", 2.0f, "DCA z cut"}; + Configurable dcaXY{"dcaXY", 0.1f, "DCA xy cut"}; + Configurable dcaZ{"dcaZ", 1.0f, "DCA z cut"}; + Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; + Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 40.0f, "Maximum ITSchi2NCl"}; Configurable mintPCCls{"mintPCCls", 70.0f, "minimum number of TPC clusters"}; Configurable> centLimits{"centLimits", {0, 5}, "centrality min and max"}; Configurable> vertexXYZ{"vertexXYZ", {0.3f, 0.4f, 10.0f}, "vertex cuts"}; Configurable> ptCuts{"ptCuts", {0.2f, 2.0f}, "pT cuts"}; Configurable isApplySameBunchPileup{"isApplySameBunchPileup", true, "Enable SameBunchPileup cut"}; Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", true, "Enable GoodZvtxFT0vsPV cut"}; + Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; Configurable isApplyVertexITSTPC{"isApplyVertexITSTPC", true, "Enable VertexITSTPC cut"}; Configurable isApplyVertexTOFmatched{"isApplyVertexTOFmatched", true, "Enable VertexTOFmatched cut"}; Configurable isApplyVertexTRDmatched{"isApplyVertexTRDmatched", true, "Enable VertexTRDmatched cut"}; @@ -81,14 +86,20 @@ struct FactorialMomentsTask { Configurable includeITSTracks{"includeITSTracks", false, "ITS Tracks"}; Configurable samplesize{"samplesize", 100, "Sample size"}; Configurable useMC{"useMC", false, "Use MC information"}; + Configurable useGlobalTrack{"useGlobalTrack", true, "Require global track in filter"}; + Configurable cfgITScluster{"cfgITScluster", 6, "Minimum Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 80, "Minimum Number of TPC cluster"}; + Configurable cfgTPCnCrossedRows{"cfgTPCnCrossedRows", 70, "Minimum Number of TPC crossed-rows"}; + Configurable cfgTPCnCrossedRowsOverFindableCls{"cfgTPCnCrossedRowsOverFindableCls", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; Configurable reduceOutput{"reduceOutput", 0, "Suppress info level output (0 = all output, 1 = per collision, 2 = none)"}; - Filter filterTracks = (nabs(aod::track::eta) < centralEta) && (aod::track::pt >= ptMin) && (nabs(aod::track::dcaXY) < dcaXY) && (nabs(aod::track::dcaZ) < dcaZ); + Filter filterTracks = (nabs(aod::track::eta) < centralEta) && (aod::track::pt >= ptMin); Filter filterCollisions = (nabs(aod::collision::posZ) < vertexXYZ.value[2]) && (nabs(aod::collision::posX) < vertexXYZ.value[0]) && (nabs(aod::collision::posY) < vertexXYZ.value[1]); Service pdg; // Histograms HistogramRegistry histos1{ "histos1", { + {"h3DVtxZetaPhi", "VtxZ vs #eta vs #phi;VtxZ;#eta;#phi", {HistType::kTH3F, {{20, -10, 10}, {16, -0.8, 0.8}, {100, 0., o2::constants::math::TwoPI}}}}, {"hRecoPtBefore", "Reco pT before cuts;pt (GeV/c);Counts", {HistType::kTH1F, {{1000, 0.0, 20.0}}}}, {"hGenPtBefore", "Gen pT before cuts;pt (GeV/c);Counts", {HistType::kTH1F, {{1000, 0.0, 20.0}}}}, {"hRecoPtAfter", "Reco pT after cuts;pt (GeV/c);Counts", {HistType::kTH1F, {{1000, 0.0, 20.0}}}}, @@ -118,6 +129,8 @@ struct FactorialMomentsTask { HistogramRegistry histos{ "histos", { + + {"mtpcsignalvspt", "tpcsignal vs #pt", {HistType::kTH2F, {{900, 0, 10}, {1400, 0, 1400}}}}, {"mChargeBefore", "Charge before MC cuts;charge;entries", {HistType::kTH1F, {{7, -3.5, 3.5}}}}, {"mChargeAfter", "Charge after MC cuts;charge;entries", {HistType::kTH1F, {{7, -3.5, 3.5}}}}, {"mCollID", "collisionID", {HistType::kTH1I, {{1000, -10000, 10000}}}}, @@ -153,6 +166,10 @@ struct FactorialMomentsTask { }, OutputObjHandlingPolicy::AnalysisObject, true}; + const double dcaxyMaxTrackPar0 = 0.0105; + const double dcaxyMaxTrackPar1 = 0.035; + const double dcaxyMaxTrackPar2 = 1.1; + const double dcazMaxTrack = 2.0; static const int nBins = 52; double kMinCharge = 1e-6; static const int nfqOrder = 6; @@ -167,6 +184,7 @@ struct FactorialMomentsTask { std::array, 5>, 6> errorFq = {{{{{0, 0, 0, 0, 0}}}}}; std::vector> mHistArrReset; std::vector> mHistArrQA; + std::vector> mHistArrEff; std::vector> mFqBinFinal; std::vector> mBinConFinal; std::vector> mFqBinFinalSampled; @@ -185,14 +203,15 @@ struct FactorialMomentsTask { } } AxisSpec axisPt[5] = {{100, -0.01, 3 * ptCuts.value[1], ""}, {100, -0.01, 3 * ptCuts.value[3], ""}, {100, -0.01, 3 * ptCuts.value[5], ""}, {100, -0.01, 3 * ptCuts.value[7], ""}, {100, -0.01, 3 * ptCuts.value[9], ""}}; // pT axis - auto mEventSelected = std::get>(histos.add("mEventSelected", "eventSelected", HistType::kTH1D, {{8, 0.5, 8.5}})); - mEventSelected->GetXaxis()->SetBinLabel(1, "all"); - mEventSelected->GetXaxis()->SetBinLabel(2, "sel8"); - mEventSelected->GetXaxis()->SetBinLabel(3, "sameBunchPileup"); - mEventSelected->GetXaxis()->SetBinLabel(4, "goodZvtxFT0vsPV"); - mEventSelected->GetXaxis()->SetBinLabel(5, "vertexITSTPC"); - mEventSelected->GetXaxis()->SetBinLabel(6, "centrality"); - mEventSelected->GetXaxis()->SetBinLabel(7, "final"); + auto mEventSelected = std::get>(histos.add("mEventSelected", "eventSelected", HistType::kTH1D, {{7, 0.5, 8.5}})); + mEventSelected->GetXaxis()->SetBinLabel(0, "all"); + mEventSelected->GetXaxis()->SetBinLabel(1, "sel8"); + mEventSelected->GetXaxis()->SetBinLabel(2, "kNoITSROFrameBorder"); + mEventSelected->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); + mEventSelected->GetXaxis()->SetBinLabel(4, "sameBunchPileup"); + mEventSelected->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); + mEventSelected->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); + mEventSelected->GetXaxis()->SetBinLabel(7, "FTOC"); auto mTrackSelected = std::get>(histos.add( "mTrackSelected", "Track Selection Steps", HistType::kTH1D, {{5, 0.5, 5.5}})); mTrackSelected->GetXaxis()->SetBinLabel(1, "all"); @@ -207,6 +226,7 @@ struct FactorialMomentsTask { binningM[iM] = 2 * (iM + 2); } for (int iPt = 0; iPt < numPt; ++iPt) { + mHistArrEff.push_back(std::get>(histos.add(Form("bin%i/m3DVtxZetaPhi", iPt + 1), Form("#eta #phi #vtxz for bin %.2f-%.2f;vz;#eta;#phi", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH3F, {{20, -10, 10}, {16, -0.8, +0.8}, {100, 0., o2::constants::math::TwoPI}}))); mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mEta", iPt + 1), Form("#eta for bin %.2f-%.2f;#eta", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, -2, 2}}))); mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mPt", iPt + 1), Form("pT for bin %.2f-%.2f;pT", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {axisPt[iPt]}))); mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mPhi", iPt + 1), Form("#phi for bin %.2f-%.2f;#phi", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, 0, o2::constants::math::TwoPI}}))); @@ -236,24 +256,22 @@ struct FactorialMomentsTask { template void checkpT(const T& track) { - for (int iPt = 0; iPt < numPt; ++iPt) { + for (auto iPt = 0; iPt < numPt; ++iPt) { if (track.pt() > ptCuts.value[2 * iPt] && track.pt() < ptCuts.value[2 * iPt + 1]) { float iphi = track.phi(); iphi = gRandom->Gaus(iphi, o2::constants::math::TwoPI); - iphi = RecoDecay::constrainAngle(iphi); - + iphi = RecoDecay::constrainAngle(iphi, 0.); + mHistArrEff[iPt]->Fill(collisionZ, track.eta(), iphi); mHistArrQA[iPt * 4]->Fill(track.eta()); mHistArrQA[iPt * 4 + 1]->Fill(track.pt()); - mHistArrQA[iPt * 4 + 2]->Fill(track.phi()); + mHistArrQA[iPt * 4 + 2]->Fill(iphi); countTracks[iPt]++; - - for (int iM = 0; iM < nBins; ++iM) { - mHistArrReset[iPt * nBins + iM]->Fill(track.eta(), track.phi()); + for (auto iM = 0; iM < nBins; ++iM) { + mHistArrReset[iPt * nBins + iM]->Fill(track.eta(), iphi); } } } } - void calculateMoments(std::vector> hist) { double binContent = 0; @@ -319,21 +337,36 @@ struct FactorialMomentsTask { void processRun3(soa::Filtered>::iterator const& coll, TracksFMs const& tracks) { // selection of events + histos.fill(HIST("mEventSelected"), 0); if (!coll.sel8()) { return; } + if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + return; + } + + histos.fill(HIST("mEventSelected"), 2); + if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { + return; + } + histos.fill(HIST("mEventSelected"), 3); if (isApplySameBunchPileup && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return; } - if (isApplyGoodZvtxFT0vsPV && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + histos.fill(HIST("mEventSelected"), 4); + if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { return; } - if (isApplyVertexITSTPC && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + histos.fill(HIST("mEventSelected"), 5); + if (isApplyGoodZvtxFT0vsPV && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return; } + histos.fill(HIST("mEventSelected"), 6); if (coll.centFT0C() < centLimits.value[0] || coll.centFT0C() > centLimits.value[1]) { return; } + collisionZ = coll.posZ(); + histos.fill(HIST("mEventSelected"), 7); histos.fill(HIST("mVertexX"), coll.posX()); histos.fill(HIST("mVertexY"), coll.posY()); histos.fill(HIST("mVertexZ"), coll.posZ()); @@ -354,29 +387,32 @@ struct FactorialMomentsTask { continue; if (useGlobal && !track.isGlobalTrack()) continue; - histos.fill(HIST("mCollID"), track.collisionId()); - histos.fill(HIST("mEta"), track.eta()); - histos.fill(HIST("mPt"), track.pt()); - histos.fill(HIST("mPhi"), track.phi()); - histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); - histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); - histos.fill(HIST("mNClsITS"), track.itsNCls()); - histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); - histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); - histos.fill(HIST("mChi2TRD"), track.trdChi2()); - histos.fill(HIST("mDCAxy"), track.dcaXY()); - histos.fill(HIST("mDCAx"), track.dcaZ()); - histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); - histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); - histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); - histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); - histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); - histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); - histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); - histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); - checkpT(track); - } + if (std::fabs(track.dcaXY()) < (dcaxyMaxTrackPar0 + dcaxyMaxTrackPar1 / std::pow(track.pt(), dcaxyMaxTrackPar2))) { + histos.fill(HIST("mCollID"), track.collisionId()); + histos.fill(HIST("mEta"), track.eta()); + histos.fill(HIST("mPt"), track.pt()); + histos.fill(HIST("mPhi"), track.phi()); + histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); + histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); + histos.fill(HIST("mNClsITS"), track.itsNCls()); + histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); + histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); + histos.fill(HIST("mChi2TRD"), track.trdChi2()); + histos.fill(HIST("mDCAxy"), track.dcaXY()); + histos.fill(HIST("mtpcsignalvspt"), track.pt(), track.tpcSignal()); + histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); + histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); + histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); + histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); + histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); + histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); + checkpT(track); + } + } for (int iPt = 0; iPt < numPt; ++iPt) { if (countTracks[iPt] > 0) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); @@ -412,6 +448,7 @@ struct FactorialMomentsTask { if (coll.centFT0C() < centLimits.value[0] || coll.centFT0C() > centLimits.value[1]) { return; } + histos.fill(HIST("mEventSelected"), 5); histos.fill(HIST("mVertexX"), coll.posX()); histos.fill(HIST("mVertexY"), coll.posY()); @@ -430,28 +467,31 @@ struct FactorialMomentsTask { continue; if (useGlobal && !track.isGlobalTrack()) continue; - histos.fill(HIST("mCollID"), track.collisionId()); - histos.fill(HIST("mEta"), track.eta()); - histos.fill(HIST("mPt"), track.pt()); - histos.fill(HIST("mPhi"), track.phi()); - histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); - histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); - histos.fill(HIST("mNClsITS"), track.itsNCls()); - histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); - histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); - histos.fill(HIST("mChi2TRD"), track.trdChi2()); - histos.fill(HIST("mDCAxy"), track.dcaXY()); - histos.fill(HIST("mDCAx"), track.dcaZ()); - histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); - histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); - histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); - histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); - histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); - histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); - histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); - histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); - if (applyCheckPtForRec && !applyCheckPtForMC) { - checkpT(track); + if (std::fabs(track.dcaXY()) < (dcaxyMaxTrackPar0 + dcaxyMaxTrackPar1 / std::pow(track.pt(), dcaxyMaxTrackPar2))) { + histos.fill(HIST("mCollID"), track.collisionId()); + histos.fill(HIST("mEta"), track.eta()); + histos.fill(HIST("mPt"), track.pt()); + histos.fill(HIST("mPhi"), track.phi()); + histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); + histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); + histos.fill(HIST("mNClsITS"), track.itsNCls()); + histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); + histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); + histos.fill(HIST("mChi2TRD"), track.trdChi2()); + histos.fill(HIST("mDCAxy"), track.dcaXY()); + histos.fill(HIST("mDCAx"), track.dcaZ()); + histos.fill(HIST("mtpcsignalvspt"), track.pt(), track.tpcSignal()); + histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); + histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); + histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); + histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); + histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); + histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); + if (applyCheckPtForRec && !applyCheckPtForMC) { + checkpT(track); + } } } auto mcParts = mcParticles.sliceBy(perMcCollision, coll.mcCollision().globalIndex()); From 0954eef99446b11e083dccbef98aec268145a9f2 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 24 May 2026 15:29:08 +0200 Subject: [PATCH 276/449] [PWGEM/Dilepton] update taggingHFE.cxx for ITSib requirement (#16361) --- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 79 ++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index ac395fbe2fc..8c12b5b11f3 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -199,8 +199,8 @@ struct taggingHFE { Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 2, "min ncluster its"}; Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; + Configurable cfg_itsib_type{"cfg_itsib_type", 0, "0:free, 1:OR, 2:AND between 2 legs, else:free"}; Configurable cfg_min_dcaxy{"cfg_min_dcaxy", 0.1, "min dca XY for v0 legs in cm"}; - Configurable cfg_max_alpha_veto{"cfg_max_alpha_veto", 0.95, "max alpha for photon conversion rejection"}; Configurable cfg_max_qt_veto{"cfg_max_qt_veto", 0.01, "max qT for photon conversion rejection"}; @@ -241,6 +241,12 @@ struct taggingHFE { Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; Configurable cfg_min_dcaxy_bachelor{"cfg_min_dcaxy_bachelor", 0.05, "min dca XY for bachelor in cm"}; Configurable cfg_min_dcaxy_v0{"cfg_min_dcaxy_v0", 0.0, "min dca XY for V0 in cm"}; + + Configurable cfg_itsib_type{"cfg_itsib_type", 0, "0:free, 1:OR, 2:AND between 2 legs, else:free"}; + Configurable cfg_min_ncluster_its_v0leg{"cfg_min_ncluster_its_v0leg", 2, "min ncluster its"}; + Configurable cfg_min_ncluster_itsib_v0leg{"cfg_min_ncluster_itsib_v0leg", 0, "min ncluster itsib"}; + Configurable cfg_min_ncluster_its_bachelor{"cfg_min_ncluster_its_bachelor", 2, "min ncluster its"}; + Configurable cfg_min_ncluster_itsib_bachelor{"cfg_min_ncluster_itsib_bachelor", 0, "min ncluster itsib"}; } cascadeCut; struct : ConfigurableGroup { @@ -467,9 +473,11 @@ struct taggingHFE { fRegistry.add("Cascade/hPt", "pT of cascade;p_{T} (GeV/c)", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Cascade/hYPhi", "rapidity vs. #varphi of cascade;#varphi (rad.);rapidity_{#Lambda}", kTH2F, {{90, 0, 2 * M_PI}, {80, -2, +2}}, false); fRegistry.add("Cascade/hCosPA", "cosPA;cosine of pointing angle", kTH1F, {{100, 0.9, 1}}, false); + fRegistry.add("Cascade/hLxy", "decay length from PV;L_{xy} (cm)", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Cascade/hDCA2Legs", "distance between 2 legs at PCA;distance between 2 legs (cm)", kTH1F, {{100, 0, 1}}, false); fRegistry.add("Cascade/hV0CosPA", "cosPA of V0 in cascade;cosine of pointing angle", kTH1F, {{100, 0.9, 1}}, false); fRegistry.add("Cascade/hV0DCA2Legs", "distance between 2 legs at PCA of V0 in cascade;distance between 2 legs (cm)", kTH1F, {{100, 0, 1}}, false); + fRegistry.add("Cascade/hV0Lxy", "decay length from PV of V0;L_{xy} (cm)", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Cascade/hMassLambda", "Lambda mass;m_{p#pi^{-}} (GeV/c^{2})", kTH1F, {{100, 1.08, 1.18}}, false); fRegistry.add("Cascade/hMassXi", "#Xi mass;m_{#Lambda#pi} (GeV/c^{2})", kTH1F, {{100, 1.27, 1.37}}, false); fRegistry.add("Cascade/hMassOmega", "#Omega mass;m_{#LambdaK} (GeV/c^{2})", kTH1F, {{100, 1.62, 1.72}}, false); @@ -768,9 +776,10 @@ struct taggingHFE { return (cascadeCut.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < cascadeCut.cfg_max_mass_Omega) && (cascade.mXi() < cascadeCut.cfg_min_mass_Xi_veto || cascadeCut.cfg_max_mass_Xi_veto < cascade.mXi()); } - template + template bool isSelectedV0Leg(TTrack const& track) { + // trackType = 0:v0leg, 1:v0leg in cascade, 2:bachelor of cascade only for ITS requirements if constexpr (isMC) { if (!track.has_mcParticle()) { return false; @@ -781,15 +790,21 @@ struct taggingHFE { return false; } - if (track.itsChi2NCl() > v0Cut.cfg_max_chi2its) { - return false; - } - - if (track.itsNCls() < v0Cut.cfg_min_ncluster_its) { - return false; + if constexpr (trackType == 0) { + if (track.itsNCls() < v0Cut.cfg_min_ncluster_its) { // must be 2 + return false; + } + } else if constexpr (trackType == 1) { + if (track.itsNCls() < cascadeCut.cfg_min_ncluster_its_v0leg) { // must be 2 + return false; + } + } else if constexpr (trackType == 2) { + if (track.itsNCls() < cascadeCut.cfg_min_ncluster_its_bachelor) { // must be 2 + return false; + } } - if (track.itsNClsInnerBarrel() < v0Cut.cfg_min_ncluster_itsib) { + if (track.itsChi2NCl() > v0Cut.cfg_max_chi2its) { return false; } @@ -816,6 +831,35 @@ struct taggingHFE { return true; } + template + bool checkITSibForV0Legs(TTrack const& t1, TTrack const& t2) + { + // typeSV = 0:v0, 1:cascade + if constexpr (typeSV == 0) { // V0 legs + if (v0Cut.cfg_itsib_type == 0) { // free + return true; + } else if (v0Cut.cfg_itsib_type == 1) { // OR + return t1.itsNClsInnerBarrel() >= v0Cut.cfg_min_ncluster_itsib || t2.itsNClsInnerBarrel() >= v0Cut.cfg_min_ncluster_itsib; + } else if (v0Cut.cfg_itsib_type == 2) { // AND + return t1.itsNClsInnerBarrel() >= v0Cut.cfg_min_ncluster_itsib && t2.itsNClsInnerBarrel() >= v0Cut.cfg_min_ncluster_itsib; + } else { + return true; + } + } else if constexpr (typeSV == 1) { // V0 legs in cascade + if (cascadeCut.cfg_itsib_type == 0) { // free + return true; + } else if (cascadeCut.cfg_itsib_type == 1) { // OR + return t1.itsNClsInnerBarrel() >= cascadeCut.cfg_min_ncluster_itsib_v0leg || t2.itsNClsInnerBarrel() >= cascadeCut.cfg_min_ncluster_itsib_v0leg; + } else if (cascadeCut.cfg_itsib_type == 2) { // AND + return t1.itsNClsInnerBarrel() >= cascadeCut.cfg_min_ncluster_itsib_v0leg && t2.itsNClsInnerBarrel() >= cascadeCut.cfg_min_ncluster_itsib_v0leg; + } else { + return true; + } + } else { + return true; + } + } + template void fillEventHistograms(TCollision const& collision) { @@ -879,8 +923,10 @@ struct taggingHFE { fRegistry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); fRegistry.fill(HIST("Cascade/hCosPA"), cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ())); fRegistry.fill(HIST("Cascade/hDCA2Legs"), cascade.dcacascdaughters()); + fRegistry.fill(HIST("Cascade/hLxy"), cascade.cascradius()); fRegistry.fill(HIST("Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); fRegistry.fill(HIST("Cascade/hV0DCA2Legs"), cascade.dcaV0daughters()); + fRegistry.fill(HIST("Cascade/hV0Lxy"), cascade.v0radius()); if (cascade.sign() < 0) { // Xi- or Omega- if (isPionFromXi(collision, bachelor) && isProtonFromLambdaFromXi(collision, pos) && isPionFromLambdaFromXi(collision, neg)) { @@ -1180,7 +1226,7 @@ struct taggingHFE { if (pos.sign() * neg.sign() > 0) { continue; } - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { + if (!isSelectedV0Leg<0, true>(pos) || !isSelectedV0Leg<0, true>(neg)) { continue; } @@ -1257,7 +1303,7 @@ struct taggingHFE { continue; } - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg) || !isSelectedV0Leg(bachelor)) { + if (!isSelectedV0Leg<1, true>(pos) || !isSelectedV0Leg<1, true>(neg) || !isSelectedV0Leg<2, true>(bachelor)) { continue; } @@ -1517,7 +1563,11 @@ struct taggingHFE { for (const auto& v0 : v0s_per_coll) { auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { + if (!isSelectedV0Leg<0, isMC>(pos) || !isSelectedV0Leg<0, isMC>(neg)) { + continue; + } + + if (!checkITSibForV0Legs<0>(pos, neg)) { continue; } @@ -1570,7 +1620,10 @@ struct taggingHFE { continue; } - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg) || !isSelectedV0Leg(bachelor)) { + if (!isSelectedV0Leg<1, isMC>(pos) || !isSelectedV0Leg<1, isMC>(neg) || !isSelectedV0Leg<2, isMC>(bachelor)) { + continue; + } + if (!checkITSibForV0Legs<1>(pos, neg)) { continue; } From 7b8df4bbaed1f0ec52cb2a67e4478033c21ffaae Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 25 May 2026 02:55:00 +0200 Subject: [PATCH 277/449] [PWGEM/Dilepton] fix nBins CutDir (#16364) --- PWGEM/Dilepton/Utils/ElectronModule.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index d1283127ca8..f71f7d3d7a9 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -427,7 +427,7 @@ class ElectronModule if (fConfigDFeT.useML) { static constexpr int nClassesMl = 4; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; const uint32_t nBinsMl = fConfigDFeT.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); @@ -453,7 +453,7 @@ class ElectronModule if (fConfigDFeV0.useML) { static constexpr int nClassesMl = 4; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; const uint32_t nBinsMl = fConfigDFeV0.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); @@ -479,7 +479,7 @@ class ElectronModule if (fConfigDFeC.useML) { static constexpr int nClassesMl = 4; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; const uint32_t nBinsMl = fConfigDFeC.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); From 9a3711095b2337b0c8eec31e492f35abe3f39a8d Mon Sep 17 00:00:00 2001 From: Cristian-Moscatelli Date: Mon, 25 May 2026 10:48:59 +0200 Subject: [PATCH 278/449] [PWGLF] Add INEL>0 event selection in PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx (#16351) Co-authored-by: Cristian Moscatelli --- .../Nuspex/deuteronInTriggeredEvents.cxx | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx index 8749d248835..0f309b028d0 100644 --- a/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx +++ b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx @@ -29,6 +29,7 @@ // same as Data and o2-analysis-mccollision-converter #include "PWGLF/DataModel/LFSlimNucleiTables.h" +#include "PWGLF/Utils/inelGt.h" // #include "PWGJE/Core/JetBkgSubUtils.h" #include "PWGJE/Core/JetUtilities.h" @@ -57,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -205,14 +207,15 @@ enum evSel { kIsGoodZvtxFT0vsPV, kIsGoodITSLayersAll, kIsEPtriggered, + kINELgt0, kIsJetTriggered, // Check: evSel for event with at least one jet over pT-threshold kNevSels }; static const std::vector eventSelectionTitle{"Event selections"}; -static const std::vector eventSelectionLabels{"TVX", "TF border", "ITS ROF border", "Z vtx", "No same-bunch pile-up", "kIsGoodZvtxFT0vsPV", "isGoodITSLayersAll", "isEPtriggered", "IsJetTriggered"}; +static const std::vector eventSelectionLabels{"TVX", "TF border", "ITS ROF border", "Z vtx", "No same-bunch pile-up", "kIsGoodZvtxFT0vsPV", "isGoodITSLayersAll", "isEPtriggered", "IsINELgt0", "IsJetTriggered"}; -constexpr int EvSelDefault[9][1]{ +constexpr int EvSelDefault[10][1]{ {1}, {1}, {1}, // Default: sel8 @@ -221,11 +224,13 @@ constexpr int EvSelDefault[9][1]{ {0}, {0}, {0}, + {0}, // INEL > 0 {1}}; // Triggered on jets enum evGenSel : uint8_t { - kGenIsJetTriggered = 1 << 0, - kGenHasRecoEv = 1 << 1 + kGenIsINELgt0 = 1 << 0, + kGenIsJetTriggered = 1 << 1, + kGenHasRecoEv = 1 << 2 }; enum triggerListName { @@ -254,7 +259,8 @@ struct DeuteronInTriggeredEvents { Produces nucleiTableMCExtension; // For MC analysis Produces GenEventMCSel; // For MC reco events Service ccdb; - Zorro zorro; // Definition of Zorro: helpful for skimmed data + Service pdgDB; // For INELgt0 gen MC selection + Zorro zorro; // Definition of Zorro: helpful for skimmed data OutputObj zorroSummary{"zorroSummary"}; Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", false, "If true, divide tpcInnerParam by the electric charge"}; @@ -280,7 +286,7 @@ struct DeuteronInTriggeredEvents { Configurable cfgCutPtMaxTree{"cfgCutPtMaxTree", 15.0f, "Maximum track transverse momentum for tree saving"}; // Event selections - Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 9, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; + Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 10, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {nuclei::bbMomScalingDefault[0], 5, 2, nuclei::names, nuclei::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; @@ -409,6 +415,11 @@ struct DeuteronInTriggeredEvents { spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsEPtriggered + 1); } + if (cfgEventSelections->get(nuclei::evSel::kINELgt0) && !collision.selection_bit(aod::kINELgtZERO)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kINELgt0 + 1); + auto bc = collision.template bc_as(); initCCDB(bc); @@ -494,6 +505,7 @@ struct DeuteronInTriggeredEvents { spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodZvtxFT0vsPV + 2, "isGoodZvtxFT0vsPV"); spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodITSLayersAll + 2, "IsGoodITSLayersAll"); spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsEPtriggered + 2, "IsEPtriggered"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kINELgt0 + 2, "IsINELgt0"); spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsJetTriggered + 2, "IsJetTriggered"); // Distribution of z-vertex of selected events @@ -943,8 +955,11 @@ struct DeuteronInTriggeredEvents { auto mcParticlesPerColl = particlesMC.sliceBy(perMcCollision, c.globalIndex()); auto& mask = eventMask[c.globalIndex()]; + if (o2::pwglf::isINELgt0mc(mcParticlesPerColl, pdgDB)) + mask |= nuclei::kGenIsINELgt0; + if (isMCJetTriggered(mcParticlesPerColl, particlesMC, trigger)) - mask |= nuclei::kIsJetTriggered; + mask |= nuclei::kGenIsJetTriggered; } for (const auto& collision : collisions) { @@ -971,10 +986,13 @@ struct DeuteronInTriggeredEvents { auto& mask = eventMask[mcId]; mask |= nuclei::kGenHasRecoEv; - GenEventMCSel(mask); fillDataInfo(collision, slicedTracks); } + for (const auto& c : mcCollisions) { + GenEventMCSel(eventMask[c.globalIndex()]); + } + std::vector isReconstructed(particlesMC.size(), false); for (auto& c : nuclei::candidates) { auto label = tracks.iteratorAt(c.globalIndex); From 0f74b890d55b7a720a6ec6ec206f2c686684e250 Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Tue, 26 May 2026 07:01:46 +0200 Subject: [PATCH 279/449] [PWGCF] Updating PID strategy (#16370) Co-authored-by: Sushanta Tripathy --- .../Tasks/nucleibalance.cxx | 116 +++++++++++++++--- 1 file changed, 99 insertions(+), 17 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx index 64059ba5e9e..b70f6037b85 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -1677,6 +1677,10 @@ struct Lambdastarproxy { static constexpr float TofBetaMin = 0.01f; static constexpr float TofBetaMax = 1.2f; static constexpr double Half = 0.5; + // PID strategy values + static constexpr int PidStrategyRectangular = 0; + static constexpr int PidStrategyCircularTPCAndTOF = 1; + static constexpr int PidStrategyTOFOnly = 2; // Basic configuration for event and track selection Configurable lstarCutVertex{"lstarCutVertex", float{CutVertexDefault}, "Accepted z-vertex range (cm)"}; Configurable lstarCutPtMin{"lstarCutPtMin", float{CutPtMinDefault}, "Minimal pT for tracks (GeV/c)"}; @@ -1696,6 +1700,24 @@ struct Lambdastarproxy { Configurable lstarCutNsigmaTOFKaon{"lstarCutNsigmaTOFKaon", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{K}| cut"}; Configurable lstarCutNsigmaTPCDe{"lstarCutNsigmaTPCDe", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{d}| cut"}; Configurable lstarCutNsigmaTOFDe{"lstarCutNsigmaTOFDe", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{d}| cut"}; + // PID strategy for final K/p/d candidate selection. + // 0 = rectangular cuts: |TPC| < cut and, if TOF exists, |TOF| < cut + // 1 = pT-ref dependent circular cut: + // pT < pTref: require |TPC| < TPC cut only + // pT >= pTref and TOF exists: require sqrt(TPC^2 + TOF^2) < circular cut + // pT >= pTref and TOF missing: reject + // 2 = TOF-only above pTref: + // pT < pTref: require |TPC| < TPC cut only + // pT >= pTref: require TOF hit and |TOF| < TOF cut + Configurable lstarPidStrategy{"lstarPidStrategy", int{PidStrategyRectangular}, "PID strategy: 0=rectangular TPC/TOF, 1=pTref circular TPC+TOF, 2=pTref TOF-only"}; + + Configurable lstarPidCircularCutKaon{"lstarPidCircularCutKaon", 2.0f, "Circular PID cut sqrt(nSigmaTPC_K^2+nSigmaTOF_K^2) for kaons"}; + Configurable lstarPidCircularCutPr{"lstarPidCircularCutPr", 2.0f, "Circular PID cut sqrt(nSigmaTPC_p^2+nSigmaTOF_p^2) for protons"}; + Configurable lstarPidCircularCutDe{"lstarPidCircularCutDe", 2.0f, "Circular PID cut sqrt(nSigmaTPC_d^2+nSigmaTOF_d^2) for deuterons"}; + + Configurable lstarPidPtRefKaon{"lstarPidPtRefKaon", 0.5f, "pT reference for kaon PID strategy"}; + Configurable lstarPidPtRefPr{"lstarPidPtRefPr", 0.8f, "pT reference for proton PID strategy"}; + Configurable lstarPidPtRefDe{"lstarPidPtRefDe", 0.8f, "pT reference for deuteron PID strategy"}; // Track quality Configurable lstarRequireGlobalTrack{"lstarRequireGlobalTrack", bool{RequireGlobalTrackDefault}, "Require global tracks (default)"}; @@ -2305,6 +2327,45 @@ struct Lambdastarproxy { return true; // fallback: if column not present, assume available } + bool passFinalCandidatePID(float pt, + float nsTPC, + float nsTOF, + bool hasTof, + float tpcCut, + float tofCut, + float circularCut, + float ptRef) const + { + // Strategy 1: analysis-note style circular TPC+TOF cut + if (lstarPidStrategy.value == PidStrategyCircularTPCAndTOF) { + if (pt < ptRef) { + return std::abs(nsTPC) < tpcCut; + } + + if (!hasTof) { + return false; + } + + return std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF) < circularCut; + } + + // Strategy 2: TOF-only above pTref + if (lstarPidStrategy.value == PidStrategyTOFOnly) { + if (pt < ptRef) { + return std::abs(nsTPC) < tpcCut; + } + + if (!hasTof) { + return false; + } + + return std::abs(nsTOF) < tofCut; + } + + // Strategy 0: old rectangular logic + return (std::abs(nsTPC) < tpcCut) && (!hasTof || (std::abs(nsTOF) < tofCut)); + } + // Return: 0=#pi, 1=K, 2=p, 3=d, -1=unclassified template int classifyPidSpecies(const TTrack& trk) @@ -2580,20 +2641,27 @@ struct Lambdastarproxy { continue; } + // Deuteron kinematics needed before PID because the PID strategy can depend on pT + const float ptD = trkD.pt(); + const float etaD = trkD.eta(); + const float phiD = trkD.phi(); + // PID for deuteron candidates const float nsTPCDe = trkD.tpcNSigmaDe(); const float nsTOFDe = trkD.tofNSigmaDe(); const bool hasTofDe = hasTOFMatch(trkD); - const bool isDeuteron = (std::abs(nsTPCDe) < lstarCutNsigmaTPCDe.value) && - (!hasTofDe || (std::abs(nsTOFDe) < lstarCutNsigmaTOFDe.value)); + const bool isDeuteron = passFinalCandidatePID(ptD, + nsTPCDe, + nsTOFDe, + hasTofDe, + lstarCutNsigmaTPCDe.value, + lstarCutNsigmaTOFDe.value, + lstarPidCircularCutDe.value, + lstarPidPtRefDe.value); if (!isDeuteron) { continue; } - // Deuteron kinematics - const float ptD = trkD.pt(); - const float etaD = trkD.eta(); - const float phiD = trkD.phi(); const double pD = static_cast(ptD) * std::cosh(static_cast(etaD)); // QA histos for deuteron PID and kinematics @@ -2642,18 +2710,25 @@ struct Lambdastarproxy { continue; } + const float ptP = trkP.pt(); + const float etaP = trkP.eta(); + const float phiP = trkP.phi(); + const float nsTPCPr = trkP.tpcNSigmaPr(); const float nsTOFPr = trkP.tofNSigmaPr(); const bool hasTofPr = hasTOFMatch(trkP); - const bool isProton = (std::abs(nsTPCPr) < lstarCutNsigmaTPCPr.value) && - (!hasTofPr || (std::abs(nsTOFPr) < lstarCutNsigmaTOFPr.value)); + const bool isProton = passFinalCandidatePID(ptP, + nsTPCPr, + nsTOFPr, + hasTofPr, + lstarCutNsigmaTPCPr.value, + lstarCutNsigmaTOFPr.value, + lstarPidCircularCutPr.value, + lstarPidPtRefPr.value); if (!isProton) { continue; } - const float ptP = trkP.pt(); - const float etaP = trkP.eta(); - const float phiP = trkP.phi(); const double pP = static_cast(ptP) * std::cosh(static_cast(etaP)); if (lstarEnablePidQA.value != 0) { @@ -2695,20 +2770,27 @@ struct Lambdastarproxy { continue; } + // Kaon kinematics needed before PID because the PID strategy can depend on pT + const float ptK = trkK.pt(); + const float etaK = trkK.eta(); + const float phiK = trkK.phi(); + // PID for kaon candidates const float nsTPCK = trkK.tpcNSigmaKa(); const float nsTOFK = trkK.tofNSigmaKa(); const bool hasTofK = hasTOFMatch(trkK); - const bool isKaon = (std::abs(nsTPCK) < lstarCutNsigmaTPCKaon.value) && - (!hasTofK || (std::abs(nsTOFK) < lstarCutNsigmaTOFKaon.value)); + const bool isKaon = passFinalCandidatePID(ptK, + nsTPCK, + nsTOFK, + hasTofK, + lstarCutNsigmaTPCKaon.value, + lstarCutNsigmaTOFKaon.value, + lstarPidCircularCutKaon.value, + lstarPidPtRefKaon.value); if (!isKaon) { continue; } - // Kaon kinematics - const float ptK = trkK.pt(); - const float etaK = trkK.eta(); - const float phiK = trkK.phi(); const double pK = static_cast(ptK) * std::cosh(static_cast(etaK)); // Kaon QA From b2421ab216d16d667bd49f4d8b5f906fb691427e Mon Sep 17 00:00:00 2001 From: blacwovie Date: Tue, 26 May 2026 14:48:55 +0800 Subject: [PATCH 280/449] [PWGCF] add configurable for pion selection (#16382) --- .../TableProducer/HadNucleiFemto.cxx | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index c132ac4c3bf..97708e877e2 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -193,6 +193,12 @@ struct HadNucleiFemto { Configurable settingEnablePionProtonRejection{"settingEnablePionProtonRejection", true, "If true, apply proton rejection in the pion PID"}; Configurable settingEnablePionKaonRejection{"settingEnablePionKaonRejection", true, "If true, apply kaon rejection in the pion PID"}; Configurable settingUsePionReferencePIDCuts{"settingUsePionReferencePIDCuts", false, "If true, use the reference pion track/PID cuts from the pi-p study"}; + Configurable settingPionRefPtMin{"settingPionRefPtMin", 0.14f, "Minimum pT for the reference pion track cuts"}; + Configurable settingPionRefPtMax{"settingPionRefPtMax", 2.5f, "Maximum pT for the reference pion track cuts"}; + Configurable settingPionRefITSInnerBarrelMin{"settingPionRefITSInnerBarrelMin", 3, "Minimum ITS inner barrel clusters for the reference pion track cuts"}; + Configurable settingPionRefITSNClsMin{"settingPionRefITSNClsMin", 7, "Minimum ITS clusters for the reference pion track cuts"}; + Configurable settingPionRefTPCNClsFoundMin{"settingPionRefTPCNClsFoundMin", 80, "Minimum found TPC clusters for the reference pion track cuts"}; + Configurable settingPionRefTPCCrossedRowsMin{"settingPionRefTPCCrossedRowsMin", 90, "Minimum crossed TPC rows for the reference pion track cuts"}; // Deuteron purity and PID cuts Configurable settingCutPinMinDe{"settingCutPinMinDe", 0.0f, "Minimum Pin for De"}; Configurable settingCutClSizeItsDe{"settingCutClSizeItsDe", 4.0f, "Minimum ITS cluster size for De"}; @@ -540,26 +546,19 @@ struct HadNucleiFemto { template bool selectTrackPionReference(const Ttrack& candidate) { - constexpr float pionRefPtMin = 0.14f; - constexpr float pionRefPtMax = 2.5f; - constexpr int pionRefITSInnerBarrelMin = 3; - constexpr int pionRefITSNClsMin = 7; - constexpr int pionRefTPCNClsFoundMin = 80; - constexpr int pionRefTPCCrossedRowsMin = 90; - if (std::abs(candidate.eta()) > settingCutEta) { return false; } const float absPt = std::abs(candidate.pt()); - if (absPt < pionRefPtMin || absPt > pionRefPtMax) { + if (absPt < settingPionRefPtMin || absPt > settingPionRefPtMax) { return false; } - if (candidate.itsNClsInnerBarrel() < pionRefITSInnerBarrelMin || - candidate.itsNCls() < pionRefITSNClsMin || - candidate.tpcNClsFound() < pionRefTPCNClsFoundMin || - candidate.tpcNClsCrossedRows() < pionRefTPCCrossedRowsMin) { + if (candidate.itsNClsInnerBarrel() < settingPionRefITSInnerBarrelMin || + candidate.itsNCls() < settingPionRefITSNClsMin || + candidate.tpcNClsFound() < settingPionRefTPCNClsFoundMin || + candidate.tpcNClsCrossedRows() < settingPionRefTPCCrossedRowsMin) { return false; } From 0c1c7fa1c2db687e4d600723bec19bedf208564e Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Tue, 26 May 2026 10:01:31 +0200 Subject: [PATCH 281/449] [PWGLF] Add thermal toy model and histograms for charged tracks + delta pt distributions (#16378) --- .../Strangeness/strangenessInJetsIons.cxx | 235 +++++++++++++++++- 1 file changed, 225 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index efe715d91be..e39ceb4020b 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -52,8 +52,10 @@ #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include +#include #include #include +#include #include #include @@ -109,7 +111,7 @@ struct StrangenessInJetsIons { HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryDataMB{"registryDataMB", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Global analysis parameters // List of Particles @@ -126,6 +128,19 @@ struct StrangenessInJetsIons { ParticleOfInterest::kProtons}; std::map particleOfInterestDict; + // --- Variables for the thermal toy-model + struct BkgFitParams { + float centMin; // Lower edge centrality bin + float centMax; // Upper edge centrality bin + double mass; // Levy-Tsallis: mass [GeV/c^2] + double n; // Levy-Tsallis: n + double C; // Levy-Tsallis: T (temperature) + double dNch_deta; // for FT0M + }; + TRandom3 fRng{0}; + TF1* fTsallisToy = nullptr; + // --- + Configurable> particleOfInterest{"particleOfInterest", {0, 0, 0, 0, 0}, "Particles to study: [K0 and Lambda, Xi and Omega, Pion, Kaon, Proton]"}; Configurable minJetPt{"minJetPt", 10.0, "Minimum reconstructed pt of the jet (GeV/c)"}; Configurable rJet{"rJet", 0.4, "Jet resolution parameter (R)"}; @@ -136,6 +151,7 @@ struct StrangenessInJetsIons { Configurable centrEstimator{"centrEstimator", 1, "Select centrality estimator. Options: 0 = FT0C, 1 = FT0M. CCDB objects available only for FT0M."}; Configurable calculateFeeddownMatrix{"calculateFeeddownMatrix", true, "Fill feeddown matrix for Lambda if MC"}; Configurable useV0inJetRec{"useV0inJetRec", true, "Include V0s in jet reconstruction"}; + Configurable doThermalToyModel{"doThermalToyModel", false, "Use the thermal toy model to embed background particles to the jet finder input list"}; Configurable saveChargedParticleMB{"saveChargedParticleMB", false, "Store charged particle information to build inclusive spectra."}; // Event selection @@ -250,6 +266,7 @@ struct StrangenessInJetsIons { const AxisSpec ptAxis{500, 0.0, 50.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec ptJetAxis{100, 0.0, 100.0, "#it{p}_{T,jet} (GeV/#it{c})"}; + const AxisSpec ptChargedAxis{10000, 0.0, 100.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec numJets{21, -0.5, 20.5, "Number of jets per collision"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassLambdaAxis{200, 1.09, 1.14, "m_{p#pi} (GeV/#it{c}^{2})"}; @@ -261,6 +278,8 @@ struct StrangenessInJetsIons { const AxisSpec dcaAxis{longLivedOptions.longLivedBinsDca, "DCA_{xy} (cm)"}; const AxisSpec alphaArmAxis{1000, -1.0f, 1.0f, "#alpha^{arm}"}; const AxisSpec qtarmAxis{1000, 0.0f, 0.30f, "q_{T}^{arm}"}; + const AxisSpec numBkgParticles{500, 0.0, 500.0, "Number of particles"}; + const AxisSpec deltaPtAxis{2400, -60.0, 60.0, "#delta #it{p}_{T} (GeV/#it{c})"}; // Join enum ParticleOfInterest and the configurable vector particlesOfInterest in a map particleOfInterestDict const std::vector& particleOnOff = particleOfInterest; @@ -278,6 +297,12 @@ struct StrangenessInJetsIons { LOG(fatal) << "No particles selected. Select at least one particle." << endl; } + // --- Distribution for the thermal toy model + fTsallisToy = new TF1("fTsallisToy", LevyTsallis_Func, 0.0, 50.0, 4); + fTsallisToy->SetParNames("mass", "n", "C", "norm"); + fTsallisToy->SetNpx(1000); + // --- + // Histograms for checks // registryQC.add("V0_type", "V0_type", HistType::kTH1F, {{10, -0.5, 9.5, "V0 type"}}); @@ -304,6 +329,10 @@ struct StrangenessInJetsIons { registryData.add("n_jets_vs_mult_pT", "n_jets_vs_mult_pT", HistType::kTH2F, {multAxis, ptJetAxis}); registryData.add("n_jets_vs_mult", "n_jets_vs_mult", HistType::kTH2F, {multAxis, numJets}); + // Delta pT distribution + registryData.add("delta_pT_data", "delta_pT_data", HistType::kTH2F, {multAxis, deltaPtAxis}); + registryData.add("delta_pT_RC_data", "delta_pT_RC_data", HistType::kTH2F, {multAxis, deltaPtAxis}); + // Armenteros-Podolanski plot // registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); @@ -366,6 +395,15 @@ struct StrangenessInJetsIons { registryMC.add("n_jets_vs_mult_pT_mc_gen", "n_jets_vs_mult_pT_mc_gen", HistType::kTH2F, {multAxis, ptJetAxis}); registryMC.add("n_jets_vs_mult_mc_gen", "n_jets_vs_mult_mc_gen", HistType::kTH2F, {multAxis, numJets}); + // Delta pT distribution + registryMC.add("delta_pT_gen", "delta_pT_gen", HistType::kTH2F, {multAxis, deltaPtAxis}); + // registryMC.add("delta_pT_RC_gen", "delta_pT_RC_gen", HistType::kTH2F, {multAxis, deltaPtAxis}); + + if (doThermalToyModel) { + registryMC.add("thermalToy_pT_gen", "thermalToy_pT_gen", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("thermalToy_nBkg_gen", "thermalToy_nBkg_gen", HistType::kTH2F, {multAxis, numBkgParticles}); + } + // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -462,6 +500,17 @@ struct StrangenessInJetsIons { registryMC.add("n_jets_vs_mult_pT_mc_rec", "n_jets_vs_mult_pT_mc_rec", HistType::kTH2F, {multAxis, ptJetAxis}); registryMC.add("n_jets_vs_mult_mc_rec", "n_jets_vs_mult_mc_rec", HistType::kTH2F, {multAxis, numJets}); + // Delta pT distribution + registryMC.add("delta_pT_rec", "delta_pT_rec", HistType::kTH2F, {multAxis, deltaPtAxis}); + + if (doThermalToyModel) { + registryMC.add("thermalToy_pT_rec", "thermalToy_pT_rec", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("thermalToy_nBkg_rec", "thermalToy_nBkg_rec", HistType::kTH2F, {multAxis, numBkgParticles}); + registryMC.add("chargedBkg_toy_rec_jet", "chargedBkg_toy_rec_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("chargedBkg_toy_rec_ue", "chargedBkg_toy_rec_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("charged_embedJets_rec_jet", "charged_embedJets_rec_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("charged_embedJets_rec_ue", "charged_embedJets_rec_ue", HistType::kTH2F, {multAxis, ptAxis}); + } // Armenteros-Podolanski plot // registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); @@ -591,7 +640,7 @@ struct StrangenessInJetsIons { registryDataMB.add("Proton_in_MB", "Proton_in_MB", HistType::kTHnSparseF, {multAxis, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); } if (saveChargedParticleMB) { - registryDataMB.add("ChargedTrack_in_MB", "ChargedTrack_in_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryDataMB.add("ChargedTrack_in_MB", "ChargedTrack_in_MB", HistType::kTH2F, {multAxis, ptChargedAxis}); } } } @@ -1920,6 +1969,91 @@ struct StrangenessInJetsIons { // LOG(info) << "[AddV0sForJetReconstructionMCP] Size fjInput dopo move: " << fjInput.size(); } + // --- LEVY-TSALLIS --- + // Implementation adapted from: https://github.com/alisw/AliPhysics/blob/master/PWGLF/SPECTRA/UTILS/SpectraUtils.C + static double LevyTsallis_Func(const double* x, const double* p) + { + double pt = x[0]; + double mass = p[0]; + double mt = std::sqrt(pt * pt + mass * mass); + double n = p[1]; + double C = p[2]; + double norm = p[3]; + + double part1 = (n - 1.) * (n - 2.); + double part2 = n * C * (n * C + mass * (n - 2.)); + double part3 = part1 / part2; + double part4 = 1. + (mt - mass) / n / C; + double part5 = TMath::Power(part4, -n); + return pt * norm * part3 * part5; + } + // -------------------- + + /** + * @brief Inject particles of the thermal toy model into the input list for the jet finder + * @param[in,out] fjInput Vector of FastJet PseudoJets where thermal background will be appended. + * @param[in] centrality + * @param[in] isReco if true (RECO MC), do not store id -999 with set_user_index() + */ + void InjectThermalBackground(std::vector& fjInput, std::vector& toyTracks, float centrality, bool isReco = false) + { + // Fit results of charged-particle spectra in MB OO data using Levy-Tsallis + static const std::vector bkgTable = { + // centMin, centMax, mass, n, C, dNch_deta + {0.0, 5.0, 0.50369, 6.496, 0.1778, 126.764}, + {5.0, 10.0, 0.51298, 6.346, 0.1724, 105.196}, + {10.0, 20.0, 0.51757, 6.221, 0.1685, 86.0196}, + {20.0, 30.0, 0.52036, 6.089, 0.1646, 66.2334}, + {30.0, 50.0, 0.52361, 5.927, 0.1594, 44.3346}, + {50.0, 100.0, 0.56123, 5.570, 0.1432, 24.30225}}; + // {0.0, 100.0, 0.52145, 6.072, 0.1635, 37.8073} + + // Extract parameters for this centrality value + BkgFitParams currentParams = bkgTable.back(); // fallback to last element + for (const auto& params : bkgTable) { + if (centrality >= params.centMin && centrality < params.centMax) { + currentParams = params; + break; + } + } + + fTsallisToy->SetParameters(currentParams.mass, currentParams.n, currentParams.C, 1.0); + + // Compute number of background particles in the event using poissonian fluctuations + double etaWindow = std::fabs(configTracks.etaMax - configTracks.etaMin); + double meanMultiplicity = currentParams.dNch_deta * etaWindow; + int nBkgParticles = fRng.Poisson(meanMultiplicity); + if (isReco) { + registryMC.fill(HIST("thermalToy_nBkg_rec"), centrality, nBkgParticles); + } else { + registryMC.fill(HIST("thermalToy_nBkg_gen"), centrality, nBkgParticles); + } + // Generation and embedding of background particles + for (int i = 0; i < nBkgParticles; ++i) { + // Compute pT using Levy-Tsallis + isotropic background + double pt = fTsallisToy->GetRandom(&fRng); + double phi = fRng.Uniform(0.0, TMath::TwoPi()); + double eta = fRng.Uniform(configTracks.etaMin, configTracks.etaMax); + + double px = pt * std::cos(phi); + double py = pt * std::sin(phi); + double pz = pt * std::sinh(eta); + double energy = GetEnergy(px, py, pz, currentParams.mass); + fastjet::PseudoJet bkgParticle(px, py, pz, energy); + + // ID = -999, to identify these background particles + if (isReco) { + registryMC.fill(HIST("thermalToy_pT_rec"), centrality, pt); + } else { + bkgParticle.set_user_index(-999); + registryMC.fill(HIST("thermalToy_pT_gen"), centrality, pt); + } + + fjInput.push_back(bkgParticle); + toyTracks.emplace_back(bkgParticle); + } + } + // Process data void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, DaughterTracks const& tracks, @@ -2022,6 +2156,14 @@ struct StrangenessInJetsIons { std::vector ue2; std::vector jetPt; + // Event multiplicity + float multiplicity; + if (centrEstimator == 0) { + multiplicity = collision.centFT0C(); + } else { + multiplicity = collision.centFT0M(); + } + // Loop over reconstructed jets for (const auto& jet : jets) { @@ -2036,6 +2178,10 @@ struct StrangenessInJetsIons { continue; isAtLeastOneJetSelected = true; + // delta pT distribution after jet selection by pT + double deltaPt = jet.pt() - jetMinusBkg.pt(); + registryData.fill(HIST("delta_pT_data"), multiplicity, deltaPt); + // Calculation of perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); @@ -2056,14 +2202,6 @@ struct StrangenessInJetsIons { // Fill event counter with events with at least one jet registryData.fill(HIST("number_of_events_data"), 7.5); - // Event multiplicity - float multiplicity; - if (centrEstimator == 0) { - multiplicity = collision.centFT0C(); - } else { - multiplicity = collision.centFT0M(); - } - // Fill event multiplicity registryData.fill(HIST("number_of_events_vsmultiplicity"), multiplicity); registryData.fill(HIST("n_jets_vs_mult"), multiplicity, static_cast(selectedJet.size())); @@ -2252,6 +2390,7 @@ struct StrangenessInJetsIons { { // Define per-event particle containers std::vector fjParticles; + std::vector toyTracks; std::vector strHadronMomentum; std::vector pdg; @@ -2293,6 +2432,7 @@ struct StrangenessInJetsIons { // Clear containers at the start of the event loop fjParticles.clear(); + toyTracks.clear(); strHadronMomentum.clear(); pdg.clear(); @@ -2356,6 +2496,9 @@ struct StrangenessInJetsIons { AddV0sForJetReconstructionMCP(fjParticles, fjParticleObj, mcParticlesPerColl, mcParticles); } + if (doThermalToyModel) + InjectThermalBackground(fjParticles, toyTracks, genMultiplicity); + // Skip events with no particles if (fjParticles.size() < 1) continue; @@ -2392,6 +2535,10 @@ struct StrangenessInJetsIons { // Fill jet counter registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); + // delta pT distribution after jet selection by pT + double deltaPt = jet.pt() - jetMinusBkg.pt(); + registryMC.fill(HIST("delta_pT_gen"), genMultiplicity, deltaPt); + // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); double coneRadius = std::sqrt(jet.area() / PI); // TODO: replace with rJet (similar results) @@ -2579,6 +2726,7 @@ struct StrangenessInJetsIons { { // Define per-event containers std::vector fjParticles; + std::vector toyTracks; std::vector selectedJet; std::vector ue1; std::vector ue2; @@ -2600,6 +2748,7 @@ struct StrangenessInJetsIons { // Clear containers at the start of the event loop fjParticles.clear(); + toyTracks.clear(); selectedJet.clear(); ue1.clear(); ue2.clear(); @@ -2667,6 +2816,9 @@ struct StrangenessInJetsIons { } fjTracks.clear(); + if (doThermalToyModel) + InjectThermalBackground(fjParticles, toyTracks, multiplicity, true); + // Reject empty events if (fjParticles.size() < 1) continue; @@ -2695,6 +2847,10 @@ struct StrangenessInJetsIons { continue; isAtLeastOneJetSelected = true; + // delta pT distribution after jet selection by pT + double deltaPt = jet.pt() - jetMinusBkg.pt(); + registryMC.fill(HIST("delta_pT_rec"), multiplicity, deltaPt); + // Perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); @@ -2991,6 +3147,65 @@ struct StrangenessInJetsIons { } } } + + // ------------------------------------------------------------------ + // Background toy particles + if (doThermalToyModel) { + // Store charged particles reconstructed in embeded jets + for (auto const& track : tracksPerColl) { + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + const double deltaEtaJet = track.eta() - selectedJet[i].Eta(); + const double deltaPhiJet = getDeltaPhi(track.phi(), selectedJet[i].Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + + const double deltaEtaUe1 = track.eta() - ue1[i].Eta(); + const double deltaPhiUe1 = getDeltaPhi(track.phi(), ue1[i].Phi()); + const double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + + const double deltaEtaUe2 = track.eta() - ue2[i].Eta(); + const double deltaPhiUe2 = getDeltaPhi(track.phi(), ue2[i].Phi()); + const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Charged track in jet + if (deltaRJet < rJet) { + registryMC.fill(HIST("charged_embedJets_rec_jet"), multiplicity, track.pt()); + } + + // Charged track in UE + if (deltaRUe1 < rJet || deltaRUe2 < rJet) { + registryMC.fill(HIST("charged_embedJets_rec_ue"), multiplicity, track.pt()); + } + } + + // Store toy charged particles (background particles) + for (const auto& toyPart : toyTracks) { + TVector3 toyMom(toyPart.px(), toyPart.py(), toyPart.pz()); + + const double deltaEtaJet = toyMom.Eta() - selectedJet[i].Eta(); + const double deltaPhiJet = getDeltaPhi(toyMom.Phi(), selectedJet[i].Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + + const double deltaEtaUe1 = toyMom.Eta() - ue1[i].Eta(); + const double deltaPhiUe1 = getDeltaPhi(toyMom.Phi(), ue1[i].Phi()); + const double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + + const double deltaEtaUe2 = toyMom.Eta() - ue2[i].Eta(); + const double deltaPhiUe2 = getDeltaPhi(toyMom.Phi(), ue2[i].Phi()); + const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Background particles in jet + if (deltaRJet < rJet) { + registryMC.fill(HIST("chargedBkg_toy_rec_jet"), multiplicity, toyMom.Pt()); + } + // Background particles in UE + if (deltaRUe1 < rJet || deltaRUe2 < rJet) { + registryMC.fill(HIST("chargedBkg_toy_rec_ue"), multiplicity, toyMom.Pt()); + } + } + } + // ------------------------------------------------------------------ } jetPt.clear(); } From 16db26a16c74c1f25f8934f2f263bcebe5f2b7f4 Mon Sep 17 00:00:00 2001 From: Fernanda Torres <135931275+mtorresc15@users.noreply.github.com> Date: Tue, 26 May 2026 02:59:58 -0600 Subject: [PATCH 282/449] [PWGHF] Fix PID assignment in Xic0 and Omegac0 candidate creator (#16352) --- .../candidateCreatorXic0Omegac0.cxx | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index b2f6980d93f..3aa743aeeca 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -96,6 +96,28 @@ enum McMatchFlag : uint8_t { V0Unmatched }; +// Convert the absolute KFParticle PDG code to the O2 track PID enum needed by getTrackParCovFromKFP() +o2::track::PID::ID getTrackPIDFromPDG(const int pdg) +{ + switch (std::abs(pdg)) { + case kPiPlus: + return o2::track::PID::Pion; + case kKPlus: + return o2::track::PID::Kaon; + case kProton: + return o2::track::PID::Proton; + case kLambda0: + return o2::track::PID::Lambda; + case kXiMinus: + return o2::track::PID::XiMinus; + case kOmegaMinus: + return o2::track::PID::OmegaMinus; + default: + LOGF(fatal, "Unsupported PDG code %d in getTrackPIDFromPDG()", pdg); + return o2::track::PID::Pion; + } +} + // Reconstruction of omegac0 and xic0 candidates struct HfCandidateCreatorXic0Omegac0 { Produces rowCandToXiPi; @@ -959,12 +981,16 @@ struct HfCandidateCreatorXic0Omegac0 { omegaDauChargedTrackParCov = getTrackParCovFromKFP(kfBachKaonToOmega, o2::track::PID::Kaon, bachCharge); // Cascade bach kaon omegaDauChargedTrackParCov.setAbsCharge(1); - o2::track::TrackParCov trackCasc = getTrackParCovFromKFP(kfOmegaToOmegaC, kfOmegaToOmegaC.GetPDG(), bachCharge); + o2::track::PID::ID pidCasc = getTrackPIDFromPDG(kfOmegaToOmegaC.GetPDG()); + o2::track::TrackParCov trackCasc = getTrackParCovFromKFP(kfOmegaToOmegaC, pidCasc, bachCharge); trackCasc.setAbsCharge(1); - trackParCovV0Dau0 = getTrackParCovFromKFP(kfPos, kfPos.GetPDG(), 1); // V0 postive daughter + o2::track::PID::ID pidV0Dau0 = getTrackPIDFromPDG(kfPos.GetPDG()); + trackParCovV0Dau0 = getTrackParCovFromKFP(kfPos, pidV0Dau0, +1); // V0 postive daughter trackParCovV0Dau0.setAbsCharge(1); - trackParCovV0Dau1 = getTrackParCovFromKFP(kfNeg, kfNeg.GetPDG(), -1); // V0 negtive daughter + + o2::track::PID::ID pidV0Dau1 = getTrackPIDFromPDG(kfNeg.GetPDG()); + trackParCovV0Dau1 = getTrackParCovFromKFP(kfNeg, pidV0Dau1, -1); // V0 negative daughter trackParCovV0Dau1.setAbsCharge(1); //-------------------------- V0 info--------------------------- @@ -1452,12 +1478,17 @@ struct HfCandidateCreatorXic0Omegac0 { xiDauChargedTrackParCov = getTrackParCovFromKFP(kfBachPionToXi, o2::track::PID::Pion, bachCharge); // Cascade bach pion xiDauChargedTrackParCov.setAbsCharge(1); - o2::track::TrackParCov trackCasc = getTrackParCovFromKFP(kfXiToXiC, kfXiToXiC.GetPDG(), bachCharge); + + o2::track::PID::ID pidCasc = getTrackPIDFromPDG(kfXiToXiC.GetPDG()); + o2::track::TrackParCov trackCasc = getTrackParCovFromKFP(kfXiToXiC, pidCasc, bachCharge); trackCasc.setAbsCharge(1); - trackParCovV0Dau0 = getTrackParCovFromKFP(kfPos, kfPos.GetPDG(), 1); // V0 postive daughter + o2::track::PID::ID pidV0Dau0 = getTrackPIDFromPDG(kfPos.GetPDG()); + trackParCovV0Dau0 = getTrackParCovFromKFP(kfPos, pidV0Dau0, +1); // V0 postive daughter trackParCovV0Dau0.setAbsCharge(1); - trackParCovV0Dau1 = getTrackParCovFromKFP(kfNeg, kfNeg.GetPDG(), -1); // V0 negtive daughter + + o2::track::PID::ID pidV0Dau1 = getTrackPIDFromPDG(kfNeg.GetPDG()); + trackParCovV0Dau1 = getTrackParCovFromKFP(kfNeg, pidV0Dau1, -1); // V0 negative daughter trackParCovV0Dau1.setAbsCharge(1); //-------------------------- V0 info--------------------------- From bc60c89f49f6b903ba1d7b4de36722e71eab9803 Mon Sep 17 00:00:00 2001 From: CyF1rmiana <3326561594@qq.com> Date: Tue, 26 May 2026 18:35:09 +0800 Subject: [PATCH 283/449] [PWGCF] Make q2 selection for resolution. (#16385) Co-authored-by: Shiqi Wang --- PWGCF/Flow/Tasks/flowEseTask.cxx | 290 +++++++++++++++++++++++++------ 1 file changed, 240 insertions(+), 50 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEseTask.cxx b/PWGCF/Flow/Tasks/flowEseTask.cxx index a4d66a46944..4f6ee235114 100644 --- a/PWGCF/Flow/Tasks/flowEseTask.cxx +++ b/PWGCF/Flow/Tasks/flowEseTask.cxx @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -155,12 +156,13 @@ struct FlowEseTask { ConfigurableAxis rapAxis{"rapAxis", {10, -0.5, 0.5}, "Rapidity axis"}; ConfigurableAxis qqAxis{"qqAxis", {100, -0.1, 0.1}, "qq axis"}; ConfigurableAxis multAxis{"multAxis", {300, 0, 2700}, "multiplicity"}; - ConfigurableAxis qvecAxis{"qvecAxis", {300, -1, 1}, "range of Qvector component"}; - ConfigurableAxis qvec2Axis{"qvec2Axis", {600, 0, 600}, "range of Qvector Module"}; + ConfigurableAxis qvecAxis{"qvecAxis", {600, 0, 600}, "range of Qvector Module"}; ConfigurableAxis lowerQAxis = {"lowerQAxis", {800, 0.0, 800.0}, "range of lowerQ QAplots"}; ConfigurableAxis upperQAxis = {"upperQAxis", {300, 0.0, 6.0}, "range of upperQ QAplots"}; - ConfigurableAxis lowerQAxisTPC = {"lowerQAxisTPC", {150, 0.0, 150.0}, "range of lowerQTPC QAplots"}; - ConfigurableAxis upperQAxisTPC = {"upperQAxisTPC", {100, 0.0, 10.0}, "range of upperQTPC QAplots"}; + + Configurable> cfgQ2SelBin{"cfgQ2SelBin", {0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, "centrality bins for q2 selection"}; + Configurable> cfgQ2Low{"cfgQ2Low", {124.2131f, 109.1698f, 91.9999f, 73.8884f, 56.9597f, 42.3456f, 30.2032f, 20.3889f, 0.0000f}, ""}; + Configurable> cfgQ2High{"cfgQ2High", {202.9085f, 171.5700f, 142.6870f, 116.0087f, 91.4749f, 69.2724f, 49.8817f, 33.8359f, 0.0000f}, ""}; static constexpr float MinAmplitudeThreshold = 1e-5f; static constexpr int ShiftLevel = 10; @@ -220,6 +222,53 @@ struct FlowEseTask { } } + enum class Q2Group { + Low, + Mid, + High + }; + + bool q2sel(float q2, Q2Group q2Group) + { + if (cfgQ2SelBin->empty() || cfgQ2Low->empty() || cfgQ2High->empty()) { + return false; + } + + auto it = std::upper_bound(cfgQ2SelBin->begin(), cfgQ2SelBin->end(), centrality); + int idx = std::distance(cfgQ2SelBin->begin(), it) - 1; + if (idx < 0) { + idx = 0; + } + if (idx >= static_cast(cfgQ2Low->size())) { + idx = cfgQ2Low->size() - 1; + } + if (idx >= static_cast(cfgQ2High->size())) { + idx = cfgQ2High->size() - 1; + } + + float low = cfgQ2Low->at(idx); + float high = cfgQ2High->at(idx); + if (q2Group == Q2Group::Low) { + return q2 < low; + } + if (q2Group == Q2Group::Mid) { + return q2 >= low && q2 < high; + } + if (q2Group == Q2Group::High) { + return q2 >= high; + } + return false; + } + + template + double getQ2(TCollision const& collision) + { + if (cfgMultCor) + return std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * collision.sumAmplFT0C() / std::sqrt(collision.multFT0C()); + else + return std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()); + } + void init(o2::framework::InitContext&) { AxisSpec centQaAxis = {80, 0.0, 80.0}; @@ -233,36 +282,22 @@ struct FlowEseTask { AxisSpec shiftAxis = {10, 0, 10, "shift"}; AxisSpec basisAxis = {20, 0, 20, "basis"}; - histos.add(Form("histQvecV2"), "", {HistType::kTH3F, {qvecAxis, qvecAxis, centAxis}}); histos.add(Form("histQvecCent"), "", {HistType::kTH3F, {lowerQAxis, upperQAxis, centQaAxis}}); - histos.add(Form("histMultCor"), "", {HistType::kTH2F, {multAxis, centAxis}}); - histos.add(Form("histMultUncor"), "", {HistType::kTH2F, {multAxis, centAxis}}); - histos.add(Form("histLowerQvecCentCor"), "", {HistType::kTH2F, {lowerQAxis, centQaAxis}}); - histos.add(Form("histLowerQvecCentUncor"), "", {HistType::kTH2F, {lowerQAxis, centQaAxis}}); - histos.add(Form("histUpperQvecCent"), "", {HistType::kTH2F, {upperQAxis, centQaAxis}}); - histos.add(Form("histLowerQvecCentTPCpos"), "", {HistType::kTH2F, {lowerQAxisTPC, centQaAxis}}); - histos.add(Form("histLowerQvecCentTPCneg"), "", {HistType::kTH2F, {lowerQAxisTPC, centQaAxis}}); - histos.add(Form("histLowerQvecCentTPCall"), "", {HistType::kTH2F, {lowerQAxisTPC, centQaAxis}}); - histos.add(Form("histUpperQvecCentTPCpos"), "", {HistType::kTH2F, {upperQAxisTPC, centQaAxis}}); - histos.add(Form("histUpperQvecCentTPCneg"), "", {HistType::kTH2F, {upperQAxisTPC, centQaAxis}}); - histos.add(Form("histUpperQvecCentTPCall"), "", {HistType::kTH2F, {upperQAxisTPC, centQaAxis}}); histos.add(Form("histVertex"), "", {HistType::kTHnSparseF, {vertexAxis, vertexAxis, vertexAxis, centAxis}}); - histos.add(Form("histV2"), "", {HistType::kTHnSparseF, {centAxis, ptAxis, cosAxis, qvec2Axis}}); - histos.add(Form("histV2_lambda"), "", {HistType::kTHnSparseF, {centAxis, ptAxis, cosAxis, qvec2Axis, massAxis}}); - histos.add(Form("histV2_alambda"), "", {HistType::kTHnSparseF, {centAxis, ptAxis, cosAxis, qvec2Axis, massAxis}}); + histos.add(Form("histV2_q2"), "", {HistType::kTHnSparseF, {centAxis, ptAxis, cosAxis, qvecAxis}}); histos.add("QA/CentDist", "", {HistType::kTH1F, {centQaAxis}}); histos.add("QA/PVzDist", "", {HistType::kTH1F, {pVzQaAxis}}); for (auto i = 2; i < cfgnMods + 2; i++) { histos.add(Form("psi%d/h_lambda_cos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, epAxis}}); histos.add(Form("psi%d/h_alambda_cos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, epAxis}}); - histos.add(Form("psi%d/h_lambda_cos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); - histos.add(Form("psi%d/h_alambda_cos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); + histos.add(Form("psi%d/h_lambda_cos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + histos.add(Form("psi%d/h_alambda_cos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); histos.add(Form("psi%d/h_lambda_cos2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, epAxis}}); histos.add(Form("psi%d/h_alambda_cos2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, epAxis}}); - histos.add(Form("psi%d/h_lambda_cos2_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); - histos.add(Form("psi%d/h_alambda_cos2_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); + histos.add(Form("psi%d/h_lambda_cos2_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + histos.add(Form("psi%d/h_alambda_cos2_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); if (cfgRapidityDep) { histos.add(Form("psi%d/h_lambda_cos2_rap", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, rapAxis}}); @@ -272,8 +307,16 @@ struct FlowEseTask { histos.add(Form("psi%d/h_lambda_cossin", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); histos.add(Form("psi%d/h_alambda_cossin", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); - histos.add(Form("psi%d/h_lambda_cossin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); - histos.add(Form("psi%d/h_alambda_cossin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); + histos.add(Form("psi%d/h_lambda_cossin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + histos.add(Form("psi%d/h_alambda_cossin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/h_lambda_cossin_q2low", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_lambda_cossin_q2mid", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_lambda_cossin_q2high", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_alambda_cossin_q2low", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_alambda_cossin_q2mid", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_alambda_cossin_q2high", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + } if (cfgAccAzimuth) { histos.add(Form("psi%d/h_lambda_coscos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); @@ -282,13 +325,23 @@ struct FlowEseTask { histos.add(Form("psi%d/h_lambda_vncos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); histos.add(Form("psi%d/h_lambda_vnsin", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); - histos.add(Form("psi%d/h_lambda_vncos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); - histos.add(Form("psi%d/h_lambda_vnsin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); + histos.add(Form("psi%d/h_lambda_vncos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + histos.add(Form("psi%d/h_lambda_vnsin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/h_lambda_vncos_q2low", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_lambda_vncos_q2mid", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_lambda_vncos_q2high", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + } histos.add(Form("psi%d/h_alambda_vncos", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); histos.add(Form("psi%d/h_alambda_vnsin", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); - histos.add(Form("psi%d/h_alambda_vncos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); - histos.add(Form("psi%d/h_alambda_vnsin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvec2Axis}}); + histos.add(Form("psi%d/h_alambda_vncos_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + histos.add(Form("psi%d/h_alambda_vnsin_q2", i), "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis, qvecAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/h_alambda_vncos_q2low", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_alambda_vncos_q2mid", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + histos.add("psi2/h_alambda_vncos_q2high", "", {HistType::kTHnSparseF, {massAxis, ptAxis, cosAxis, centAxis}}); + } } histos.add("QA/ptspec_l", "", {HistType::kTH3F, {massAxis, ptAxis, centAxis}}); histos.add("QA/ptspec_al", "", {HistType::kTH3F, {massAxis, ptAxis, centAxis}}); @@ -381,9 +434,50 @@ struct FlowEseTask { histos.add(Form("psi%d/QA/qqAxis_Det_RefB_yy", i), "", {HistType::kTH2F, {centQaAxis, qqAxis}}); histos.add(Form("psi%d/QA/qqAxis_RefA_RefB_yy", i), "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/QA/qqAxis_Det_RefA_xx_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_xx_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_xx_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_yy_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_yy_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_yy_q2", "", {HistType::kTH3F, {centQaAxis, qqAxis, qvecAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_xx_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_xx_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_xx_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_xx_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_xx_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_xx_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_xx_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_xx_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_xx_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_yy_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_yy_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefA_yy_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_yy_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_yy_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_Det_RefB_yy_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_yy_q2low", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_yy_q2mid", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + histos.add("psi2/QA/qqAxis_RefA_RefB_yy_q2high", "", {HistType::kTH2F, {centQaAxis, qqAxis}}); + } + histos.add(Form("psi%d/QA/EPRes_Det_RefA", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); histos.add(Form("psi%d/QA/EPRes_Det_RefB", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); histos.add(Form("psi%d/QA/EPRes_RefA_RefB", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/QA/EPRes_Det_RefA_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_Det_RefB_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_RefA_RefB_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_Det_RefA_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_Det_RefA_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_Det_RefA_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_Det_RefB_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_Det_RefB_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_Det_RefB_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_RefA_RefB_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_RefA_RefB_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_RefA_RefB_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + } histos.add(Form("psi%d/QA/EP_FT0C_shifted", i), "", {HistType::kTH2F, {centQaAxis, epQaAxis}}); histos.add(Form("psi%d/QA/EP_FT0A_shifted", i), "", {HistType::kTH2F, {centQaAxis, epQaAxis}}); @@ -392,6 +486,20 @@ struct FlowEseTask { histos.add(Form("psi%d/QA/EPRes_FT0C_FT0A_shifted", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); histos.add(Form("psi%d/QA/EPRes_FT0C_FV0A_shifted", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); histos.add(Form("psi%d/QA/EPRes_FT0A_FV0A_shifted", i), "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + if (i == CorrLevel[0]) { + histos.add("psi2/QA/EPRes_FT0C_FT0A_shifted_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FV0A_shifted_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_FT0A_FV0A_shifted_q2", "", {HistType::kTH3F, {centQaAxis, cosAxis, qvecAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FT0A_shifted_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FT0A_shifted_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FT0A_shifted_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FV0A_shifted_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FV0A_shifted_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0C_FV0A_shifted_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0A_FV0A_shifted_q2low", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0A_FV0A_shifted_q2mid", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + histos.add("psi2/QA/EPRes_FT0A_FV0A_shifted_q2high", "", {HistType::kTH2F, {centQaAxis, cosAxis}}); + } } } @@ -633,6 +741,60 @@ struct FlowEseTask { histos.fill(HIST("psi2/QA/EPRes_Det_RefA"), centrality, std::cos(std::atan2(collision.qvecIm()[qvecDetInd], collision.qvecRe()[qvecDetInd]) - std::atan2(collision.qvecIm()[qvecRefAInd], collision.qvecRe()[qvecRefAInd]))); histos.fill(HIST("psi2/QA/EPRes_Det_RefB"), centrality, std::cos(std::atan2(collision.qvecIm()[qvecDetInd], collision.qvecRe()[qvecDetInd]) - std::atan2(collision.qvecIm()[qvecRefBInd], collision.qvecRe()[qvecRefBInd]))); histos.fill(HIST("psi2/QA/EPRes_RefA_RefB"), centrality, std::cos(std::atan2(collision.qvecIm()[qvecRefAInd], collision.qvecRe()[qvecRefAInd]) - std::atan2(collision.qvecIm()[qvecRefBInd], collision.qvecRe()[qvecRefBInd]))); + double q2 = getQ2(collision); + double qqDetRefAxx = collision.qvecRe()[qvecDetInd] * collision.qvecRe()[qvecRefAInd]; + double qqDetRefBxx = collision.qvecRe()[qvecDetInd] * collision.qvecRe()[qvecRefBInd]; + double qqRefARefBxx = collision.qvecRe()[qvecRefAInd] * collision.qvecRe()[qvecRefBInd]; + double qqDetRefAyy = collision.qvecIm()[qvecDetInd] * collision.qvecIm()[qvecRefAInd]; + double qqDetRefByy = collision.qvecIm()[qvecDetInd] * collision.qvecIm()[qvecRefBInd]; + double qqRefARefByy = collision.qvecIm()[qvecRefAInd] * collision.qvecIm()[qvecRefBInd]; + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_xx_q2"), centrality, qqDetRefAxx, q2); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_xx_q2"), centrality, qqDetRefBxx, q2); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_xx_q2"), centrality, qqRefARefBxx, q2); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_yy_q2"), centrality, qqDetRefAyy, q2); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_yy_q2"), centrality, qqDetRefByy, q2); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_yy_q2"), centrality, qqRefARefByy, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_xx_q2low"), centrality, qqDetRefAxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_xx_q2low"), centrality, qqDetRefBxx); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_xx_q2low"), centrality, qqRefARefBxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_yy_q2low"), centrality, qqDetRefAyy); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_yy_q2low"), centrality, qqDetRefByy); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_yy_q2low"), centrality, qqRefARefByy); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_xx_q2mid"), centrality, qqDetRefAxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_xx_q2mid"), centrality, qqDetRefBxx); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_xx_q2mid"), centrality, qqRefARefBxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_yy_q2mid"), centrality, qqDetRefAyy); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_yy_q2mid"), centrality, qqDetRefByy); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_yy_q2mid"), centrality, qqRefARefByy); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_xx_q2high"), centrality, qqDetRefAxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_xx_q2high"), centrality, qqDetRefBxx); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_xx_q2high"), centrality, qqRefARefBxx); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefA_yy_q2high"), centrality, qqDetRefAyy); + histos.fill(HIST("psi2/QA/qqAxis_Det_RefB_yy_q2high"), centrality, qqDetRefByy); + histos.fill(HIST("psi2/QA/qqAxis_RefA_RefB_yy_q2high"), centrality, qqRefARefByy); + } + double epResDetRefA = std::cos(std::atan2(collision.qvecIm()[qvecDetInd], collision.qvecRe()[qvecDetInd]) - std::atan2(collision.qvecIm()[qvecRefAInd], collision.qvecRe()[qvecRefAInd])); + double epResDetRefB = std::cos(std::atan2(collision.qvecIm()[qvecDetInd], collision.qvecRe()[qvecDetInd]) - std::atan2(collision.qvecIm()[qvecRefBInd], collision.qvecRe()[qvecRefBInd])); + double epResRefARefB = std::cos(std::atan2(collision.qvecIm()[qvecRefAInd], collision.qvecRe()[qvecRefAInd]) - std::atan2(collision.qvecIm()[qvecRefBInd], collision.qvecRe()[qvecRefBInd])); + histos.fill(HIST("psi2/QA/EPRes_Det_RefA_q2"), centrality, epResDetRefA, q2); + histos.fill(HIST("psi2/QA/EPRes_Det_RefB_q2"), centrality, epResDetRefB, q2); + histos.fill(HIST("psi2/QA/EPRes_RefA_RefB_q2"), centrality, epResRefARefB, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/QA/EPRes_Det_RefA_q2low"), centrality, epResDetRefA); + histos.fill(HIST("psi2/QA/EPRes_Det_RefB_q2low"), centrality, epResDetRefB); + histos.fill(HIST("psi2/QA/EPRes_RefA_RefB_q2low"), centrality, epResRefARefB); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/QA/EPRes_Det_RefA_q2mid"), centrality, epResDetRefA); + histos.fill(HIST("psi2/QA/EPRes_Det_RefB_q2mid"), centrality, epResDetRefB); + histos.fill(HIST("psi2/QA/EPRes_RefA_RefB_q2mid"), centrality, epResRefARefB); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/QA/EPRes_Det_RefA_q2high"), centrality, epResDetRefA); + histos.fill(HIST("psi2/QA/EPRes_Det_RefB_q2high"), centrality, epResDetRefB); + histos.fill(HIST("psi2/QA/EPRes_RefA_RefB_q2high"), centrality, epResRefARefB); + } } else if (nmode == CorrLevel[1]) { histos.fill(HIST("psi3/QA/EP_Det"), centrality, std::atan2(collision.qvecIm()[qvecDetInd], collision.qvecRe()[qvecDetInd]) / static_cast(nmode)); histos.fill(HIST("psi3/QA/EP_RefA"), centrality, std::atan2(collision.qvecIm()[qvecRefAInd], collision.qvecRe()[qvecRefAInd]) / static_cast(nmode)); @@ -695,6 +857,26 @@ struct FlowEseTask { histos.fill(HIST("psi2/QA/EPRes_FT0C_FT0A_shifted"), centrality, std::cos(static_cast(nmode) * (psidefFT0C + deltapsiFT0C - psidefFT0A - deltapsiFT0A))); histos.fill(HIST("psi2/QA/EPRes_FT0C_FV0A_shifted"), centrality, std::cos(static_cast(nmode) * (psidefFT0C + deltapsiFT0C - psidefFV0A - deltapsiFV0A))); histos.fill(HIST("psi2/QA/EPRes_FT0A_FV0A_shifted"), centrality, std::cos(static_cast(nmode) * (psidefFT0A + deltapsiFT0A - psidefFV0A - deltapsiFV0A))); + double q2 = getQ2(collision); + double epResFT0CFT0AShifted = std::cos(static_cast(nmode) * (psidefFT0C + deltapsiFT0C - psidefFT0A - deltapsiFT0A)); + double epResFT0CFV0AShifted = std::cos(static_cast(nmode) * (psidefFT0C + deltapsiFT0C - psidefFV0A - deltapsiFV0A)); + double epResFT0AFV0AShifted = std::cos(static_cast(nmode) * (psidefFT0A + deltapsiFT0A - psidefFV0A - deltapsiFV0A)); + histos.fill(HIST("psi2/QA/EPRes_FT0C_FT0A_shifted_q2"), centrality, epResFT0CFT0AShifted, q2); + histos.fill(HIST("psi2/QA/EPRes_FT0C_FV0A_shifted_q2"), centrality, epResFT0CFV0AShifted, q2); + histos.fill(HIST("psi2/QA/EPRes_FT0A_FV0A_shifted_q2"), centrality, epResFT0AFV0AShifted, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/QA/EPRes_FT0C_FT0A_shifted_q2low"), centrality, epResFT0CFT0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0C_FV0A_shifted_q2low"), centrality, epResFT0CFV0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0A_FV0A_shifted_q2low"), centrality, epResFT0AFV0AShifted); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/QA/EPRes_FT0C_FT0A_shifted_q2mid"), centrality, epResFT0CFT0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0C_FV0A_shifted_q2mid"), centrality, epResFT0CFV0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0A_FV0A_shifted_q2mid"), centrality, epResFT0AFV0AShifted); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/QA/EPRes_FT0C_FT0A_shifted_q2high"), centrality, epResFT0CFT0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0C_FV0A_shifted_q2high"), centrality, epResFT0CFV0AShifted); + histos.fill(HIST("psi2/QA/EPRes_FT0A_FV0A_shifted_q2high"), centrality, epResFT0AFV0AShifted); + } } else if (nmode == CorrLevel[1]) { histos.fill(HIST("psi3/QA/EP_FT0C_shifted"), centrality, psidefFT0C + deltapsiFT0C); @@ -728,7 +910,7 @@ struct FlowEseTask { continue; } if (nmode == CorrLevel[0]) { - histos.fill(HIST("histV2"), collision.centFT0C(), trk.pt(), + histos.fill(HIST("histV2_q2"), collision.centFT0C(), trk.pt(), std::cos(static_cast(nmode) * (trk.phi() - helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode))), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C())); } @@ -736,19 +918,7 @@ struct FlowEseTask { histos.fill(HIST("histQvecCent"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]), centrality); - histos.fill(HIST("histLowerQvecCentCor"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * collision.sumAmplFT0C() / std::sqrt(collision.multFT0C()), centrality); - histos.fill(HIST("histLowerQvecCentUncor"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), centrality); - histos.fill(HIST("histUpperQvecCent"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]), centrality); - histos.fill(HIST("histQvecV2"), collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], collision.centFT0C()); - histos.fill(HIST("histMultCor"), collision.multFT0C(), collision.centFT0C()); - histos.fill(HIST("histMultUncor"), collision.sumAmplFT0C(), collision.centFT0C()); histos.fill(HIST("histVertex"), collision.posX(), collision.posY(), collision.posZ(), collision.centFT0C()); - histos.fill(HIST("histLowerQvecCentTPCpos"), std::sqrt(collision.qvecTPCposReVec()[0] * collision.qvecTPCposReVec()[0] + collision.qvecTPCposImVec()[0] * collision.qvecTPCposImVec()[0]) * std::sqrt(collision.nTrkTPCpos()), centrality); - histos.fill(HIST("histLowerQvecCentTPCneg"), std::sqrt(collision.qvecTPCnegReVec()[0] * collision.qvecTPCnegReVec()[0] + collision.qvecTPCnegImVec()[0] * collision.qvecTPCnegImVec()[0]) * std::sqrt(collision.nTrkTPCneg()), centrality); - histos.fill(HIST("histLowerQvecCentTPCall"), std::sqrt(collision.qvecTPCallReVec()[0] * collision.qvecTPCallReVec()[0] + collision.qvecTPCallImVec()[0] * collision.qvecTPCallImVec()[0]) * std::sqrt(collision.nTrkTPCall()), centrality); - histos.fill(HIST("histUpperQvecCentTPCpos"), std::sqrt(collision.qvecTPCposReVec()[0] * collision.qvecTPCposReVec()[0] + collision.qvecTPCposImVec()[0] * collision.qvecTPCposImVec()[0]), centrality); - histos.fill(HIST("histUpperQvecCentTPCneg"), std::sqrt(collision.qvecTPCnegReVec()[0] * collision.qvecTPCnegReVec()[0] + collision.qvecTPCnegImVec()[0] * collision.qvecTPCnegImVec()[0]), centrality); - histos.fill(HIST("histUpperQvecCentTPCall"), std::sqrt(collision.qvecTPCallReVec()[0] * collision.qvecTPCallReVec()[0] + collision.qvecTPCallImVec()[0] * collision.qvecTPCallImVec()[0]), centrality); for (const auto& v0 : V0s) { auto postrack = v0.template posTrack_as(); @@ -787,18 +957,10 @@ struct FlowEseTask { if (lambdaTag) { protonVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); pionVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); - histos.fill(HIST("histV2_lambda"), collision.centFT0C(), v0.pt(), - std::cos(static_cast(nmode) * (v0.phi() - helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode))), - std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), - v0.mLambda()); } if (aLambdaTag) { protonVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); pionVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); - histos.fill(HIST("histV2_alambda"), collision.centFT0C(), v0.pt(), - std::cos(static_cast(nmode) * (v0.phi() - helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode))), - std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), - v0.mAntiLambda()); } LambdaVec = protonVec + pionVec; LambdaVec.SetM(massLambda); @@ -877,7 +1039,21 @@ struct FlowEseTask { histos.fill(HIST("psi2/h_lambda_cos_q2"), v0.mLambda(), v0.pt(), angle * weight, centrality, q2); histos.fill(HIST("psi2/h_lambda_cos2_q2"), v0.mLambda(), v0.pt(), angle * angle, centrality, q2); histos.fill(HIST("psi2/h_lambda_cossin_q2"), v0.mLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/h_lambda_cossin_q2low"), v0.mLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/h_lambda_cossin_q2mid"), v0.mLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/h_lambda_cossin_q2high"), v0.mLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } histos.fill(HIST("psi2/h_lambda_vncos_q2"), v0.mLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/h_lambda_vncos_q2low"), v0.mLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/h_lambda_vncos_q2mid"), v0.mLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/h_lambda_vncos_q2high"), v0.mLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } histos.fill(HIST("psi2/h_lambda_vnsin_q2"), v0.mLambda(), v0.pt(), std::sin(relphi), centrality, q2); if (cfgRapidityDep) { @@ -932,7 +1108,21 @@ struct FlowEseTask { histos.fill(HIST("psi2/h_alambda_cos_q2"), v0.mAntiLambda(), v0.pt(), angle * weight, centrality, q2); histos.fill(HIST("psi2/h_alambda_cos2_q2"), v0.mAntiLambda(), v0.pt(), angle * angle, centrality, q2); histos.fill(HIST("psi2/h_alambda_cossin_q2"), v0.mAntiLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/h_alambda_cossin_q2low"), v0.mAntiLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/h_alambda_cossin_q2mid"), v0.mAntiLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/h_alambda_cossin_q2high"), v0.mAntiLambda(), v0.pt(), angle * std::sin(relphi) * weight, centrality); + } histos.fill(HIST("psi2/h_alambda_vncos_q2"), v0.mAntiLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality, q2); + if (q2sel(q2, Q2Group::Low)) { + histos.fill(HIST("psi2/h_alambda_vncos_q2low"), v0.mAntiLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::Mid)) { + histos.fill(HIST("psi2/h_alambda_vncos_q2mid"), v0.mAntiLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } else if (q2sel(q2, Q2Group::High)) { + histos.fill(HIST("psi2/h_alambda_vncos_q2high"), v0.mAntiLambda(), v0.pt(), qvecMag * std::cos(relphi) * weight, centrality); + } histos.fill(HIST("psi2/h_alambda_vnsin_q2"), v0.mAntiLambda(), v0.pt(), std::sin(relphi), centrality, q2); if (cfgRapidityDep) { From eb83f269b34d4443100aacb1c5fc5022a1e492f3 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 26 May 2026 13:06:28 +0200 Subject: [PATCH 284/449] [PWGDQ] enable processing of real data in matching tasks (#16340) --- PWGDQ/Tasks/mftMchMatcher.cxx | 81 +++-- PWGDQ/Tasks/qaMatching.cxx | 601 +++++++++++++++++++++------------- 2 files changed, 437 insertions(+), 245 deletions(-) diff --git a/PWGDQ/Tasks/mftMchMatcher.cxx b/PWGDQ/Tasks/mftMchMatcher.cxx index 5c8f668e5e8..d69afb2356c 100644 --- a/PWGDQ/Tasks/mftMchMatcher.cxx +++ b/PWGDQ/Tasks/mftMchMatcher.cxx @@ -574,19 +574,13 @@ struct mftMchMatcher { return result; } - void processMC(MyEvents const& collisions, - aod::BCsWithTimestamps const& bcs, - MyMuonsMC const& muonTracks, - MyMFTsMC const& mftTracks, - MyMFTCovariances const& mftCovs, - aod::McParticles const& /*mcParticles*/) + template + void fillTable(TCOLLS const& collisions, + TBCS const& /*bcs*/, + TMUONS const& muonTracks, + TMFTS const& mftTracks, + TCOVS const& mftCovs) { - if (bcs.size() > 0) { - auto bc = bcs.begin(); - initCCDB(bc); - VarManager::SetMatchingPlane(fzMatching.value); - } - registry.get(HIST("acceptedEvents"))->Fill(0); // reject a randomly selected fraction of events if (fSamplingFraction < 1.0) { @@ -600,7 +594,9 @@ struct mftMchMatcher { fillBestMuonMatches(muonTracks); std::vector> matchablePairs; - fillMatchablePairs(muonTracks, mftTracks, matchablePairs); + if constexpr (isMc) { + fillMatchablePairs(muonTracks, mftTracks, matchablePairs); + } mftCovIndexes.clear(); for (auto& mftTrackCov : mftCovs) { @@ -626,10 +622,10 @@ struct mftMchMatcher { } const auto& collision = collisions.rawIteratorAt(muon.collisionId()); - auto bc_coll = collision.bc_as(); + auto bc_coll = collision.template bc_as(); - auto muontrack = muon.template matchMCHTrack_as(); - auto mfttrack = muon.template matchMFTTrack_as(); + auto muontrack = muon.template matchMCHTrack_as(); + auto mfttrack = muon.template matchMFTTrack_as(); auto const& mfttrackcov = mftCovs.rawIteratorAt(mftCovIndexes[mfttrack.globalIndex()]); auto muonTime = muontrack.trackTime() + bc_coll.globalBC() * o2::constants::lhc::LHCBunchSpacingNS; @@ -657,9 +653,21 @@ struct mftMchMatcher { bool IsAmbig = (muon.compatibleCollIds().size() != 1); int MFTMult = collision.mftNtracks(); - auto matchType = getMatchType(muon, muonTracks, mftTracks, matchablePairs, isBestMatch); + auto matchType = kMatchTypeUndefined; + if constexpr (isMc) { + matchType = getMatchType(muon, muonTracks, mftTracks, matchablePairs, isBestMatch); + } bool isSignal = (matchType == kMatchTypeTrueLeading) || (matchType == kMatchTypeTrueNonLeading); + int mcMaskMuon = 0; + int mcMaskMft = 0; + int ncMaskGlob = 0; + if constexpr (isMc) { + mcMaskMuon = muontrack.mcMask(); + mcMaskMft = mfttrack.mcMask(); + ncMaskGlob = muon.mcMask(); + } + registry.get(HIST("matchType"))->Fill(static_cast(matchType)); fwdMatchMLCandidates( @@ -719,15 +727,48 @@ struct mftMchMatcher { muon.fwdDcaY(), IsAmbig, MFTMult, - muontrack.mcMask(), - mfttrack.mcMask(), - muon.mcMask(), + mcMaskMuon, + mcMaskMft, + ncMaskGlob, static_cast(matchType), isSignal); } } + void processMC(MyEvents const& collisions, + aod::BCsWithTimestamps const& bcs, + MyMuonsMC const& muonTracks, + MyMFTsMC const& mftTracks, + MyMFTCovariances const& mftCovs, + aod::McParticles const& /*mcParticles*/) + { + if (bcs.size() > 0) { + auto bc = bcs.begin(); + initCCDB(bc); + VarManager::SetMatchingPlane(fzMatching.value); + } + + fillTable(collisions, bcs, muonTracks, mftTracks, mftCovs); + } + PROCESS_SWITCH(mftMchMatcher, processMC, "process_MC", true); + + void processRD(MyEvents const& collisions, + aod::BCsWithTimestamps const& bcs, + MyMuonsWithCov const& muonTracks, + MyMFTs const& mftTracks, + MyMFTCovariances const& mftCovs) + { + if (bcs.size() > 0) { + auto bc = bcs.begin(); + initCCDB(bc); + VarManager::SetMatchingPlane(fzMatching.value); + } + + fillTable(collisions, bcs, muonTracks, mftTracks, mftCovs); + } + + PROCESS_SWITCH(mftMchMatcher, processRD, "process_RD", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 6f2056d9c24..5da0840fcc2 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -95,6 +95,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(MatchLabel, matchLabel, int8_t); DECLARE_SOA_COLUMN(TrackId, trackId, int64_t); DECLARE_SOA_COLUMN(MatchType, matchType, int8_t); +DECLARE_SOA_COLUMN(MatchChi2, matchChi2, float); DECLARE_SOA_COLUMN(MatchScore, matchScore, float); DECLARE_SOA_COLUMN(MatchRanking, matchRanking, int32_t); DECLARE_SOA_COLUMN(MftMultiplicity, mftMultiplicity, int32_t); @@ -152,7 +153,7 @@ DECLARE_SOA_TABLE(QaMatchingCandidates, "AOD", "QAMCAND", qamatching::MatchLabel, qamatching::TrackId, qamatching::P, qamatching::Pt, qamatching::Eta, qamatching::Phi, - qamatching::MatchType, qamatching::MatchScore, qamatching::MatchRanking, + qamatching::MatchType, qamatching::MatchChi2, qamatching::MatchScore, qamatching::MatchRanking, qamatching::XAtVtx, qamatching::YAtVtx, qamatching::ZAtVtx, @@ -184,6 +185,19 @@ static float chi2ToScore(float chi2, int ndf, float chi2max) return static_cast(result); } +static void setMatchTypeAxisLabels(TAxis* axis) +{ + axis->SetBinLabel(1, "true (leading)"); + axis->SetBinLabel(2, "wrong (leading)"); + axis->SetBinLabel(3, "decay (leading)"); + axis->SetBinLabel(4, "fake (leading)"); + axis->SetBinLabel(5, "true (non leading)"); + axis->SetBinLabel(6, "wrong (non leading)"); + axis->SetBinLabel(7, "decay (non leading)"); + axis->SetBinLabel(8, "fake (non leading)"); + axis->SetBinLabel(9, "unknown"); +} + struct QaMatching { template @@ -217,12 +231,15 @@ struct QaMatching { static constexpr int ExtrapolationMethodVertex = 3; static constexpr int ExtrapolationMethodMftDca = 4; static constexpr int DecayRankingDirect = 2; + static constexpr float MatchingPlaneDefaultZ = -77.5; struct MatchingCandidate { int64_t collisionId{-1}; int64_t globalTrackId{-1}; int64_t muonTrackId{-1}; int64_t mftTrackId{-1}; + o2::track::TrackParCovFwd mftTrackProp; + o2::track::TrackParCovFwd mchTrackProp; double matchScore{-1}; double matchChi2{-1}; int matchRanking{-1}; @@ -233,6 +250,8 @@ struct QaMatching { MuonMatchType matchType{kMatchTypeUndefined}; }; + Configurable cfgIsMc{"cfgIsMc", true, "Wheter the processed data is from MC simulations"}; + //// Variables for selecting muon tracks Configurable cfgPMchLow{"cfgPMchLow", 0.0f, ""}; Configurable cfgPtMchLow{"cfgPtMchLow", 0.7f, ""}; @@ -634,6 +653,42 @@ struct QaMatching { } }; + struct MatchFeaturesHistos { + o2::framework::HistPtr hDeltaP; + o2::framework::HistPtr hDeltaPt; + o2::framework::HistPtr hDeltaX; + o2::framework::HistPtr hDeltaY; + o2::framework::HistPtr hDeltaPhi; + o2::framework::HistPtr hDeltaTanl; + o2::framework::HistPtr hDeltaEta; + o2::framework::HistPtr hRabs; + + MatchFeaturesHistos(std::string path, HistogramRegistry* registry, int numCandidates) + { + AxisSpec indexAxis = {numCandidates + 1, 0, static_cast(numCandidates + 1), "ranking index"}; + AxisSpec scoreAxis = {100, 0, 1, "match score"}; + int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; + AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; + AxisSpec dxAxis = {100, -10, 10, "#Deltax (cm)"}; + AxisSpec dyAxis = {100, -10, 10, "#Deltay (cm)"}; + AxisSpec dpAxis = {100, -10, 10, "#Deltap (GeV/c)"}; + AxisSpec dptAxis = {100, -1, 1, "#Deltap_{T} (GeV/c)"}; + AxisSpec dphiAxis = {100, -1, 1, "#Delta#phi (rad)"}; + AxisSpec dtanlAxis = {100, -10, 10, "#Deltatanl"}; + AxisSpec detaAxis = {100, -1, 1, "#Delta#eta"}; + AxisSpec rabsAxis = {100, 0, 100, "R_{abs}"}; + + hDeltaP = registry->add((path + "/deltaP").c_str(), "MFT-MCH #Deltap", {HistType::kTHnSparseF, {dpAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaPt = registry->add((path + "/deltaPt").c_str(), "MFT-MCH #Deltap_{T}", {HistType::kTHnSparseF, {dptAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaX = registry->add((path + "/deltaX").c_str(), "MFT-MCH #Deltax", {HistType::kTHnSparseF, {dxAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaY = registry->add((path + "/deltaY").c_str(), "MFT-MCH #Deltay", {HistType::kTHnSparseF, {dyAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaPhi = registry->add((path + "/deltaPhi").c_str(), "MFT-MCH #Delta#phi", {HistType::kTHnSparseF, {dphiAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaTanl = registry->add((path + "/deltaTanl").c_str(), "MFT-MCH #DeltaTanl", {HistType::kTHnSparseF, {dtanlAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaEta = registry->add((path + "/deltaEta").c_str(), "MFT-MCH #Delta#eta", {HistType::kTHnSparseF, {detaAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hRabs = registry->add((path + "/Rabs").c_str(), "MFT-MCH R_{abs}", {HistType::kTHnSparseF, {rabsAxis, scoreAxis, indexAxis, matchTypeAxis}}); + } + }; + struct MatchRankingHistos { o2::framework::HistPtr hist; o2::framework::HistPtr histVsP; @@ -680,6 +735,8 @@ struct QaMatching { std::unique_ptr fMatchRankingPaired; std::unique_ptr fMatchRankingPairedGoodMCH; + std::unique_ptr fMatchFeaturesGoodMCH; + //- o2::framework::HistPtr fMissedMatches; o2::framework::HistPtr fMissedMatchesGoodMCH; @@ -717,10 +774,10 @@ struct QaMatching { o2::framework::HistPtr fTrueMatchChi2VsProd; //- - EfficiencyPlotter fMatchingPurityPlotter; - EfficiencyPlotter fPairingEfficiencyPlotter; - EfficiencyPlotter fMatchingEfficiencyPlotter; - EfficiencyPlotter fFakeMatchingEfficiencyPlotter; + std::unique_ptr fMatchingPurityPlotter; + std::unique_ptr fPairingEfficiencyPlotter; + std::unique_ptr fMatchingEfficiencyPlotter; + std::unique_ptr fFakeMatchingEfficiencyPlotter; HistogramRegistry* registry; @@ -728,191 +785,129 @@ struct QaMatching { HistogramRegistry* reg, bool createPdgMomHistograms, int mftMultMax, - int numCandidates) - : fMatchingPurityPlotter(path + "matching-purity/", "Matching purity", *reg, createPdgMomHistograms), - fPairingEfficiencyPlotter(path + "pairing-efficiency/", "Pairing efficiency", *reg, createPdgMomHistograms), - fMatchingEfficiencyPlotter(path + "matching-efficiency/", "Matching efficiency", *reg, createPdgMomHistograms), - fFakeMatchingEfficiencyPlotter(path + "fake-matching-efficiency/", "Fake matching efficiency", *reg, createPdgMomHistograms) + int numCandidates, + bool isMc) { registry = reg; AxisSpec pAxis = {100, 0, 100, "p (GeV/c)"}; AxisSpec ptAxis = {100, 0, 10, "p_{T} (GeV/c)"}; AxisSpec dzAxis = {100, 0, 50, "#Deltaz (cm)"}; AxisSpec indexAxis = {6, 0, 6, "ranking index"}; - - std::string histName = path + "matchRanking"; - std::string histTitle = "True match ranking"; - - fMatchRanking = std::make_unique(path + "matchRanking", "True match ranking", registry, mftMultMax, numCandidates); - fMatchRankingGoodMCH = std::make_unique(path + "matchRankingGoodMCH", "True match ranking (good MCH tracks)", registry, mftMultMax, numCandidates); - fMatchRankingPaired = std::make_unique(path + "matchRankingPaired", "True match ranking (paired MCH tracks)", registry, mftMultMax, numCandidates); - fMatchRankingPairedGoodMCH = std::make_unique(path + "matchRankingPairedGoodMCH", "True match ranking (good paired MCH tracks)", registry, mftMultMax, numCandidates); - - //- - AxisSpec missedMatchAxis = {5, 0, 5, ""}; - histName = path + "missedMatches"; - histTitle = "Missed matches"; - fMissedMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {missedMatchAxis}}); - std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(1, "not paired"); - std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(2, "fake MCH"); - std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(3, "not stored"); - histName = path + "missedMatchesGoodMCH"; - histTitle = "Missed matches - good MCH tracks"; - fMissedMatchesGoodMCH = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {missedMatchAxis}}); - std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(1, "not paired"); - std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(2, "fake MCH"); - std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(3, "not stored"); - - AxisSpec decayRankingAxis = {5, 0, 5, "decay ranking"}; - histName = path + "decayRankingGoodMatches"; - histTitle = "Decay ranking - good matches"; - fDecayRankingGoodMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); - histName = path + "decayRankingNonLeadingMatches"; - histTitle = "Decay ranking - non-leading matches"; - fDecayRankingNonLeadingMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); - histName = path + "decayRankingMissedMatches"; - histTitle = "Decay ranking - missed matches"; - fDecayRankingMissedMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); - - AxisSpec scoreGapAxis = {100, 0, 1, "match score difference"}; - histName = path + "scoreGapLeadingTrueMatches"; - histTitle = "Score gap between leading and subleading matches - good matches"; - fScoreGapLeadingTrueMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {scoreGapAxis}}); - histName = path + "scoreGapNonLeadingTrueMatches"; - histTitle = "Score gap between leading and subleading matches - non-leading matches"; - fScoreGapNonLeadingTrueMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {scoreGapAxis}}); - - //- AxisSpec chi2Axis = {100, 0, 100, "matching #chi^{2}/NDF"}; AxisSpec scoreAxis = {100, 0, 1, "matching score"}; - int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; - AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), ""}; - histName = path + "matchType"; - histTitle = "Match type"; - fMatchType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {matchTypeAxis}}); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchType)->GetXaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchTypeVsP"; - histTitle = "Match type vs. p"; - fMatchTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pAxis, matchTypeAxis}}); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchTypeVsP)->GetYaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchTypeVsPt"; - histTitle = "Match type vs. p_{T}"; - fMatchTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {ptAxis, matchTypeAxis}}); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchTypeVsPt)->GetYaxis()->SetBinLabel(9, "undefined"); - - histName = path + "matchChi2VsType"; - histTitle = "Match #chi^{2} vs. match type"; - fMatchChi2VsType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {matchTypeAxis, chi2Axis}}); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchChi2VsType)->GetXaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchChi2VsTypeVsP"; - histTitle = "Match #chi^{2} vs. match type vs. p"; - fMatchChi2VsTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {pAxis, matchTypeAxis, chi2Axis}}); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchChi2VsTypeVsP)->GetYaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchChi2VsTypeVsPt"; - histTitle = "Match #chi^{2} vs. match type vs. p_{T}"; - fMatchChi2VsTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {ptAxis, matchTypeAxis, chi2Axis}}); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()->SetBinLabel(9, "undefined"); - //- - histName = path + "matchScoreVsType"; - histTitle = "Match score vs. match type"; - fMatchScoreVsType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {matchTypeAxis, scoreAxis}}); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchScoreVsType)->GetXaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchScoreVsTypeVsP"; - histTitle = "Match score vs. match type vs. p"; - fMatchScoreVsTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {pAxis, matchTypeAxis, scoreAxis}}); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchScoreVsTypeVsP)->GetYaxis()->SetBinLabel(9, "undefined"); - histName = path + "matchScoreVsTypeVsPt"; - histTitle = "Match score vs. match type vs. p_{T}"; - fMatchScoreVsTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {ptAxis, matchTypeAxis, scoreAxis}}); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(1, "true (leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(2, "wrong (leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(3, "decay (leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(4, "fake (leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(5, "true (non leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(6, "wrong (non leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(7, "decay (non leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(8, "fake (non leading)"); - std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()->SetBinLabel(9, "undefined"); + + std::string histName; + std::string histTitle; + + fMatchFeaturesGoodMCH = std::make_unique(path + "matchFeaturesGoodMCH", registry, numCandidates); + + if (isMc) { + fMatchRanking = std::make_unique(path + "matchRanking", "True match ranking", registry, mftMultMax, numCandidates); + fMatchRankingGoodMCH = std::make_unique(path + "matchRankingGoodMCH", "True match ranking (good MCH tracks)", registry, mftMultMax, numCandidates); + fMatchRankingPaired = std::make_unique(path + "matchRankingPaired", "True match ranking (paired MCH tracks)", registry, mftMultMax, numCandidates); + fMatchRankingPairedGoodMCH = std::make_unique(path + "matchRankingPairedGoodMCH", "True match ranking (good paired MCH tracks)", registry, mftMultMax, numCandidates); + + fMatchingPurityPlotter = std::make_unique(path + "matching-purity/", "Matching purity", *reg, createPdgMomHistograms); + fPairingEfficiencyPlotter = std::make_unique(path + "pairing-efficiency/", "Pairing efficiency", *reg, createPdgMomHistograms); + fMatchingEfficiencyPlotter = std::make_unique(path + "matching-efficiency/", "Matching efficiency", *reg, createPdgMomHistograms); + fFakeMatchingEfficiencyPlotter = std::make_unique(path + "fake-matching-efficiency/", "Fake matching efficiency", *reg, createPdgMomHistograms); + + //- + AxisSpec missedMatchAxis = {5, 0, 5, ""}; + histName = path + "missedMatches"; + histTitle = "Missed matches"; + fMissedMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {missedMatchAxis}}); + std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(1, "not paired"); + std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(2, "fake MCH"); + std::get>(fMissedMatches)->GetXaxis()->SetBinLabel(3, "not stored"); + histName = path + "missedMatchesGoodMCH"; + histTitle = "Missed matches - good MCH tracks"; + fMissedMatchesGoodMCH = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {missedMatchAxis}}); + std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(1, "not paired"); + std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(2, "fake MCH"); + std::get>(fMissedMatchesGoodMCH)->GetXaxis()->SetBinLabel(3, "not stored"); + + AxisSpec decayRankingAxis = {5, 0, 5, "decay ranking"}; + histName = path + "decayRankingGoodMatches"; + histTitle = "Decay ranking - good matches"; + fDecayRankingGoodMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); + histName = path + "decayRankingNonLeadingMatches"; + histTitle = "Decay ranking - non-leading matches"; + fDecayRankingNonLeadingMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); + histName = path + "decayRankingMissedMatches"; + histTitle = "Decay ranking - missed matches"; + fDecayRankingMissedMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {decayRankingAxis}}); + + AxisSpec scoreGapAxis = {100, 0, 1, "match score difference"}; + histName = path + "scoreGapLeadingTrueMatches"; + histTitle = "Score gap between leading and subleading matches - good matches"; + fScoreGapLeadingTrueMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {scoreGapAxis}}); + histName = path + "scoreGapNonLeadingTrueMatches"; + histTitle = "Score gap between leading and subleading matches - non-leading matches"; + fScoreGapNonLeadingTrueMatches = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {scoreGapAxis}}); + + //- + int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; + AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), ""}; + histName = path + "matchType"; + histTitle = "Match type"; + fMatchType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {matchTypeAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchType)->GetXaxis()); + histName = path + "matchTypeVsP"; + histTitle = "Match type vs. p"; + fMatchTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pAxis, matchTypeAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchTypeVsP)->GetYaxis()); + histName = path + "matchTypeVsPt"; + histTitle = "Match type vs. p_{T}"; + fMatchTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {ptAxis, matchTypeAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchTypeVsPt)->GetYaxis()); + + histName = path + "matchChi2VsType"; + histTitle = "Match #chi^{2} vs. match type"; + fMatchChi2VsType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {matchTypeAxis, chi2Axis}}); + setMatchTypeAxisLabels(std::get>(fMatchChi2VsType)->GetXaxis()); + histName = path + "matchChi2VsTypeVsP"; + histTitle = "Match #chi^{2} vs. match type vs. p"; + fMatchChi2VsTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {pAxis, matchTypeAxis, chi2Axis}}); + setMatchTypeAxisLabels(std::get>(fMatchChi2VsTypeVsP)->GetYaxis()); + histName = path + "matchChi2VsTypeVsPt"; + histTitle = "Match #chi^{2} vs. match type vs. p_{T}"; + fMatchChi2VsTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {ptAxis, matchTypeAxis, chi2Axis}}); + setMatchTypeAxisLabels(std::get>(fMatchChi2VsTypeVsPt)->GetYaxis()); + //- + histName = path + "matchScoreVsType"; + histTitle = "Match score vs. match type"; + fMatchScoreVsType = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {matchTypeAxis, scoreAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchScoreVsType)->GetXaxis()); + histName = path + "matchScoreVsTypeVsP"; + histTitle = "Match score vs. match type vs. p"; + fMatchScoreVsTypeVsP = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {pAxis, matchTypeAxis, scoreAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchScoreVsTypeVsP)->GetYaxis()); + histName = path + "matchScoreVsTypeVsPt"; + histTitle = "Match score vs. match type vs. p_{T}"; + fMatchScoreVsTypeVsPt = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH3F, {ptAxis, matchTypeAxis, scoreAxis}}); + setMatchTypeAxisLabels(std::get>(fMatchScoreVsTypeVsPt)->GetYaxis()); + } AxisSpec prodScoreAxis = {100, 0, 1, "matching score (prod)"}; histName = path + "matchScoreVsProd"; histTitle = "Match score vs. production"; fMatchScoreVsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {prodScoreAxis, scoreAxis}}); - histName = path + "trueMatchScoreVsProd"; - histTitle = "Match score vs. production - true match"; - fTrueMatchScoreVsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {prodScoreAxis, scoreAxis}}); + if (isMc) { + histName = path + "trueMatchScoreVsProd"; + histTitle = "Match score vs. production - true match"; + fTrueMatchScoreVsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {prodScoreAxis, scoreAxis}}); + } AxisSpec prodChi2Axis = {100, 0, 100, "matching #chi^{2}/NDF (prod)"}; histName = path + "matchChi2VsProd"; histTitle = "Match #chi^{2} vs. production"; fMatchChi2VsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {prodChi2Axis, chi2Axis}}); - histName = path + "trueMatchChi2VsProd"; - histTitle = "Match #chi^{2} vs. production - true match"; - fTrueMatchChi2VsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {{100, 0, 10, "matching #chi^{2} (prod)"}, {100, 0, 10, "matching #chi^{2}"}}}); + if (isMc) { + histName = path + "trueMatchChi2VsProd"; + histTitle = "Match #chi^{2} vs. production - true match"; + fTrueMatchChi2VsProd = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {{100, 0, 10, "matching #chi^{2} (prod)"}, {100, 0, 10, "matching #chi^{2}"}}}); + } } }; std::unique_ptr fChi2MatchingPlotter; @@ -948,7 +943,7 @@ struct QaMatching { } } - void createMatchingHistosMc() + void createMatchingHistos() { AxisSpec chi2Axis = {1000, 0, 1000, "chi^{2}"}; AxisSpec chi2AxisSmall = {200, 0, 100, "chi^{2}"}; @@ -956,7 +951,7 @@ struct QaMatching { AxisSpec pTAxis = {100, 0, 10, "p_{T} (GeV/c)"}; AxisSpec etaAxis = {100, -4, -2, "#eta"}; AxisSpec phiAxis = {90, -180, 180, "#phi (degrees)"}; - std::string histPath = "matching/MC/"; + std::string histPath = cfgIsMc.value ? "matching/MC/" : "matching/"; AxisSpec trackPositionXAtMftAxis = {100, -15, 15, "MFT x (cm)"}; AxisSpec trackPositionYAtMftAxis = {100, -15, 15, "MFT y (cm)"}; @@ -966,18 +961,18 @@ struct QaMatching { registry.add((histPath + "selectedMCHTracksAtMFTTrue").c_str(), "Selected MCH tracks position at MFT end - true", {HistType::kTH2F, {trackPositionXAtMftAxis, trackPositionYAtMftAxis}}); registry.add((histPath + "selectedMCHTracksAtMFTFake").c_str(), "Selected MCH tracks position at MFT end - fake", {HistType::kTH2F, {trackPositionXAtMftAxis, trackPositionYAtMftAxis}}); - fChi2MatchingPlotter = std::make_unique(histPath + "Prod/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); + fChi2MatchingPlotter = std::make_unique(histPath + "Prod/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax, cfgIsMc.value); int registryIndex = 0; for (const auto& [label, func] : matchingChi2Functions) { - fMatchingPlotters[label] = std::make_unique(histPath + label + "/", registryMatchingVec[registryIndex], configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); + fMatchingPlotters[label] = std::make_unique(histPath + label + "/", registryMatchingVec[registryIndex], configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax, cfgIsMc.value); registryIndex += 1; } for (const auto& [label, response] : matchingMlResponses) { - fMatchingPlotters[label] = std::make_unique(histPath + label + "/", (registryMatchingVec[registryIndex]), configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); + fMatchingPlotters[label] = std::make_unique(histPath + label + "/", (registryMatchingVec[registryIndex]), configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax, cfgIsMc.value); registryIndex += 1; } - fTaggedMuonsMatchingPlotter = std::make_unique(histPath + "Tagged/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax); + fTaggedMuonsMatchingPlotter = std::make_unique(histPath + "Tagged/", ®istryMatching, configQas.cfgCreatePdgMomHistograms, cfgMftTrackMultiplicityMax, cfgNCandidatesMax, cfgIsMc.value); } void createDimuonHistos() @@ -1203,7 +1198,7 @@ struct QaMatching { std::get>(matchMethodsHist)->GetXaxis()->SetBinLabel(iLabel + 1, matchMethodLabels[iLabel].c_str()); } - createMatchingHistosMc(); + createMatchingHistos(); createDimuonHistos(); } @@ -1973,11 +1968,12 @@ struct QaMatching { return attempts; } - template + template void fillCollisions(EVT const& collisions, BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, + MyMFTCovariances const& mftCovs, CollisionInfos& collisionInfos) { collisionInfos.clear(); @@ -2009,8 +2005,10 @@ struct QaMatching { collisionInfo.bc = bc.globalBC(); collisionInfo.zVertex = collision.posZ(); - if (collisionInfo.matchablePairs.empty()) { - fillMatchablePairs(collisionInfo, muonTracks, mftTracks); + if constexpr (isMC) { + if (collisionInfo.matchablePairs.empty()) { + fillMatchablePairs(collisionInfo, muonTracks, mftTracks); + } } if (static_cast(muonTrack.trackType()) > GlobalTrackTypeMax) { @@ -2027,6 +2025,18 @@ struct QaMatching { auto const& mftTrack = muonTrack.template matchMFTTrack_as(); int64_t mftTrackIndex = mftTrack.globalIndex(); + // get MFT track covariances + if (mftTrackCovs.count(mftTrack.globalIndex()) < 1) { + continue; + } + auto const& mftTrackCov = mftCovs.rawIteratorAt(mftTrackCovs[mftTrack.globalIndex()]); + + // propagate MCH and MFT tracks to matching plane + auto mchTrackProp = fwdToTrackPar(mchTrack, mchTrack); + mchTrackProp = propagateToMatchingPlaneMch(mchTrack, mftTrack, mftTrackCov, collision, MatchingPlaneDefaultZ, 0); + auto mftTrackProp = fwdToTrackPar(mftTrack, mftTrackCov); + mftTrackProp = propagateToMatchingPlaneMft(mchTrack, mftTrack, mftTrackCov, collision, MatchingPlaneDefaultZ, 0); + // check if a vector of global muon candidates is already available for the current MCH index // if not, initialize a new one and add the current global muon track // bool globalMuonTrackFound = false; @@ -2037,6 +2047,8 @@ struct QaMatching { muonTrackIndex, mchTrackIndex, mftTrackIndex, + mftTrackProp, + mchTrackProp, matchScore, matchChi2, -1, @@ -2051,6 +2063,8 @@ struct QaMatching { muonTrackIndex, mchTrackIndex, mftTrackIndex, + mftTrackProp, + mchTrackProp, matchScore, matchChi2, -1, @@ -2104,7 +2118,11 @@ struct QaMatching { candidate.matchRanking = ranking; candidate.matchRankingProd = ranking; - candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, collisionInfo.matchablePairs, ranking); + if constexpr (isMC) { + candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, collisionInfo.matchablePairs, ranking); + } else { + candidate.matchType = kMatchTypeUndefined; + } candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } @@ -2112,6 +2130,67 @@ struct QaMatching { } } + template + void fillMatchingPlots(C const& collision, + TMUON const& muonTracks, + const MatchingCandidates& matchingCandidates, + MatchingPlotter* plotter) + { + // ==================================== + // Matching properties + for (const auto& [mchIndex, globalTracksVector] : matchingCandidates) { + if (globalTracksVector.size() < 1) + continue; + + // get the standalone MCH track + auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); + + // skip global muon tracks that do not pass the MCH and MFT quality cuts + if (!isGoodGlobalMuon(mchTrack, collision)) + continue; + + for (const auto& candidate : globalTracksVector) { + double dp = candidate.mchTrackProp.getP() - candidate.mftTrackProp.getP(); + double dpt = candidate.mchTrackProp.getPt() - candidate.mftTrackProp.getPt(); + double dx = candidate.mchTrackProp.getX() - candidate.mftTrackProp.getX(); + double dy = candidate.mchTrackProp.getY() - candidate.mftTrackProp.getY(); + double dphi = candidate.mchTrackProp.getPhi() - candidate.mftTrackProp.getPhi(); + double dtanl = candidate.mchTrackProp.getTanl() - candidate.mftTrackProp.getTanl(); + double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); + int matchType = static_cast(candidate.matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), candidate.matchScore, candidate.matchRanking, matchType); + } + } + + // ==================================== + // Matching chi2 and score vs. production values + for (const auto& [mchIndex, globalTracksVector] : matchingCandidates) { + if (globalTracksVector.size() < 1) + continue; + + // loop over candidates + for (const auto& candidate : globalTracksVector) { + auto const& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); + + float matchScore = candidate.matchScore; + float matchChi2 = candidate.matchChi2; + + float matchChi2Prod = muonTrack.chi2MatchMCHMFT() / 5.f; + float matchScoreProd = chi2ToScore(muonTrack.chi2MatchMCHMFT(), 5, 50.f); + + std::get>(plotter->fMatchScoreVsProd)->Fill(matchScoreProd, matchScore); + std::get>(plotter->fMatchChi2VsProd)->Fill(matchChi2Prod, matchChi2); + } + } + } + template void fillMatchingPlotsMc(C const& collision, const CollisionInfo& collisionInfo, @@ -2216,6 +2295,27 @@ struct QaMatching { std::get>(plotter->fMatchRankingPairedGoodMCH->histVsDeltaChi2)->Fill(dchi2, trueMatchIndex); } + if (isGoodMCH) { + for (const auto& candidate : globalTracksVector) { + double dp = candidate.mchTrackProp.getP() - candidate.mftTrackProp.getP(); + double dpt = candidate.mchTrackProp.getPt() - candidate.mftTrackProp.getPt(); + double dx = candidate.mchTrackProp.getX() - candidate.mftTrackProp.getX(); + double dy = candidate.mchTrackProp.getY() - candidate.mftTrackProp.getY(); + double dphi = candidate.mchTrackProp.getPhi() - candidate.mftTrackProp.getPhi(); + double dtanl = candidate.mchTrackProp.getTanl() - candidate.mftTrackProp.getTanl(); + double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); + int matchType = static_cast(candidate.matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, candidate.matchScore, candidate.matchRanking, matchType); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), candidate.matchScore, candidate.matchRanking, matchType); + } + } + if (trueMatchIndex == 0) { // missed matches if (!isPairedMCH) { @@ -2341,13 +2441,10 @@ struct QaMatching { // get the standalone MCH and MFT tracks auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); - auto const& mftTrack = muonTrack.template matchMFTTrack_as(); // skip global muon tracks that do not pass the MCH and MFT quality cuts if (!isGoodGlobalMuon(mchTrack, collision)) continue; - if (!isGoodMft(mftTrack)) - continue; // skip candidates that do not pass the matching quality cuts if (!isGoodGlobalMatching(muonTrack, matchingScore, matchingScoreCut)) @@ -2363,9 +2460,9 @@ struct QaMatching { motherPDG = motherParticles[1].first; } // fill matching purity plots - plotter->fMatchingPurityPlotter.fill(mchTrack, isTrueMatch); + plotter->fMatchingPurityPlotter->fill(mchTrack, isTrueMatch); if (configQas.cfgCreatePdgMomHistograms) { - plotter->fMatchingPurityPlotter.fill(mchTrack, motherPDG, isTrueMatch); + plotter->fMatchingPurityPlotter->fill(mchTrack, motherPDG, isTrueMatch); } } @@ -2421,17 +2518,17 @@ struct QaMatching { } // fill matching efficiency plots - plotter->fPairingEfficiencyPlotter.fill(mchTrack, goodMatchFound); + plotter->fPairingEfficiencyPlotter->fill(mchTrack, goodMatchFound); if (configQas.cfgCreatePdgMomHistograms) { - plotter->fPairingEfficiencyPlotter.fill(mchTrack, motherPDG, goodMatchFound); + plotter->fPairingEfficiencyPlotter->fill(mchTrack, motherPDG, goodMatchFound); } - plotter->fMatchingEfficiencyPlotter.fill(mchTrack, (goodMatchFound && isTrueMatch)); + plotter->fMatchingEfficiencyPlotter->fill(mchTrack, (goodMatchFound && isTrueMatch)); if (configQas.cfgCreatePdgMomHistograms) { - plotter->fMatchingEfficiencyPlotter.fill(mchTrack, motherPDG, (goodMatchFound && isTrueMatch)); + plotter->fMatchingEfficiencyPlotter->fill(mchTrack, motherPDG, (goodMatchFound && isTrueMatch)); } - plotter->fFakeMatchingEfficiencyPlotter.fill(mchTrack, (goodMatchFound && !isTrueMatch)); + plotter->fFakeMatchingEfficiencyPlotter->fill(mchTrack, (goodMatchFound && !isTrueMatch)); if (configQas.cfgCreatePdgMomHistograms) { - plotter->fFakeMatchingEfficiencyPlotter.fill(mchTrack, motherPDG, (goodMatchFound && !isTrueMatch)); + plotter->fFakeMatchingEfficiencyPlotter->fill(mchTrack, motherPDG, (goodMatchFound && !isTrueMatch)); } } } @@ -2523,7 +2620,7 @@ struct QaMatching { } } - template + template void runChi2Matching(C const& collisions, BC const& bcs, TMUON const& muonTracks, @@ -2548,6 +2645,7 @@ struct QaMatching { auto matchingFunc = mMatchingFunctionMap.at(funcName); for (const auto& [mchIndex, globalTracksVector] : matchingCandidates) { + // get the MCH standalone track auto const& mchTrack = muonTracks.rawIteratorAt(mchIndex); for (const auto& candidate : globalTracksVector) { @@ -2557,11 +2655,9 @@ struct QaMatching { auto collision = collisions.rawIteratorAt(muonTrack.collisionId()); - // get MCH and MFT standalone tracks - // auto mchTrack = muonTrack.template matchMCHTrack_as(); + // get the MFT standalone track auto const& mftTrack = muonTrack.template matchMFTTrack_as(); if (mftTrackCovs.count(mftTrack.globalIndex()) < 1) { - // std::cout << std::format("Covariance matrix for MFT track #{} not found", mftTrack.globalIndex()) << std::endl; continue; } auto const& mftTrackCov = mftCovs.rawIteratorAt(mftTrackCovs[mftTrack.globalIndex()]); @@ -2591,6 +2687,8 @@ struct QaMatching { candidate.globalTrackId, mchIndex, mftTrack.globalIndex(), + mftTrackProp, + mchTrackProp, matchScore, matchChi2, -1, @@ -2604,6 +2702,8 @@ struct QaMatching { candidate.globalTrackId, mchIndex, mftTrack.globalIndex(), + mftTrackProp, + mchTrackProp, matchScore, matchChi2, -1, @@ -2630,14 +2730,18 @@ struct QaMatching { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; - candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + if constexpr (isMC) { + candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + } else { + candidate.matchType = kMatchTypeUndefined; + } candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } } - template + template void runChi2Matching(C const& collisions, BC const& bcs, TMUON const& muonTracks, @@ -2668,10 +2772,10 @@ struct QaMatching { auto matchingPlaneZ = matchingPlanesZ[label]; auto extrapMethod = matchingExtrapMethod[label]; - runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchablePairs, matchingCandidates, newMatchingCandidates); + runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchablePairs, matchingCandidates, newMatchingCandidates); } - template + template void runMlMatching(C const& collisions, BC const& bcs, TMUON const& muonTracks, @@ -2700,12 +2804,9 @@ struct QaMatching { // get MFT standalone track auto const& mftTrack = muonTrack.template matchMFTTrack_as(); if (mftTrackCovs.count(mftTrack.globalIndex()) < 1) { - // std::cout << std::format("Covariance matrix for MFT track #{} not found", mftTrack.globalIndex()) << std::endl; continue; } - // std::cout << fmt::format("Getting covariance matrix for MFT track #{} -> {}", mftTrack.globalIndex(), mftTrackCovs[mftTrack.globalIndex()]) << std::endl; auto const& mftTrackCov = mftCovs.rawIteratorAt(mftTrackCovs[mftTrack.globalIndex()]); - // std::cout << fmt::format("Covariance matrix for MFT track #{} retrieved", mftTrack.globalIndex()) << std::endl; // get tracks parameters in O2 format auto mftTrackProp = fwdToTrackPar(mftTrack, mftTrackCov); @@ -2725,7 +2826,6 @@ struct QaMatching { float matchScore = output[0]; float matchChi2Prod = muonTrack.chi2MatchMCHMFT() / MatchingDegreesOfFreedom; float matchScoreProd = chi2ToScore(muonTrack.chi2MatchMCHMFT(), MatchingDegreesOfFreedom, MatchingScoreChi2Max); - // std::cout << std::format("Matching score: {}, Chi2: {}", matchingScore, muonTrack.chi2MatchMCHMFT()) << std::endl; // check if a vector of global muon candidates is already available for the current MCH index // if not, initialize a new one and add the current global muon track @@ -2736,6 +2836,8 @@ struct QaMatching { candidate.globalTrackId, mchIndex, mftTrack.globalIndex(), + mftTrackProp, + mchTrackProp, matchScore, -1, -1, @@ -2749,6 +2851,8 @@ struct QaMatching { candidate.globalTrackId, mchIndex, mftTrack.globalIndex(), + mftTrackProp, + mchTrackProp, matchScore, -1, -1, @@ -2775,20 +2879,24 @@ struct QaMatching { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; - candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + if constexpr (isMC) { + candidate.matchType = getMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + } else { + candidate.matchType = kMatchTypeUndefined; + } candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } } - template - void processCollisionMc(const CollisionInfo& collisionInfo, - C const& collisions, - BC const& bcs, - TMUON const& muonTracks, - TMFT const& mftTracks, - CMFT const& mftCovs) + template + void processCollision(const CollisionInfo& collisionInfo, + C const& collisions, + BC const& bcs, + TMUON const& muonTracks, + TMFT const& mftTracks, + CMFT const& mftCovs) { auto collision = collisions.rawIteratorAt(collisionInfo.index); @@ -2807,7 +2915,11 @@ struct QaMatching { //------------------------------- // Chi2-based matching from production fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); + if constexpr (isMC) { + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); + } else { + fillMatchingPlots(collision, muonTracks, collisionInfo.matchingCandidates, fChi2MatchingPlotter.get()); + } //------------------------------- // Tagged muons @@ -2840,35 +2952,46 @@ struct QaMatching { taggedMatchingCandidates[mchIndex] = globalTracksVector; } } - matchingMethodCounter += 1; - fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fTaggedMuonsMatchingPlotter.get()); + if constexpr (isMC) { + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fTaggedMuonsMatchingPlotter.get()); + } else { + fillMatchingPlots(collision, muonTracks, taggedMatchingCandidates, fTaggedMuonsMatchingPlotter.get()); + } //------------------------------- // Custom chi2-based matching methods for (const auto& [label, func] : matchingChi2Functions) { MatchingCandidates matchingCandidates; - runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + runChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); + if constexpr (isMC) { + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); + } else { + fillMatchingPlots(collision, muonTracks, matchingCandidates, plotter); + } } - // ML-based matching analysis + //------------------------------- + // Custom ML-based matching methods for (const auto& [label, mlResponse] : matchingMlResponses) { MatchingCandidates matchingCandidates; - runMlMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + runMlMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); + if constexpr (isMC) { + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); + } else { + fillMatchingPlots(collision, muonTracks, matchingCandidates, plotter); + } } //------------------------------- @@ -2905,6 +3028,7 @@ struct QaMatching { static_cast(candidateTrack.eta()), static_cast(candidateTrack.phi()), static_cast(candidate.matchType), + static_cast(candidate.matchChi2), static_cast(candidate.matchScore), static_cast(candidate.matchRanking), static_cast(candidateTrackAtVertex.getX()), @@ -3005,14 +3129,41 @@ struct QaMatching { mftTrackCovs[mftTrackCov.matchMFTTrackId()] = mftTrackCov.globalIndex(); } - fillCollisions(collisions, bcs, muonTracks, mftTracks, fCollisionInfos); + fillCollisions(collisions, bcs, muonTracks, mftTracks, mftCovs, fCollisionInfos); for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - processCollisionMc(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); + processCollision(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); } } PROCESS_SWITCH(QaMatching, processQAMC, "processQAMC", true); + + void processQA(MyEvents const& collisions, + aod::BCsWithTimestamps const& bcs, + MyMuons const& muonTracks, + MyMFTs const& mftTracks, + MyMFTCovariances const& mftCovs) + { + auto bc = bcs.begin(); + initCcdb(bc); + + for (const auto& muon : muonTracks) { + registry.get(HIST("nTracksPerType"))->Fill(static_cast(muon.trackType())); + } + + mftTrackCovs.clear(); + for (const auto& mftTrackCov : mftCovs) { + mftTrackCovs[mftTrackCov.matchMFTTrackId()] = mftTrackCov.globalIndex(); + } + + fillCollisions(collisions, bcs, muonTracks, mftTracks, mftCovs, fCollisionInfos); + + for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { + processCollision(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); + } + } + + PROCESS_SWITCH(QaMatching, processQA, "processQA", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 1c221cb6bd6635e6d695064232785f2ac5d13660 Mon Sep 17 00:00:00 2001 From: Andreas Molander Date: Tue, 26 May 2026 14:41:05 +0300 Subject: [PATCH 285/449] [DPG] FIT: Add table for FIT standalone derived data (AFIT-138) (#16144) --- DPG/Tasks/CMakeLists.txt | 1 + DPG/Tasks/FIT/CMakeLists.txt | 15 ++ DPG/Tasks/FIT/fitAll.cxx | 479 +++++++++++++++++++++++++++++++++++ 3 files changed, 495 insertions(+) create mode 100644 DPG/Tasks/FIT/CMakeLists.txt create mode 100644 DPG/Tasks/FIT/fitAll.cxx diff --git a/DPG/Tasks/CMakeLists.txt b/DPG/Tasks/CMakeLists.txt index 642f8d6e772..8f58550868f 100644 --- a/DPG/Tasks/CMakeLists.txt +++ b/DPG/Tasks/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(AOTTrack) add_subdirectory(AOTEvent) add_subdirectory(TPC) add_subdirectory(TOF) +add_subdirectory(FIT) add_subdirectory(FV0) add_subdirectory(FDD) add_subdirectory(MFT) diff --git a/DPG/Tasks/FIT/CMakeLists.txt b/DPG/Tasks/FIT/CMakeLists.txt new file mode 100644 index 00000000000..db76da4e4aa --- /dev/null +++ b/DPG/Tasks/FIT/CMakeLists.txt @@ -0,0 +1,15 @@ +# 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. + +o2physics_add_dpl_workflow(fit-all + SOURCES fitAll.cxx + PUBLIC_LINK_LIBRARIES O2Physics::DataModel O2::Framework O2::FV0Base O2::FDDBase + COMPONENT_NAME Analysis) diff --git a/DPG/Tasks/FIT/fitAll.cxx b/DPG/Tasks/FIT/fitAll.cxx new file mode 100644 index 00000000000..63b6c630230 --- /dev/null +++ b/DPG/Tasks/FIT/fitAll.cxx @@ -0,0 +1,479 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file fitAll.cxx +/// \brief FITAll table definition and producer. Standalone derived data used for FIT studies. +/// +/// \author Andreas Molander andreas.molander@cern.ch + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using BCsWithTimestamps = soa::Join; + +namespace o2::aod +{ +namespace fit +{ + +// Constants +static constexpr int NchFt0 = 208; ///< Number of FT0 channels +static constexpr int NchFt0A = 96; ///< Number of FT0A channels +static constexpr int NchFv0 = o2::fv0::Constants::nFv0Channels; ///< Number of FV0 channels +static constexpr int NchFdd = o2::fdd::Nchannels; ///< Number of FDD channels + +// BCs +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(GlobalBc, globalBc, uint64_t); +DECLARE_SOA_COLUMN(CtpTriggerMask, ctpTriggerMask, uint64_t); +DECLARE_SOA_COLUMN(CtpInputMask, ctpInputMask, uint64_t); + +// Timestamps +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); + +// EvSels +DECLARE_SOA_BITMAP_COLUMN(TriggerAlias, triggerAlias, 32); +DECLARE_SOA_BITMAP_COLUMN(SelectionFlags, selectionFlags, 64); +DECLARE_SOA_BITMAP_COLUMN(RctFlags, rctFlags, 32); +DECLARE_SOA_COLUMN(Sel8, sel8, bool); +DECLARE_SOA_COLUMN(HasFt0, hasFt0, bool); +DECLARE_SOA_COLUMN(HasFv0, hasFv0, bool); +DECLARE_SOA_COLUMN(HasFdd, hasFdd, bool); +DECLARE_SOA_COLUMN(HasZdc, hasZdc, bool); + +// Collisions +DECLARE_SOA_COLUMN(BcId, bcId, int32_t); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); +DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(Flags, flags, uint16_t); +DECLARE_SOA_COLUMN(NumContrib, numContrib, uint16_t); +DECLARE_SOA_COLUMN(CollisionTime, collisionTime, float); +DECLARE_SOA_COLUMN(CollisionTimeRes, collisionTimeRes, float); + +// Mults +DECLARE_SOA_COLUMN(MultFt0A, multFt0A, float); +DECLARE_SOA_COLUMN(MultFt0C, multFt0C, float); +DECLARE_SOA_COLUMN(MultFv0A, multFv0A, float); +DECLARE_SOA_COLUMN(MultFddA, multFddA, float); +DECLARE_SOA_COLUMN(MultFddC, multFddC, float); +DECLARE_SOA_COLUMN(MultZnA, multZnA, float); +DECLARE_SOA_COLUMN(MultZnC, multZnC, float); +DECLARE_SOA_COLUMN(MultZem1, multZem1, float); +DECLARE_SOA_COLUMN(MultZem2, multZem2, float); +DECLARE_SOA_COLUMN(MultZpA, multZpA, float); +DECLARE_SOA_COLUMN(MultZpC, multZpC, float); + +// FT0s +DECLARE_SOA_COLUMN(Ft0BcId, ft0BcId, int32_t); +DECLARE_SOA_COLUMN(Ft0AmplitudeA, ft0AmplitudeA, std::vector); +DECLARE_SOA_COLUMN(Ft0ChannelA, ft0ChannelA, std::vector); +DECLARE_SOA_COLUMN(Ft0AmplitudeC, ft0AmplitudeC, std::vector); +DECLARE_SOA_COLUMN(Ft0ChannelC, ft0ChannelC, std::vector); +DECLARE_SOA_COLUMN(Ft0TimeA, ft0TimeA, float); +DECLARE_SOA_COLUMN(Ft0TimeC, ft0TimeC, float); +DECLARE_SOA_COLUMN(Ft0TriggerMask, ft0TriggerMask, uint8_t); +DECLARE_SOA_COLUMN(Ft0PosZ, ft0PosZ, float); +DECLARE_SOA_COLUMN(Ft0CollTime, ft0CollTime, float); +DECLARE_SOA_COLUMN(Ft0SumAmpA, ft0SumAmpA, float); +DECLARE_SOA_COLUMN(Ft0SumAmpC, ft0SumAmpC, float); + +// FT0sCorrected +DECLARE_SOA_COLUMN(T0aCorrected, t0aCorrected, float); +DECLARE_SOA_COLUMN(T0cCorrected, t0cCorrected, float); +DECLARE_SOA_COLUMN(T0ac, t0ac, float); +DECLARE_SOA_COLUMN(T0resolution, t0resolution, float); + +// FT0 derived quantities +DECLARE_SOA_COLUMN(Ft0ChAmpl, ft0ChAmpl, std::vector); ///< FT0 channel amplitudes, vector idx = ch ID +DECLARE_SOA_COLUMN(Ft0TotAmplA, ft0TotAmplA, float); ///< FT0-A total amplitude computed from channel amplitudes (for cross check) +DECLARE_SOA_COLUMN(Ft0TotAmplC, ft0TotAmplC, float); ///< FT0-C total amplitude computed from channel amplitudes (for cross check) + +// FV0As +DECLARE_SOA_COLUMN(Fv0BcId, fv0BcId, int32_t); +DECLARE_SOA_COLUMN(Fv0Amplitude, fv0Amplitude, std::vector); +DECLARE_SOA_COLUMN(Fv0Channel, fv0Channel, std::vector); +DECLARE_SOA_COLUMN(Fv0Time, fv0Time, float); +DECLARE_SOA_COLUMN(Fv0TriggerMask, fv0TriggerMask, uint8_t); + +// FV0 derived quantities +DECLARE_SOA_COLUMN(Fv0ChAmpl, fv0ChAmpl, std::vector); ///< FV0 channel amplitudes, vector idx = ch ID +DECLARE_SOA_COLUMN(Fv0TotAmpl, fv0TotAmpl, float); ///< FV0 total amplitude computed from channel amplitudes (for cross check) + +// FDDs +DECLARE_SOA_COLUMN(FddBcId, fddBcId, int32_t); +DECLARE_SOA_COLUMN(FddChargeA, fddChargeA, int16_t[8]); +DECLARE_SOA_COLUMN(FddChargeC, fddChargeC, int16_t[8]); +DECLARE_SOA_COLUMN(FddTimeA, fddTimeA, float); +DECLARE_SOA_COLUMN(FddTimeC, fddTimeC, float); +DECLARE_SOA_COLUMN(FddTriggerMask, fddTriggerMask, uint8_t); + +// FDD derived quantities +DECLARE_SOA_COLUMN(FddChAmpl, fddChAmpl, std::vector); ///< FDD channel amplitudes, vector idx = ch ID +DECLARE_SOA_COLUMN(FddTotAmplA, fddTotAmplA, float); ///< FDD-A total amplitude computed from channel amplitudes (for cross check) +DECLARE_SOA_COLUMN(FddTotAmplC, fddTotAmplC, float); ///< FDD-C total amplitude computed from channel amplitudes (for cross check) + +// ZDCs +DECLARE_SOA_COLUMN(EnergyCommonZnA, energyCommonZnA, float); +DECLARE_SOA_COLUMN(EnergyCommonZnC, energyCommonZnC, float); +DECLARE_SOA_COLUMN(TimeZem1, timeZem1, float); +DECLARE_SOA_COLUMN(TimeZem2, timeZem2, float); + +} // namespace fit + +DECLARE_SOA_TABLE(FITsAll, "AOD", "FITALL", ///< Standalone derived data used for FIT studies. + fit::RunNumber, fit::GlobalBc, fit::CtpTriggerMask, fit::CtpInputMask, + fit::Timestamp, + fit::TriggerAlias, fit::SelectionFlags, fit::RctFlags, fit::Sel8, fit::HasFt0, fit::HasFv0, fit::HasFdd, fit::HasZdc, + fit::BcId, fit::PosX, fit::PosY, fit::PosZ, fit::Flags, fit::NumContrib, fit::CollisionTime, fit::CollisionTimeRes, + fit::MultFt0A, fit::MultFt0C, fit::MultFv0A, fit::MultFddA, fit::MultFddC, fit::MultZnA, fit::MultZnC, fit::MultZem1, fit::MultZem2, fit::MultZpA, fit::MultZpC, + fit::Ft0BcId, fit::Ft0AmplitudeA, fit::Ft0ChannelA, fit::Ft0AmplitudeC, fit::Ft0ChannelC, + fit::Ft0TimeA, fit::Ft0TimeC, fit::Ft0TriggerMask, fit::Ft0PosZ, fit::Ft0CollTime, fit::Ft0SumAmpA, fit::Ft0SumAmpC, + fit::T0aCorrected, fit::T0cCorrected, fit::T0ac, fit::T0resolution, + fit::Ft0ChAmpl, fit::Ft0TotAmplA, fit::Ft0TotAmplC, + fit::Fv0BcId, fit::Fv0Amplitude, fit::Fv0Channel, fit::Fv0Time, fit::Fv0TriggerMask, + fit::Fv0ChAmpl, fit::Fv0TotAmpl, + fit::FddBcId, fit::FddChargeA, fit::FddChargeC, fit::FddTimeA, fit::FddTimeC, fit::FddTriggerMask, + fit::FddChAmpl, fit::FddTotAmplA, fit::FddTotAmplC, + fit::EnergyCommonZnA, fit::EnergyCommonZnC, fit::TimeZem1, fit::TimeZem2); + +using FITAll = FITsAll::iterator; + +} // namespace o2::aod + +struct FitAll { + // Producer + Produces table; + + void init(InitContext const&) + { + } + + void process(soa::Join const& collisions, + aod::BCsWithTimestamps const&, + aod::FT0s const&, aod::FV0As const&, aod::FDDs const&, aod::Zdcs const&) + { + table.reserve(collisions.size()); + + // BC + int runNumber = -1; + uint64_t globalBC = 0; + uint64_t ctpTriggerMask = 0; + uint64_t ctpInputMask = 0; + + // Timestamp + uint64_t timestamp = 0; + + // EvSel + uint32_t triggerAlias = 0; + uint64_t selectionFlags = 0; + uint32_t rctFlags = 0; + bool sel8 = false; + bool hasFT0 = false; + bool hasFV0 = false; + bool hasFDD = false; + bool hasZDC = false; + + // Collision + int32_t bcId = -1; + float posX = -200; + float posY = -200; + float posZ = -200; + uint16_t flags = 0; + uint16_t numContrib = 0; + float collisionTime = -200; + float collisionTimeRes = -200; + + // Mult + float multFT0A = 0; + float multFT0C = 0; + float multFV0A = 0; + float multFDDA = 0; + float multFDDC = 0; + float multZNA = 0; + float multZNC = 0; + float multZEM1 = 0; + float multZEM2 = 0; + float multZPA = 0; + float multZPC = 0; + + // FT0 + int32_t ft0BCId = -1; + std::vector ft0AmplitudeA; + std::vector ft0ChannelA; + std::vector ft0AmplitudeC; + std::vector ft0ChannelC; + float ft0TimeA = -200; + float ft0TimeC = -200; + uint8_t ft0TriggerMask = 0; + float ft0PosZ = -200; + float ft0CollTime = -200; + float ft0SumAmpA = 0; + float ft0SumAmpC = 0; + + // FT0Corrected + float t0ACorrected = -200; + float t0CCorrected = -200; + float t0AC = -200; + float t0resolution = -200; + + // FT0 derived quantities + std::vector ft0ChAmpl(o2::aod::fit::NchFt0, 0); + float ft0TotAmplA = 0; + float ft0TotAmplC = 0; + + // FV0A + int32_t fv0BCId = -1; + std::vector fv0Amplitude; + std::vector fv0Channel; + float fv0Time = -200; + uint8_t fv0TriggerMask = 0; + + // FV0 derived quantities + std::vector fv0ChAmpl(o2::aod::fit::NchFv0, 0); + float fv0TotAmpl = 0; + + // FDD + int32_t fddBCId = -1; + int16_t fddChargeA[8] = {0}; + int16_t fddChargeC[8] = {0}; + float fddTimeA = -200; + float fddTimeC = -200; + uint8_t fddTriggerMask = 0; + + // FDD derived quantities + std::vector fddChAmpl(o2::aod::fit::NchFdd, 0); + float fddTotAmplA = 0; + float fddTotAmplC = 0; + + // ZDC + float energyCommonZNA = -std::numeric_limits::infinity(); + float energyCommonZNC = -std::numeric_limits::infinity(); + float timeZEM1 = -std::numeric_limits::infinity(); + float timeZEM2 = -std::numeric_limits::infinity(); + + for (const auto& collision : collisions) { + auto bc = collision.bc_as(); + + // BC + runNumber = bc.runNumber(); + globalBC = bc.globalBC(); + ctpTriggerMask = bc.triggerMask(); + ctpInputMask = bc.inputMask(); + + // Timestamp + timestamp = bc.timestamp(); + + // EvSel + triggerAlias = collision.alias_raw(); + selectionFlags = collision.selection_raw(); + rctFlags = collision.rct_raw(); + sel8 = collision.sel8(); + hasFT0 = collision.has_foundFT0(); + hasFV0 = collision.has_foundFV0(); + hasFDD = collision.has_foundFDD(); + hasZDC = collision.has_foundZDC(); + + // Collision + bcId = collision.bcId(); + posX = collision.posX(); + posY = collision.posY(); + posZ = collision.posZ(); + flags = collision.flags(); + numContrib = collision.numContrib(); + collisionTime = collision.collisionTime(); + collisionTimeRes = collision.collisionTimeRes(); + + // Multiplicities + multFT0A = collision.multFT0A(); + multFT0C = collision.multFT0C(); + multFV0A = collision.multFV0A(); + multFDDA = collision.multFDDA(); + multFDDC = collision.multFDDC(); + multZNA = collision.multZNA(); + multZNC = collision.multZNC(); + multZEM1 = collision.multZEM1(); + multZEM2 = collision.multZEM2(); + multZPA = collision.multZPA(); + multZPC = collision.multZPC(); + + // FT0 + ft0BCId = -1; + ft0AmplitudeA.clear(); + ft0ChannelA.clear(); + ft0AmplitudeC.clear(); + ft0ChannelC.clear(); + ft0TimeA = -200; + ft0TimeC = -200; + ft0TriggerMask = 0; + ft0PosZ = -200; + ft0CollTime = -200; + ft0SumAmpA = 0; + ft0SumAmpC = 0; + + // FT0Corrected + t0ACorrected = collision.t0ACorrected(); + t0CCorrected = collision.t0CCorrected(); + t0AC = collision.t0AC(); + t0resolution = collision.t0resolution(); + + // FT0 derived quantities + ft0ChAmpl.assign(o2::aod::fit::NchFt0, 0); + ft0TotAmplA = 0; + ft0TotAmplC = 0; + + // FV0A + fv0BCId = -1; + fv0Amplitude.clear(); + fv0Channel.clear(); + fv0Time = -200; + fv0TriggerMask = 0; + + // FV0 derived quantities + fv0ChAmpl.assign(o2::aod::fit::NchFv0, 0); + fv0TotAmpl = 0; + + // FDD + fddBCId = -1; + std::fill(std::begin(fddChargeA), std::end(fddChargeA), 0); + std::fill(std::begin(fddChargeC), std::end(fddChargeC), 0); + fddTimeA = -200; + fddTimeC = -200; + fddTriggerMask = 0; + + // FDD derived quantities + fddChAmpl.assign(o2::aod::fit::NchFdd, 0); + fddTotAmplA = 0; + fddTotAmplC = 0; + + // ZDC + energyCommonZNA = -std::numeric_limits::infinity(); + energyCommonZNC = -std::numeric_limits::infinity(); + timeZEM1 = -std::numeric_limits::infinity(); + timeZEM2 = -std::numeric_limits::infinity(); + + if (hasFT0) { + // FT0 + auto ft0 = collision.foundFT0(); + ft0BCId = ft0.bcId(); + ft0TimeA = ft0.timeA(); + ft0TimeC = ft0.timeC(); + ft0TriggerMask = ft0.triggerMask(); + ft0PosZ = ft0.posZ(); + ft0CollTime = ft0.collTime(); + ft0SumAmpA = ft0.sumAmpA(); + ft0SumAmpC = ft0.sumAmpC(); + + for (size_t i = 0; i < ft0.amplitudeA().size(); i++) { + // FT0 + ft0AmplitudeA.push_back(ft0.amplitudeA()[i]); + ft0ChannelA.push_back(ft0.channelA()[i]); + + // FT0 derived quantities + ft0ChAmpl[ft0.channelA()[i]] = ft0.amplitudeA()[i]; + ft0TotAmplA += ft0.amplitudeA()[i]; + } + for (size_t i = 0; i < ft0.amplitudeC().size(); i++) { + // FT0 + ft0AmplitudeC.push_back(ft0.amplitudeC()[i]); + ft0ChannelC.push_back(ft0.channelC()[i]); + + // FT0 derived quantities + ft0ChAmpl[ft0.channelC()[i] + o2::aod::fit::NchFt0A] = ft0.amplitudeC()[i]; // Channel IDs in the C-side array start from zero in AO2D (JIRA AFIT-129) + ft0TotAmplC += ft0.amplitudeC()[i]; + } + } + + if (hasFV0) { + // FV0A + auto fv0 = collision.foundFV0(); + fv0BCId = fv0.bcId(); + fv0Time = fv0.time(); + fv0TriggerMask = fv0.triggerMask(); + + for (size_t i = 0; i < fv0.amplitude().size(); i++) { + // FV0A + fv0Amplitude.push_back(fv0.amplitude()[i]); + fv0Channel.push_back(fv0.channel()[i]); + + // FV0 derived quantities + fv0ChAmpl[fv0.channel()[i]] = fv0.amplitude()[i]; + fv0TotAmpl += fv0.amplitude()[i]; + } + } + + if (hasFDD) { + // FDD + auto fdd = collision.foundFDD(); + fddBCId = fdd.bcId(); + fddTimeA = fdd.timeA(); + fddTimeC = fdd.timeC(); + fddTriggerMask = fdd.triggerMask(); + + for (size_t i = 0; i < o2::aod::fit::NchFdd / 2; i++) { + // FDD + fddChargeA[i] = fdd.chargeA()[i]; + fddChargeC[i] = fdd.chargeC()[i]; + + // FDD derived quantities + fddChAmpl[i + o2::aod::fit::NchFdd / 2] = fdd.chargeA()[i]; + fddChAmpl[i] = fdd.chargeC()[i]; + fddTotAmplA += fdd.chargeA()[i]; + fddTotAmplC += fdd.chargeC()[i]; + } + } + + if (hasZDC) { + // ZDC + auto zdc = collision.foundZDC(); + energyCommonZNA = zdc.energyCommonZNA(); + energyCommonZNC = zdc.energyCommonZNC(); + timeZEM1 = zdc.timeZEM1(); + timeZEM2 = zdc.timeZEM2(); + } + + table(runNumber, globalBC, ctpTriggerMask, ctpInputMask, + timestamp, + triggerAlias, selectionFlags, rctFlags, sel8, hasFT0, hasFV0, hasFDD, hasZDC, + bcId, posX, posY, posZ, flags, numContrib, collisionTime, collisionTimeRes, + multFT0A, multFT0C, multFV0A, multFDDA, multFDDC, multZNA, multZNC, multZEM1, multZEM2, multZPA, multZPC, + ft0BCId, ft0AmplitudeA, ft0ChannelA, ft0AmplitudeC, ft0ChannelC, + ft0TimeA, ft0TimeC, ft0TriggerMask, ft0PosZ, ft0CollTime, ft0SumAmpA, ft0SumAmpC, + t0ACorrected, t0CCorrected, t0AC, t0resolution, + ft0ChAmpl, ft0TotAmplA, ft0TotAmplC, + fv0BCId, fv0Amplitude, fv0Channel, fv0Time, fv0TriggerMask, + fv0ChAmpl, fv0TotAmpl, + fddBCId, fddChargeA, fddChargeC, fddTimeA, fddTimeC, fddTriggerMask, + fddChAmpl, fddTotAmplA, fddTotAmplC, + energyCommonZNA, energyCommonZNC, timeZEM1, timeZEM2); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} From 901a613b5b5a4e3a34db1d55e77791b4c39e4d75 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 26 May 2026 15:47:00 +0200 Subject: [PATCH 286/449] [PWGEM/Dilepton] update taggingHFE (#16374) --- PWGEM/Dilepton/DataModel/dileptonTables.h | 25 ++- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 44 +++- .../skimmerPrimaryElectronSCT.cxx | 46 ++-- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 84 ++++--- PWGEM/Dilepton/Utils/ElectronModule.h | 207 ++++++++---------- PWGEM/Dilepton/Utils/MlResponseSCT.h | 16 +- PWGEM/Dilepton/Utils/SemiCharmTag.h | 86 ++++++-- 7 files changed, 312 insertions(+), 196 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 7bbce9eeef0..a3a7d52b4e2 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -691,13 +691,20 @@ DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! DECLARE_SOA_COLUMN(ProbElBDT, probElBDT, float); //! -DECLARE_SOA_COLUMN(BDTScorePrompt, bdtScorePrompt, std::vector); //! -DECLARE_SOA_COLUMN(BDTScorePromptHc, bdtScorePromptHc, std::vector); //! -DECLARE_SOA_COLUMN(BDTScoreNonpromptHc, bdtScoreNonpromptHc, std::vector); //! -DECLARE_SOA_COLUMN(BDTScoreHb, bdtScoreHb, std::vector); //! -DECLARE_SOA_COLUMN(HadronType, hadronType, std::vector); //! 0:track, 1:K0S, 2:Lambda, 3:AntiLambda, 4:XiMinus, 5:XiPlus, 6:OmegaMinus, 7:OmegaPlus - -DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](std::vector p0, std::vector p1, std::vector p2, std::vector p3, std::vector type, int index) -> std::array { return std::array{p0[index], p1[index], p2[index], p3[index], static_cast(type[index])}; }); +DECLARE_SOA_COLUMN(BDTScorePromptUINT8, bdtScorePromptUINT8, std::vector); //! scaling factor is 255. +DECLARE_SOA_COLUMN(BDTScorePromptHcUINT8, bdtScorePromptHcUINT8, std::vector); //! scaling factor is 255. +DECLARE_SOA_COLUMN(BDTScoreNonpromptHcUINT8, bdtScoreNonpromptHcUINT8, std::vector); //! scaling factor is 255. +DECLARE_SOA_COLUMN(BDTScoreHbUINT8, bdtScoreHbUINT8, std::vector); //! scaling factor is 255. +DECLARE_SOA_COLUMN(HadronType, hadronType, std::vector); //! 0:track, 1:K0S, 2:Lambda, 3:AntiLambda, 4:XiMinus, 5:XiPlus, 6:OmegaMinus, 7:OmegaPlus + +DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](std::vector p0, std::vector p1, std::vector p2, std::vector p3, std::vector type, int index) -> std::array { + return std::array{ + std::nextafter(p0[index] / 255.f, std::numeric_limits::infinity()), + std::nextafter(p1[index] / 255.f, std::numeric_limits::infinity()), + std::nextafter(p2[index] / 255.f, std::numeric_limits::infinity()), + std::nextafter(p3[index] / 255.f, std::numeric_limits::infinity()), + static_cast(type[index])}; +}); DECLARE_SOA_DYNAMIC_COLUMN(NSV, nSV, [](std::vector type) -> size_t { return type.size(); }); DECLARE_SOA_COLUMN(ITSNSigmaEl, itsNSigmaEl, float); //! @@ -1017,9 +1024,9 @@ DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBDERIVED using EMPrimaryElectronPrefilterBitDerived = EMPrimaryElectronsPrefilterBitDerived::iterator; DECLARE_SOA_TABLE(EMPrimaryElectronsBDTSCT, "AOD", "ELBDTSCT", // To be joined with EMPrimaryElectrons table at analysis level. - emprimaryelectron::BDTScorePrompt, emprimaryelectron::BDTScorePromptHc, emprimaryelectron::BDTScoreNonpromptHc, emprimaryelectron::BDTScoreHb, emprimaryelectron::HadronType, + emprimaryelectron::BDTScorePromptUINT8, emprimaryelectron::BDTScorePromptHcUINT8, emprimaryelectron::BDTScoreNonpromptHcUINT8, emprimaryelectron::BDTScoreHbUINT8, emprimaryelectron::HadronType, emprimaryelectron::NSV, - emprimaryelectron::ProbaSCT); + emprimaryelectron::ProbaSCT); // iterators using EMPrimaryElectronBDTSCT = EMPrimaryElectronsBDTSCT::iterator; diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 77245cee69d..8f6cac72a92 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -219,13 +219,14 @@ DECLARE_SOA_COLUMN(ImpParCZYL, impParCZYL, float); //! sigma of i DECLARE_SOA_COLUMN(ImpParCZZL, impParCZZL, float); //! sigma of impact parameter for lepton in Z DECLARE_SOA_COLUMN(PdgCodeMother, pdgCodeMother, int); //! pdg code of mother of lepton DECLARE_SOA_COLUMN(IsCorrectCollision, isCorrectCollision, bool); //! LH pair is associated to correct collision. +DECLARE_SOA_COLUMN(MotherId, motherId, int); //! globalIndex of mother of lepton } // namespace emmltrack DECLARE_SOA_TABLE(EMMLLeptons, "AOD", "EMMLLEPTON", //! o2::soa::Index<>, emmltrack::EMMLEventId, emmlevent::SubGeneratorId, emmltrack::Signed1PtL, emmltrack::EtaL, emmltrack::PhiL, emmltrack::ImpParXYL, emmltrack::ImpParZL, emmltrack::ImpParCYYL, emmltrack::ImpParCZYL, emmltrack::ImpParCZZL, - emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother, emmltrack::IsCorrectCollision); + emmltrack::IsMotherFromBeauty, emmltrack::PdgCodeMother, emmltrack::MotherId, emmltrack::IsCorrectCollision); // iterators using EMMLLepton = EMMLLeptons::iterator; @@ -248,7 +249,7 @@ DECLARE_SOA_COLUMN(ImpParCZZH, impParCZZH, float); //! sigma of impact parameter DECLARE_SOA_COLUMN(V0CPA, v0cpa, float); //! cosPA of V0 DECLARE_SOA_COLUMN(V0CPAXY, v0cpaXY, float); //! cosPA of V0 in XY plane -DECLARE_SOA_COLUMN(V0CPARZ, v0cpaRZ, float); //! cosPA of V0 in XY plane +DECLARE_SOA_COLUMN(V0CPARZ, v0cpaRZ, float); //! cosPA of V0 in RZ plane DECLARE_SOA_COLUMN(CascCPA, casccpa, float); //! cosPA of Cascade DECLARE_SOA_COLUMN(CascCPAXY, casccpaXY, float); //! cosPA of Cascade in XY plane @@ -259,11 +260,24 @@ DECLARE_SOA_COLUMN(CascadeType, cascadeType, uint8_t); //! cascade type, 0 = XiM // LH pair variables DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming pion -DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pT of LH pair -DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron -DECLARE_SOA_COLUMN(CPA, cpa, float); //! cosine of pointing angle of LH pair -DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); //! cosine of pointing angle of LH pair in XY -DECLARE_SOA_COLUMN(CPARZ, cpaRZ, float); //! cosine of pointing angle of LH pair in RZ + +DECLARE_SOA_COLUMN(PtSVL, ptSVL, float); //! pT of lepton at SV +DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV +DECLARE_SOA_COLUMN(PtSVH, ptSVH, float); //! pT of associated hadron at SV +DECLARE_SOA_COLUMN(PlSVH, plSVH, float); //! pL of associated hadron at SV + +DECLARE_SOA_COLUMN(PtFDL, ptFDL, float); //! pT of lepton perpendicular to flight direction +DECLARE_SOA_COLUMN(PlFDL, plFDL, float); //! pL of lepton in parallel to flight direction +DECLARE_SOA_COLUMN(PtFDH, ptFDH, float); //! pT of associated hadron perpendicular to flight direction +DECLARE_SOA_COLUMN(PlFDH, plFDH, float); //! pL of associated hadron in parallel to flight direction + +DECLARE_SOA_COLUMN(PtFD, ptFD, float); //! visible momentum of LH pair perpendicular to flight direction = - missing pT due to neutrino perpendicular to flight direction +DECLARE_SOA_COLUMN(PlFD, plFD, float); //! visible momentum of LH pair in parallel to flight direction + +DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron +DECLARE_SOA_COLUMN(CPA, cpa, float); //! cosine of pointing angle of LH pair +DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); //! cosine of pointing angle of LH pair in XY +DECLARE_SOA_COLUMN(CPARZ, cpaRZ, float); //! cosine of pointing angle of LH pair in RZ DECLARE_SOA_COLUMN(Lxy, lxy, float); //! decay length of LH pair DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair @@ -287,10 +301,12 @@ DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! emmllhpair::EMMLLeptonId, emmllhpair::Signed1PtH, emmllhpair::EtaH, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, + // pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, - pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + // pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, + emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); @@ -302,7 +318,9 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); @@ -314,7 +332,9 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx index 2836feae3db..53467cfbca6 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx @@ -66,16 +66,10 @@ #include -// using namespace o2; -// using namespace o2::soa; -// using namespace o2::framework; -// using namespace o2::framework::expressions; -// using namespace o2::constants::physics; -// using namespace o2::common::core; - struct skimmerPrimaryElectronSCT { - using MyBCs = o2::soa::Join; + // using MyBCs = o2::soa::Join; + using MyBCs = o2::soa::Join; using MyCollisions = o2::soa::Join; using MyCollisionsWithSWT = o2::soa::Join; @@ -207,28 +201,44 @@ struct skimmerPrimaryElectronSCT { void processRec_SA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA, "process reconstructed info only", true); // standalone void processRec_TTCA(MyCollisions const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA, "process reconstructed info only", false); // with TTCA void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, nullptr, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_SA_SWT, "process reconstructed info only", false); // standalone with swt void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs, MyTracks const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, nullptr, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA with swt @@ -237,14 +247,22 @@ struct skimmerPrimaryElectronSCT { void processMC_SA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McParticles const& mcParticles) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithoutTTCA(bcs, collisions, tracks, v0s, cascades, mcParticles, products, mRegistry); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_SA, "process reconstructed and MC info ", false); // without TTCA in MC void processMC_TTCA(o2::soa::Join const& collisions, MyBCs const& bcs, MyTracksMC const& tracks, o2::aod::TrackAssoc const& trackIndices, filteredMyV0s const& v0s, filteredMyCascades const& cascades, o2::aod::McParticles const& mcParticles) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); electronModule.processWithTTCA(bcs, collisions, tracks, v0s, cascades, trackIndices, mcParticles, products, mRegistry, cache, perCol_track, trackIndicesPerCollision, perCol_v0, perCol_casc); } PROCESS_SWITCH(skimmerPrimaryElectronSCT, processMC_TTCA, "process reconstructed info only", false); // with TTCA in MC diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 8c12b5b11f3..0b25521a7b6 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1706,7 +1706,7 @@ struct taggingHFE { npos++; leptonTable(eventTable.lastIndex() + 1, mcCollision_mcpos.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), RecoDecay::constrainAngle(leptonParCov.getPhi(), 0, 1U), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromB, mcMother.pdgCode(), isCorrectCollision); + isMotherFromB, mcMother.pdgCode(), mcMother.globalIndex(), isCorrectCollision); // D0 -> e+ nu_e K-, br = 0.03538, ctau = 123.01 um, m = 1864 MeV/c2 for (const auto& kaonId : kaonMinusIds) { @@ -1753,16 +1753,18 @@ struct taggingHFE { continue; } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaPi(), tofNSigmaPi, + // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, - kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + // kaon.tpcNSigmaPr(), tofNSigmaPr, + eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -1812,16 +1814,18 @@ struct taggingHFE { continue; } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaPi(), tofNSigmaPi, + // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, - kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + // kaon.tpcNSigmaPr(), tofNSigmaPr, + eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -1898,7 +1902,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -1959,7 +1965,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -2025,7 +2033,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2091,7 +2101,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2131,7 +2143,7 @@ struct taggingHFE { nele++; leptonTable(eventTable.lastIndex() + 1, mcCollision_mcele.getSubGeneratorId(), leptonParCov.getQ2Pt(), leptonParCov.getEta(), RecoDecay::constrainAngle(leptonParCov.getPhi(), 0, 1U), dcaXY_lepton, dcaZ_lepton, leptonParCov.getSigmaY2(), leptonParCov.getSigmaZY(), leptonParCov.getSigmaZ2(), - isMotherFromB, mcMother.pdgCode(), isCorrectCollision); + isMotherFromB, mcMother.pdgCode(), mcMother.globalIndex(), isCorrectCollision); for (const auto& kaonId : kaonMinusIds) { auto kaon = tracks.rawIteratorAt(kaonId); @@ -2177,16 +2189,18 @@ struct taggingHFE { continue; } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaPi(), tofNSigmaPi, + // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, - kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + // kaon.tpcNSigmaPr(), tofNSigmaPr, + eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -2237,16 +2251,18 @@ struct taggingHFE { continue; } - float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPi = mapTOFNsigmaPiReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; float tofNSigmaKa = mapTOFNsigmaKaReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; - float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; + // float tofNSigmaPr = mapTOFNsigmaPrReassociated[std::make_pair(collision.globalIndex(), kaon.globalIndex())]; emmlltpair(leptonTable.lastIndex(), trackParCov.getQ2Pt(), trackParCov.getEta(), dcaXY_kaon, dcaZ_kaon, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - kaon.tpcNSigmaPi(), tofNSigmaPi, + // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, - kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + // kaon.tpcNSigmaPr(), tofNSigmaPr, + eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); @@ -2322,7 +2338,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -2383,7 +2401,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); @@ -2449,7 +2469,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); @@ -2515,7 +2537,9 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index f71f7d3d7a9..c2d7d343c75 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -276,9 +276,9 @@ struct cfgDFeT : o2::framework::ConfigurableGroup { o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -293,9 +293,9 @@ struct cfgDFeV0 : o2::framework::ConfigurableGroup { o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -310,9 +310,9 @@ struct cfgDFeC : o2::framework::ConfigurableGroup { o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.2, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "cpa", "cpaXY", "dcaLH", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -330,11 +330,11 @@ class ElectronModule // destructor } - struct looseElectron { - float pt{1e+10}; - float eta{1e+10}; - float phi{1e+10}; - }; + // struct looseElectron { + // float pt{1e+10}; + // float eta{1e+10}; + // float phi{1e+10}; + // }; template void init(TElectronCut const& eCut, TElectronPFCut const& ePFCut, THadronCut const& hCut, TV0Cut const& v0Cut, TCascadeCut const& cascadeCut, TDFConfigET const& cfgET, TDFConfigEV0 const& cfgEV0, TDFConfigEC const& cfgEC, TInitContext& initContext, TCCDB& ccdb, TTOFResponse const& tofResponse, std::string const& ccdburl) @@ -402,6 +402,7 @@ class ElectronModule // initialize MLResponse if (fElectronCut.usePIDML) { + LOGF(info, "loading ONNX for ML PID"); static constexpr int nClassesMl = 2; const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; const std::vector labelsClasses = {"Background", "Signal"}; @@ -426,9 +427,10 @@ class ElectronModule } // end of ML PID if (fConfigDFeT.useML) { + LOGF(info, "loading ONNX for SCT eT"); static constexpr int nClassesMl = 4; const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + const std::vector labelsClasses = {"background", "prompthc", "nonprompthc", "hb"}; const uint32_t nBinsMl = fConfigDFeT.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); double cutsMlArr[nBinsMl][nClassesMl]; @@ -452,9 +454,10 @@ class ElectronModule } // end of ML SCTeT if (fConfigDFeV0.useML) { + LOGF(info, "loading ONNX for SCT eV0"); static constexpr int nClassesMl = 4; const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + const std::vector labelsClasses = {"background", "prompthc", "nonprompthc", "hb"}; const uint32_t nBinsMl = fConfigDFeV0.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); double cutsMlArr[nBinsMl][nClassesMl]; @@ -478,9 +481,10 @@ class ElectronModule } // end of ML SCTeV0 if (fConfigDFeC.useML) { - static constexpr int nClassesMl = 4; - const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"prompt", "prompthc", "nonprompthc", "hb"}; + LOGF(info, "loading ONNX for SCT eC"); + static constexpr int nClassesMl = 3; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutNot, o2::cuts_ml::CutNot}; + const std::vector labelsClasses = {"background", "prompthc", "nonprompthc"}; const uint32_t nBinsMl = fConfigDFeC.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); double cutsMlArr[nBinsMl][nClassesMl]; @@ -488,7 +492,6 @@ class ElectronModule cutsMlArr[i][0] = 0.0; cutsMlArr[i][1] = 0.0; cutsMlArr[i][2] = 0.0; - cutsMlArr[i][3] = 0.0; } o2::framework::LabeledArray cutsMltmp = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -1348,7 +1351,11 @@ class ElectronModule template void processWithTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const& tracks, TV0s const& v0s, TCascades const& cascades, TTrackAssoc const& trackIndices, TMCParticles const&, TProducts& products, THistoregistry& registry, TSliceCache& cache, TPresliceTrack const& perColTrack, TPresliceTrackAssoc const& trackIndicesPerCollision, TPresliceV0 const& perColV0, TPresliceCascade const& perColCasc) { - initCCDB(bcs.begin()); + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices, cache, perColTrack, trackIndicesPerCollision); @@ -1625,10 +1632,10 @@ class ElectronModule products.electronPFTable(pfb); // perform SCT from here - std::vector bdtScorePrompt; - std::vector bdtScorePromptHc; - std::vector bdtScoreNonpromptHc; - std::vector bdtScoreHb; + std::vector bdtScorePrompt; + std::vector bdtScorePromptHc; + std::vector bdtScoreNonpromptHc; + std::vector bdtScoreHb; std::vector hadronType; bdtScorePrompt.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); @@ -1674,15 +1681,11 @@ class ElectronModule pbin = static_cast(fConfigDFeT.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeT.getModelOutput(inputFeatures, pbin)[3]; - - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeT.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); hadronType.emplace_back(0); } } // end of charged track loop @@ -1717,6 +1720,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassK0Short; std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); @@ -1728,14 +1732,11 @@ class ElectronModule pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); hadronType.emplace_back(1); } } // end of k0s loop @@ -1771,6 +1772,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassLambda; std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); @@ -1782,14 +1784,11 @@ class ElectronModule pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); hadronType.emplace_back(2); } } // end of lambda loop @@ -1825,6 +1824,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassXiMinus; std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); @@ -1836,14 +1836,11 @@ class ElectronModule pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(0)); hadronType.emplace_back(4); } } // end of Xi- loop @@ -1879,6 +1876,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassOmegaMinus; std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); @@ -1890,14 +1888,11 @@ class ElectronModule pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(0)); hadronType.emplace_back(6); } } // end of Omega- loop @@ -1933,6 +1928,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassLambda; std::vector inputFeatures = mlResponseSCTeV0.getInputFeatures(candidate); float binningFeature = mlResponseSCTeV0.getBinningFeature(candidate); @@ -1944,14 +1940,11 @@ class ElectronModule pbin = static_cast(fConfigDFeV0.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); hadronType.emplace_back(3); } } // end of antilambda loop @@ -1987,6 +1980,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassXiMinus; std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); @@ -1998,14 +1992,11 @@ class ElectronModule pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(0)); hadronType.emplace_back(5); } } // end of Xi- loop @@ -2041,6 +2032,7 @@ class ElectronModule o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); + candidate.massH = o2::constants::physics::MassOmegaMinus; std::vector inputFeatures = mlResponseSCTeC.getInputFeatures(candidate); float binningFeature = mlResponseSCTeC.getBinningFeature(candidate); @@ -2052,14 +2044,11 @@ class ElectronModule pbin = static_cast(fConfigDFeC.binsMl.value.size()) - 2; } - float probaPrompt = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[0]; - float probaPromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[1]; - float probaNonpromptHc = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[2]; - float probaHb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin)[3]; - bdtScorePrompt.emplace_back(probaPrompt); - bdtScorePromptHc.emplace_back(probaPromptHc); - bdtScoreNonpromptHc.emplace_back(probaNonpromptHc); - bdtScoreHb.emplace_back(probaHb); + auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); + bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); + bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); + bdtScoreHb.emplace_back(static_cast(0)); hadronType.emplace_back(7); } } // end of Omega- loop @@ -2108,37 +2097,36 @@ class ElectronModule } template - void processWithoutTTCA(TBCs const& bcs, TCollisions const& collisions, TTracks const&, TV0s const&, TCascades const&, TMCParticles const&, TProducts&, THistoregistry&) + void processWithoutTTCA(TBCs const&, TCollisions const&, TTracks const&, TV0s const&, TCascades const&, TMCParticles const&, TProducts&, THistoregistry&) { LOGF(info, "processWithoutTTCA is not supported. Bye."); - return; - initCCDB(bcs.begin()); - // calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); + // initCCDB(bcs.begin()); + // // calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); - for (const auto& collision : collisions) { - auto bc = collision.template bc_as(); - initCCDB(bc); + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); - if constexpr (isMC) { - if (!collision.has_mcCollision()) { - continue; - } - } + // if constexpr (isMC) { + // if (!collision.has_mcCollision()) { + // continue; + // } + // } - if (!collision.isSelected()) { - continue; - } + // if (!collision.isSelected()) { + // continue; + // } - if constexpr (isTriggerAnalysis) { - if (collision.swtaliastmp_raw() == 0) { - continue; - } - } + // if constexpr (isTriggerAnalysis) { + // if (collision.swtaliastmp_raw() == 0) { + // continue; + // } + // } - } // end of collision loop + // } // end of collision loop - clear(); + // clear(); } void clear() @@ -2180,7 +2168,6 @@ class ElectronModule candidate.signLH = 0; candidate.dcaLH = pair.dca2legs; candidate.massLH = pair.mass; - candidate.ptLH = pair.pt; candidate.signedMassLH = pair.mass; candidate.cpa = pair.cospa; candidate.cpaXY = pair.cospaXY; diff --git a/PWGEM/Dilepton/Utils/MlResponseSCT.h b/PWGEM/Dilepton/Utils/MlResponseSCT.h index d0c1353e443..8a00659ecc0 100644 --- a/PWGEM/Dilepton/Utils/MlResponseSCT.h +++ b/PWGEM/Dilepton/Utils/MlResponseSCT.h @@ -53,6 +53,7 @@ enum class InputFeaturesSCT : uint8_t { impParZLinSigma, impPar3DLinSigma, ptH, + massH, tpcNSigmaKa, impParXYH, impParZH, @@ -63,8 +64,9 @@ enum class InputFeaturesSCT : uint8_t { signLH, dcaLH, massLH, - ptLH, signedMassLH, + missingPtNuPerpToFD, + correctedMass, cpa, cpaXY, impParXY, @@ -95,6 +97,7 @@ struct candidate { // hadron information float ptH{0}; + float massH{0}; // only for V0s and Cascades float tpcNSigmaKa{0}; float impParXYH{0}; float impParZH{0}; @@ -107,8 +110,9 @@ struct candidate { int signLH{0}; float dcaLH{0}; float massLH{0}; - float ptLH{0}; float signedMassLH{0}; + float missingPtNuPerpToFD{0}; + float correctedMass{0}; float cpa{0}; float cpaXY{0}; float impParXY{0}; @@ -148,6 +152,7 @@ class MlResponseSCT : public MlResponse CHECK_AND_FILL_TRACK(impParZLinSigma); CHECK_AND_FILL_TRACK(impPar3DLinSigma); CHECK_AND_FILL_TRACK(ptH); + CHECK_AND_FILL_TRACK(massH); CHECK_AND_FILL_TRACK(tpcNSigmaKa); CHECK_AND_FILL_TRACK(impParXYH); CHECK_AND_FILL_TRACK(impParZH); @@ -158,8 +163,9 @@ class MlResponseSCT : public MlResponse CHECK_AND_FILL_TRACK(signLH); CHECK_AND_FILL_TRACK(dcaLH); CHECK_AND_FILL_TRACK(massLH); - CHECK_AND_FILL_TRACK(ptLH); CHECK_AND_FILL_TRACK(signedMassLH); + CHECK_AND_FILL_TRACK(missingPtNuPerpToFD); + CHECK_AND_FILL_TRACK(correctedMass); CHECK_AND_FILL_TRACK(cpa); CHECK_AND_FILL_TRACK(cpaXY); CHECK_AND_FILL_TRACK(impParXY); @@ -224,6 +230,7 @@ class MlResponseSCT : public MlResponse FILL_MAP_TRACK(impParZLinSigma), FILL_MAP_TRACK(impPar3DLinSigma), FILL_MAP_TRACK(ptH), + FILL_MAP_TRACK(massH), FILL_MAP_TRACK(tpcNSigmaKa), FILL_MAP_TRACK(impParXYH), FILL_MAP_TRACK(impParZH), @@ -234,8 +241,9 @@ class MlResponseSCT : public MlResponse FILL_MAP_TRACK(signLH), FILL_MAP_TRACK(dcaLH), FILL_MAP_TRACK(massLH), - FILL_MAP_TRACK(ptLH), FILL_MAP_TRACK(signedMassLH), + FILL_MAP_TRACK(missingPtNuPerpToFD), + FILL_MAP_TRACK(correctedMass), FILL_MAP_TRACK(cpa), FILL_MAP_TRACK(cpaXY), FILL_MAP_TRACK(impParXY), diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index 75607042ca6..a174ca3fedc 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -23,8 +23,6 @@ #include #include #include -// #include -// #include #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) @@ -37,7 +35,6 @@ namespace o2::aod::pwgem::dilepton::utils struct LHPair { // struct to store electron-hadron pair information float mass{-999.f}; - float pt{-999.f}; float dca2legs{-999.f}; float cospa{-999.f}; float cospaXY{-999.f}; @@ -53,6 +50,20 @@ struct LHPair { // struct to store electron-hadron pair information float impParCYY{-999.f}; float impParCZY{-999.f}; float impParCZZ{-999.f}; + + float ptSVL{-999.f}; + float plSVL{-999.f}; + float ptSVH{-999.f}; + float plSVH{-999.f}; + + float ptFDL{-999.f}; + float plFDL{-999.f}; + float ptFDH{-999.f}; + float plFDH{-999.f}; + + float ptFD{-999.f}; + float plFD{-999.f}; + bool isOK{false}; }; @@ -95,6 +106,11 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton fitter.getTrack(1).getPxPyPzGlo(pvec1); // track std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; + pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + pair.plSVL = pvec0[2]; + pair.plSVH = pvec1[2]; + pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); @@ -104,12 +120,21 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.lxyz = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2) + std::pow(svpos[2] - collision.posZ(), 2)); auto primaryVertex = getPrimaryVertex(collision); - std::array covVtxLK = fitter.calcPCACovMatrixFlat(); - double phiLH{}, thetaLK{}; - getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, svpos, phiLH, thetaLK); - pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, thetaLK) + getRotatedCovMatrixXX(covVtxLK, phiLH, thetaLK)); - pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, 0.) + getRotatedCovMatrixXX(covVtxLK, phiLH, 0.)); - pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLK) + getRotatedCovMatrixXX(covVtxLK, 0, thetaLK)); + std::array covVtxLH = fitter.calcPCACovMatrixFlat(); + double phiLH{}, thetaLH{}; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, svpos, phiLH, thetaLH); + pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, thetaLH) + getRotatedCovMatrixXX(covVtxLH, phiLH, thetaLH)); + pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, 0.) + getRotatedCovMatrixXX(covVtxLH, phiLH, 0.)); + pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLH) + getRotatedCovMatrixXX(covVtxLH, 0, thetaLH)); + + std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + + pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); @@ -139,10 +164,12 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton return pair; } - ROOT::Math::PxPyPzMVector v2(pvec1[0], pvec1[1], pvec1[2], o2::constants::physics::MassPionCharged); + ROOT::Math::PxPyPzMVector v2(pvec1[0], pvec1[1], pvec1[2], o2::constants::physics::MassKaonCharged); ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); - pair.pt = v12.Pt(); + + // float tmp = v12.P() * std::sin(std::acos(pair.cospa)); + // LOGF(info, "pair.ptFD = %f, tmp = %f", pair.ptFD, tmp); pair.isOK = true; return pair; @@ -193,10 +220,15 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co for (int i = 0; i < 3; i++) { svpos[i] = vtx[i]; } - fitter.getTrack(0).getPxPyPzGlo(pvec0); // electron + fitter.getTrack(0).getPxPyPzGlo(pvec0); // lepton fitter.getTrack(1).getPxPyPzGlo(pvec1); // v0 std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; + pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + pair.plSVL = pvec0[2]; + pair.plSVH = pvec1[2]; + pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); @@ -213,6 +245,15 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLV0, 0.) + getRotatedCovMatrixXX(covVtxLV0, phiLV0, 0.)); pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLV0) + getRotatedCovMatrixXX(covVtxLV0, 0, thetaLV0)); + std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + + pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); + // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); v0ParCov.propagateTo(vtx[0], fitter.getBz()); @@ -252,7 +293,6 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); - pair.pt = v12.Pt(); pair.isOK = true; return pair; @@ -307,10 +347,15 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept for (int i = 0; i < 3; i++) { svpos[i] = vtx[i]; } - fitter.getTrack(0).getPxPyPzGlo(pvec0); // electron - fitter.getTrack(1).getPxPyPzGlo(pvec1); // v0 + fitter.getTrack(0).getPxPyPzGlo(pvec0); // lepton + fitter.getTrack(1).getPxPyPzGlo(pvec1); // cascade std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; + pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + pair.plSVL = pvec0[2]; + pair.plSVH = pvec1[2]; + pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); @@ -327,6 +372,15 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLC) + getRotatedCovMatrixXX(covVtxLC, 0, thetaLC)); pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLC, thetaLC) + getRotatedCovMatrixXX(covVtxLC, phiLC, thetaLC)); + std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + + pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); + // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); cascParCov.propagateTo(vtx[0], fitter.getBz()); @@ -365,9 +419,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept } ROOT::Math::PxPyPzMVector v12 = v1 + v2; - pair.mass = v12.M(); - pair.pt = v12.Pt(); pair.isOK = true; return pair; From 840d6bbe716e01b378919021b925802d10e3dbd8 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Tue, 26 May 2026 17:53:49 +0200 Subject: [PATCH 287/449] [PWGLF] Nuspex: proton nuclei correlation: add merging rejection (#16391) --- .../Tasks/Nuspex/hadronnucleicorrelation.cxx | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index c93c8b7778b..59e36311135 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -93,8 +93,10 @@ struct HadronNucleiCorrelation { Configurable cutzVertex{"cutzVertex", 10.0, "|vertexZ| value limit"}; // Track selection + Configurable doClosePairRejection{"doClosePairRejection", false, "doClosePairRejection"}; Configurable par0{"par0", 0.004, "par 0"}; Configurable par1{"par1", 0.013, "par 1"}; + Configurable doDCAZ{"doDCAZ", true, "do DCA z cut"}; Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of found TPC clusters"}; Configurable min_TPC_nCrossedRowsOverFindableCls{"min_TPC_nCrossedRowsOverFindableCls", 0.8, "n TPC Crossed Rows Over Findable Cls"}; Configurable max_chi2_TPC{"max_chi2_TPC", 4.0f, "maximum TPC chi^2/Ncls"}; @@ -546,7 +548,8 @@ struct HadronNucleiCorrelation { // pt-dependent selection if (std::abs(track.dcaXY()) > (par0 + par1 / track.pt())) passcut = false; - if (std::abs(track.dcaZ()) > (par0 + par1 / track.pt())) + + if (doDCAZ && std::abs(track.dcaZ()) > (par0 + par1 / track.pt())) passcut = false; return passcut; @@ -562,6 +565,11 @@ struct HadronNucleiCorrelation { return; } + if (doClosePairRejection && Pair->IsClosePair(dEta, dPhi, radiusTPC)) { + QA.fill(HIST("QA/hdEtadPhistar"), Pair->GetPhiStarDiff(radiusTPC), Pair->GetEtaDiff()); + return; + } + float deltaEta = part0.eta() - part1.eta(); float deltaPhi = part0.phi() - part1.phi(); deltaPhi = RecoDecay::constrainAngle(deltaPhi, -1 * o2::constants::math::PIHalf); @@ -611,10 +619,14 @@ struct HadronNucleiCorrelation { if (ME) { hEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, part1.pt()); - hCorrEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, part1.pt(), 1. / (corr0 * corr1)); + if (corr0 != 0 && corr1 != 0) { + hCorrEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, part1.pt(), 1. / (corr0 * corr1)); + } } else { hEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, part1.pt()); - hCorrEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, part1.pt(), 1. / (corr0 * corr1)); + if (corr0 != 0 && corr1 != 0) { + hCorrEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, part1.pt(), 1. / (corr0 * corr1)); + } } // SE } // pT condition } // nBinspT loop @@ -682,7 +694,7 @@ struct HadronNucleiCorrelation { float getMCMultiplicity(TParticles const& particles) { float Ncharged = 0.; - for (auto& mcParticle : particles) { + for (const auto& mcParticle : particles) { if (!mcParticle.isPhysicalPrimary()) { continue; From fa0ee9a4b672236526b392aba487f730df64295a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Jos=C3=A9?= <52935244+lucasjsilva@users.noreply.github.com> Date: Tue, 26 May 2026 18:06:12 +0200 Subject: [PATCH 288/449] [PWGLF] Correction for pT extrapolation (#16376) --- .../Tasks/GlobalEventProperties/studyPnch.cxx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx index 43e1d5dcce9..8bf72d54a5a 100644 --- a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx @@ -113,6 +113,7 @@ struct StudyPnch { Configurable maxPhi{"maxPhi", 6.283185f, "Maximum phi value for track selection"}; Configurable isPtincrease{"isPtincrease", false, "Varies low pT particles by a conservative amount of +100%"}; Configurable isPtdecrease{"isPtdecrease", false, "Varies low pT particles by a conservative amount of -50%"}; + Configurable cPrint{"cPrint", false, "Enable printing information for debugging"}; Configurable isApplyStrangenessSysUncert{"isApplyStrangenessSysUncert", false, "Enable the evaluation of systematics due to strange particle contribution"}; void init(InitContext const&) @@ -359,6 +360,7 @@ struct StudyPnch { float countTracksPtCut(countTrk const& tracks, McColType const& McCol) { float nTrk = 0.0; + auto count = 0; for (const auto& track : tracks) { if (!isGenTrackSelected(track)) { continue; @@ -366,14 +368,24 @@ struct StudyPnch { if (track.mcCollisionId() != McCol.mcCollisionId()) { continue; } - if (track.pt() > pTminCut) + if (track.pt() > pTminCut) { + count++; continue; + } if (isPtincrease) { - nTrk += 2 - 10 * track.pt(); + nTrk += 2 - 10 * track.pt() - 1; } else { - nTrk += 0.5 + 5 * track.pt(); + nTrk += 0.5 + 5 * track.pt() - 1; + } + if (cPrint) { + LOG(info) << "nTrk: " << nTrk; + LOG(info) << "low pT = " << track.pt(); } } + if (nTrk != 0 && cPrint) { + LOG(info) << "counts standard pT: " << count; + LOG(info) << "Result of the function: " << nTrk; + } return nTrk; } @@ -429,10 +441,17 @@ struct StudyPnch { auto multrec = countNTracksMcCol(recTracksPart, RecCol); histos.fill(HIST("hMultiplicityMCrec"), multrec); float multgen = countGenTracks(GenParticles, RecCol); + if (cPrint) { + LOG(info) << "Generated Particles with standard pT:" << multgen; + } histos.fill(HIST("hMultiplicityMCgen"), multgen); histos.fill(HIST("hResponseMatrix"), multrec, multgen); float nTrkPtCut = countTracksPtCut(GenParticles, RecCol); nTrkPtCut = multgen + nTrkPtCut; + if (cPrint) { + LOG(info) << "After Counting low pT: " << nTrkPtCut; + LOG(info) << "########################"; + } histos.fill(HIST("hMultiplicityMCgenPtCut"), nTrkPtCut); histos.fill(HIST("hResponseMatrixPtCut"), multrec, nTrkPtCut); if (isApplyStrangenessSysUncert) { From b3798af62b4ab2043f025f6cb9c51cd571668935 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Tue, 26 May 2026 22:17:31 +0530 Subject: [PATCH 289/449] [PWGLF] Added new PID method and fake track rejection (#16383) --- PWGLF/Tasks/Resonances/kstarqa.cxx | 391 +++++++++++------------------ 1 file changed, 152 insertions(+), 239 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index cb175523fd2..8dd87cb002a 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -101,6 +101,8 @@ struct Kstarqa { Configurable isapplypTdepPIDTOF{"isapplypTdepPIDTOF", false, "Apply pT dependent PID for TOF"}; Configurable isApplyParticleMID{"isApplyParticleMID", false, "Apply particle misidentification"}; Configurable isApplyParticleMIDPtDep{"isApplyParticleMIDPtDep", false, "Apply pT dependent MID selection"}; + Configurable isapplyPID2{"isapplyPID2", false, "Apply second PID selection"}; + Configurable isapplyPID1{"isapplyPID1", true, "Apply default PID selection"}; Configurable isApplyParticleMIDPtDep2{"isApplyParticleMIDPtDep2", false, "Apply pT dependent MID selection (nSigma less of contamination lt nSigma of signal)"}; Configurable allGenEvents{"allGenEvents", false, "Fill all generated events in MC for signal loss calculations"}; @@ -125,8 +127,8 @@ struct Kstarqa { Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; // Configurable ctrackRapidity{"ctrackRapidity", 0.3f, "Cut on track rapidity"}; Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; - // Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 70, "TPC NCL Found"}; + Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 80, "TPC NCL Found"}; // Configurable cfgRCRFC{"cfgRCRFC", 0.8f, "Crossed Rows to Findable Clusters"}; // Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 36.0, "ITS Chi2/NCl"}; // Configurable cfgTPCChi2NClMax{"cfgTPCChi2NClMax", 4.0, "TPC Chi2/NCl"}; @@ -136,6 +138,9 @@ struct Kstarqa { Configurable isApplyPtDepDCAxyCut{"isApplyPtDepDCAxyCut", false, "Apply pT dependent DCAxy cut"}; // Configurable isGoldenChi2{"isGoldenChi2", false, "Apply golden chi2 cut"}; // Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; + Configurable cFakeTrackCutKa{"cFakeTrackCutKa", 0.1, "Cut based on momentum difference in global and TPC tracks for Kaons"}; + Configurable cBetaCutTOFKaon{"cBetaCutTOFKaon", 0.0, "cut TOF beta"}; + Configurable cFakeTrack{"cFakeTrack", true, "Fake track selection"}; // cuts on mother // Configurable isApplyCutsOnMother{"isApplyCutsOnMother", false, "Enable additional cuts on Kstar mother"}; @@ -210,10 +215,6 @@ struct Kstarqa { // Configurable applyRecMotherRapidity{"applyRecMotherRapidity", true, "Apply rapidity cut on reconstructed mother track"}; // Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - // Configurable cBetaCutTOF{"cBetaCutTOF", 0.0, "cut TOF beta"}; - // Configurable cFakeTrack{"cFakeTrack", true, "Fake track selection"}; - // Configurable cFakeTrackCutKa{"cFakeTrackCutKa", 0.5, "Cut based on momentum difference in global and TPC tracks for Kaons"}; - // Configurable cFakeTrackCutPi{"cFakeTrackCutPi", 0.5, "Cut based on momentum difference in global and TPC tracks for Pions"}; // Configurable for histograms Configurable avoidsplitrackMC{"avoidsplitrackMC", true, "avoid split track in MC"}; @@ -296,6 +297,10 @@ struct Kstarqa { hOthers.add("hEta_after", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); hOthers.add("hCRFC_after", "CRFC after distribution", kTH1F, {{100, 0.0f, 10.0f}}); hOthers.add("hCRFC_before", "CRFC before distribution", kTH1F, {{100, 0.0f, 10.0f}}); + hOthers.add("hTOFBetaKa", "Beta distribution from TOF", kTH1F, {{50, 0.0f, 1.0f}}); + hOthers.add("hTOFBetaPi", "Beta distribution from TOF", kTH1F, {{50, 0.0f, 1.0f}}); + hOthers.add("hTPCMomDiffKa", "Momentum difference between global and TPC tracks for Kaons", kTH1F, {{100, -1.0f, 1.0f}}); + hOthers.add("hTPCMomDiffPi", "Momentum difference between global and TPC tracks for Pions", kTH1F, {{100, -1.0f, 1.0f}}); hOthers.add("hKstar_rap_pt", "Pair rapidity distribution; y; p_{T}; Counts", kTH2F, {{400, -2.0f, 2.0f}, ptAxis}); hOthers.add("hKstar_eta_pt", "Pair eta distribution; #eta; p_{T}; Counts", kTH2F, {{400, -2.0f, 2.0f}, ptAxis}); @@ -554,15 +559,13 @@ struct Kstarqa { bool selectionTrack(const T& candidate) { if (configGp.isGlobalTracks) { - if (!candidate.isGlobalTrackWoDCA()) + if (!candidate.isGlobalTrack()) return false; if (std::abs(candidate.pt()) < configGp.cfgCutPT) return false; - // if (std::abs(candidate.eta()) > configGp.cfgCutEtaMax || std::abs(candidate.eta()) < configGp.cfgCutEtaMin) if (std::abs(candidate.eta()) > configGp.cfgCutEtaMax) return false; if (!configGp.isApplyPtDepDCAxyCut) { - // if (std::abs(candidate.dcaXY()) > configGp.cfgCutDCAxyMax || std::abs(candidate.dcaXY()) < configGp.cfgCutDCAxyMin) if (std::abs(candidate.dcaXY()) > configGp.cfgCutDCAxyMax) return false; } else { @@ -571,16 +574,10 @@ struct Kstarqa { } if (std::abs(candidate.dcaZ()) > configGp.cfgCutDCAz) return false; - // if (candidate.tpcCrossedRowsOverFindableCls() < configGp.cfgRCRFC) - // return false; - // if (candidate.itsNCls() < configGp.cfgITScluster) - // return false; + if (candidate.itsNCls() < configGp.cfgITScluster) + return false; if (candidate.tpcNClsFound() < configGp.cfgTPCcluster) return false; - // if (candidate.itsChi2NCl() >= configGp.cfgITSChi2NCl) - // return false; - // if (candidate.tpcChi2NCl() >= configGp.cfgTPCChi2NClMax || candidate.tpcChi2NCl() < configGp.cfgTPCChi2NClMin) - // return false; if (configGp.hasITS && !candidate.hasITS()) return false; if (configGp.isITSTPCRefit && (!(o2::aod::track::ITSrefit) || !(o2::aod::track::TPCrefit))) @@ -600,8 +597,8 @@ struct Kstarqa { return false; // if (candidate.tpcCrossedRowsOverFindableCls() < configGp.cfgRCRFC) return false; - // if (candidate.itsNCls() < configGp.cfgITScluster) - // return false; + if (candidate.itsNCls() < configGp.cfgITScluster) + return false; if (candidate.tpcNClsFound() < configGp.cfgTPCcluster) return false; // if (candidate.itsChi2NCl() >= configGp.cfgITSChi2NCl) @@ -617,19 +614,16 @@ struct Kstarqa { return true; } - // template - // bool isFakeTrack(const T& track, int PID) - // { - // const auto pglobal = track.p(); - // const auto ptpc = track.tpcInnerParam(); - // if (PID == 0 && std::abs(pglobal - ptpc) > cFakeTrackCutPi) { - // return true; - // } - // if (PID == 1 && std::abs(pglobal - ptpc) > cFakeTrackCutKa) { - // return true; - // } - // return false; - // } + template + bool isFakeTrack(const T& track) + { + const auto pglobal = track.p(); + const auto ptpc = track.tpcInnerParam(); + if (std::abs(pglobal - ptpc) > configGp.cFakeTrackCutKa) { + return true; + } + return false; + } // deep angle cut on pair to remove photon conversion template @@ -653,6 +647,34 @@ struct Kstarqa { return true; } + template + bool selectionPID2(const T& candidate, int PID) + { + float ptThreshold = 0.5; // GeV/c + if (PID == PIDParticle::kPion) { + if (candidate.pt() < ptThreshold && TMath::Abs(candidate.tpcNSigmaPi()) < configGp.nsigmaCutTPCPi) { + return true; + } + if (candidate.pt() >= ptThreshold && TMath::Abs(candidate.tpcNSigmaPi()) < configGp.nsigmaCutTPCPi && candidate.hasTOF() && (std::pow(candidate.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi, 2) + std::pow(candidate.tpcNSigmaPi(), 2)) < (std::pow(configGp.nsigmaCutCombinedPi, 2))) { + return true; + } + if (candidate.pt() >= ptThreshold && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < configGp.nsigmaCutTPCPi) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() < ptThreshold && TMath::Abs(candidate.tpcNSigmaKa()) < configGp.nsigmaCutTPCKa) { + return true; + } + if (candidate.pt() >= ptThreshold && candidate.hasTOF() && (std::pow(candidate.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, 2) + std::pow(candidate.tpcNSigmaKa(), 2)) < (std::pow(configGp.nsigmaCutCombinedKa, 2)) && candidate.beta() > configGp.cBetaCutTOFKaon) { + return true; + } + if (candidate.pt() >= ptThreshold && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < configGp.nsigmaCutTPCKa) { + return true; + } + } + return false; + } + template bool selectionPID(const T& candidate, int PID) { @@ -1156,45 +1178,39 @@ struct Kstarqa { } // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplyPID1 && !selectionPID(track1, 1)) // kaon + continue; + if (configGp.isapplyPID1 && !selectionPID(track2, 0)) // pion + continue; + + if (configGp.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPID(track2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPID && !selectionPIDPtDep(track2, 0)) // pion continue; - if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track1, 1)) // kaon continue; - if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track2, 0)) // pion continue; - if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplyPID2 && !selectionPID2(track1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track2, 0)) // Track 2 is checked with Pion + if (configGp.isapplyPID2 && !selectionPID2(track2, 0)) // pion continue; rEventSelection.fill(HIST("tracksCheckData"), 2.5); - // if (cFakeTrack && isFakeTrack(track1, 1)) // Kaon - // continue; - // if (cFakeTrack && isFakeTrack(track2, 0)) // Pion - // continue; + if (configGp.cFakeTrack && isFakeTrack(track1)) // Kaon + continue; rEventSelection.fill(HIST("tracksCheckData"), 3.5); - // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > configGp.ctrackRapidity) - // continue; rEventSelection.fill(HIST("tracksCheckData"), 4.5); if (configGp.isApplyParticleMID) { if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(track1, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(track2, 2)) // Pion misidentified as proton - // continue; } if (configGp.isApplyParticleMIDPtDep) { @@ -1223,10 +1239,18 @@ struct Kstarqa { hPID.fill(HIST("After/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, multiplicity, track1.pt()); hPID.fill(HIST("After/hTOFnsigPi_mult_pt"), track2.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi, multiplicity, track2.pt()); - hOthers.fill(HIST("hEta_after"), track1.eta()); - hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, track1.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi, track2.pt()); + hOthers.fill(HIST("hEta_after"), track1.eta()); + hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); + } + hOthers.fill(HIST("hTPCMomDiffKa"), track1.p() - track1.tpcInnerParam()); + hOthers.fill(HIST("hTPCMomDiffPi"), track2.p() - track2.tpcInnerParam()); } if (!selectionPair(track1, track2)) { @@ -1308,21 +1332,25 @@ struct Kstarqa { o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!selectionTrack(t1) || !selectionTrack(t2)) continue; - // if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) - // continue; - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPID(t1, 1)) // Track 1 is checked with Kaon + + if (configGp.isapplyPID1 && !selectionPID(t1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPID(t2, 0)) // Track 2 is checked with Pion + if (configGp.isapplyPID1 && !selectionPID(t2, 0)) // pion continue; - if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPIDPtDep(t1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPID && !selectionPIDPtDep(t1, 1)) // kaon continue; - if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !selectionPIDPtDep(t2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPID && !selectionPIDPtDep(t2, 0)) // pion continue; - if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t2, 0)) // pion + continue; + + if (configGp.isapplyPID2 && !selectionPID2(t1, 1)) // kaon + continue; + if (configGp.isapplyPID2 && !selectionPID2(t2, 0)) // pion continue; // if (std::abs(t1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) @@ -1331,10 +1359,8 @@ struct Kstarqa { // if (std::abs(t2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > configGp.ctrackRapidity) // continue; - // if (cFakeTrack && isFakeTrack(t1, 1)) // Kaon - // continue; - // if (cFakeTrack && isFakeTrack(t2, 0)) // Pion - // continue; + if (configGp.cFakeTrack && isFakeTrack(t1)) // Kaon + continue; if (configGp.isApplyParticleMID) { if (selectionMID(t1, 0)) // Kaon misidentified as pion @@ -1410,27 +1436,22 @@ struct Kstarqa { for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!selectionTrack(t1) || !selectionTrack(t2)) continue; - // if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) - // continue; - if (!configGp.isapplypTdepPID && !selectionPID(t1, 1)) // Track 1 is checked with Kaon + + if (configGp.isapplyPID1 && !selectionPID(t1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && !selectionPID(t2, 0)) // Track 2 is checked with Pion + if (configGp.isapplyPID1 && !selectionPID(t2, 0)) // pion continue; - if (configGp.isapplypTdepPID && !selectionPIDPtDep(t1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPID && !selectionPIDPtDep(t1, 1)) // kaon continue; - if (configGp.isapplypTdepPID && !selectionPIDPtDep(t2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPID && !selectionPIDPtDep(t2, 0)) // pion continue; if (configGp.isApplyParticleMID) { if (selectionMID(t1, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(t1, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(t2, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(t2, 2)) // Pion misidentified as proton - // continue; } if (configGp.isApplyParticleMIDPtDep) { @@ -1446,6 +1467,10 @@ struct Kstarqa { if (selectionMIDPtDep2(t2, 1)) // Pion misidentified as kaon continue; } + if (configGp.isapplyPID2 && !selectionPID2(t1, 1)) // kaon + continue; + if (configGp.isapplyPID2 && !selectionPID2(t2, 0)) // pion + continue; if (!t1.has_mcParticle() || !t2.has_mcParticle()) { continue; // skip if no MC particle associated @@ -1567,27 +1592,28 @@ struct Kstarqa { } // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion - if (!configGp.isapplypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplyPID1 && !selectionPID(track1, 1)) // kaon continue; - if (!configGp.isapplypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion + if (configGp.isapplyPID1 && !selectionPID(track2, 0)) // pion continue; rEventSelection.fill(HIST("tracksCheckData"), 3.5); - if (configGp.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // kaon continue; - if (configGp.isapplypTdepPID && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion + if (configGp.isapplypTdepPID && !selectionPIDPtDep(track2, 0)) // pion continue; rEventSelection.fill(HIST("tracksCheckData"), 4.5); + if (configGp.isapplyPID2 && !selectionPID2(track1, 1)) // kaon + continue; + if (configGp.isapplyPID2 && !selectionPID2(track2, 0)) // pion + continue; + if (configGp.isApplyParticleMID) { if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(track1, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(track2, 2)) // Pion misidentified as proton - // continue; } if (configGp.isApplyParticleMIDPtDep) { @@ -1611,10 +1637,8 @@ struct Kstarqa { // if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > configGp.ctrackRapidity) // continue; - // if (cFakeTrack && isFakeTrack(track1, 1)) // Kaon - // continue; - // if (cFakeTrack && isFakeTrack(track2, 0)) // Pion - // continue; + if (configGp.cFakeTrack && isFakeTrack(track1)) // Kaon + continue; rEventSelection.fill(HIST("tracksCheckData"), 6.5); if (cQAplots) { @@ -1635,6 +1659,12 @@ struct Kstarqa { // hPID.fill(HIST("After/hNsigmaPionTOF_after"), track2.pt(), track2.tofNSigmaPi()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, track1.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi, track2.pt()); + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); + } } if (configGp.isCheckMotherClosure) { @@ -2146,24 +2176,24 @@ struct Kstarqa { rEventSelection.fill(HIST("recMCparticles"), 11.5); if (track1PDG == PDG_t::kPiPlus) { - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + if (configGp.isapplyPID1 && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon continue; - } else if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon + } + if (configGp.isapplypTdepPID && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon continue; - } else if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon + } + if (configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon continue; } + if (configGp.isapplyPID2 && !selectionPID2(track2, 0)) // pion and kaon + continue; rEventSelection.fill(HIST("recMCparticles"), 12.5); if (configGp.isApplyParticleMID) { if (selectionMID(track2, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(track2, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(track1, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(track1, 2)) // Pion misidentified as proton - // continue; } if (configGp.isApplyParticleMIDPtDep) { @@ -2195,27 +2225,35 @@ struct Kstarqa { hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track2.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, multiplicity, track2.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_after"), track2.tpcNSigmaKa(), track2.tofNSigmaKa() - configGp.shiftInNsigmaTOFKa, track2.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track1.tpcNSigmaPi(), track1.tofNSigmaPi() - configGp.shiftInNsigmaTOFPi, track1.pt()); + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); + } } } else if (track1PDG == PDG_t::kKPlus) { - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // pion and kaon + if (configGp.isapplyPID1 && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // pion and kaon continue; - } else if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 0))) { // pion and kaon + } + if (configGp.isapplypTdepPID && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 0))) { // pion and kaon continue; - } else if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 1) && selectionPIDptDepTOF(track2, 0))) { // pion and kaon + } + if (configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 1) && selectionPIDptDepTOF(track2, 0))) { // pion and kaon continue; } + if (configGp.isapplyPID2 && !selectionPID2(track1, 1)) // kaon + continue; + if (configGp.isapplyPID2 && !selectionPID2(track2, 0)) // pion + continue; rEventSelection.fill(HIST("recMCparticles"), 12.5); if (configGp.isApplyParticleMID) { if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(track2, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(track1, 2)) // Pion misidentified as proton - // continue; } if (configGp.isApplyParticleMIDPtDep) { @@ -2249,13 +2287,6 @@ struct Kstarqa { } } - /* if (configGp.isApplyCutsOnMother) { - if (mothertrack1.pt() >= configGp.cMaxPtMotherCut) // excluding candidates in overflow - continue; - if ((std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())) >= configGp.cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } */ - if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { hInvMass.fill(HIST("h1KSRecsplit"), mothertrack1.pt()); continue; @@ -2435,24 +2466,26 @@ struct Kstarqa { } rEventSelection.fill(HIST("recMCparticles"), 10.5); - if (!configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + if (configGp.isapplyPID1 && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon continue; - } else if (configGp.isapplypTdepPID && !configGp.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon + } + if (configGp.isapplypTdepPID && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon continue; - } else if (!configGp.isapplypTdepPID && configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon + } + if (configGp.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon continue; } + if (configGp.isapplyPID2 && !selectionPID2(track1, 0)) + continue; + if (configGp.isapplyPID2 && !selectionPID2(track2, 1)) + continue; rEventSelection.fill(HIST("recMCparticles"), 11.5); if (configGp.isApplyParticleMID) { if (selectionMID(track1, 1)) // Pion misidentified as kaon continue; - // if (selectionMID(track1, 2)) // Kaon misidentified as proton - // continue; if (selectionMID(track2, 0)) // Kaon misidentified as pion continue; - // if (selectionMID(track2, 2)) // Pion misidentified as proton - // continue; } rEventSelection.fill(HIST("recMCparticles"), 12.5); @@ -2470,21 +2503,8 @@ struct Kstarqa { continue; } - // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > configGp.ctrackRapidity) - // continue; - rEventSelection.fill(HIST("recMCparticles"), 13.5); - /* if (configGp.isApplyCutsOnMother) { - if (mothertrack1.pt() >= configGp.cMaxPtMotherCut) // excluding candidates in overflow - continue; - if ((std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())) >= configGp.cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } */ - if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { hInvMass.fill(HIST("h1KSRecsplit"), mothertrack1.pt()); continue; @@ -2566,33 +2586,15 @@ struct Kstarqa { continue; if (cQAplots) { - // hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track1.pt(), track1.tpcNSigmaKa()); - // hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track1.pt(), track1.tofNSigmaKa()); - // hPID.fill(HIST("Before/hNsigmaTPC_Pi_before"), track2.pt(), track2.tpcNSigmaPi()); - // hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_before"), track2.tpcNSigmaPi(), track2.tofNSigmaPi(), track2.pt()); hPID.fill(HIST("Before/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); - // hPID.fill(HIST("Before/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); hPID.fill(HIST("Before/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); hPID.fill(HIST("Before/hTOFnsigPi_mult_pt"), track2.tofNSigmaPi(), multiplicity, track2.pt()); hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); - // hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); hOthers.fill(HIST("hphi"), track1.phi()); - - // if (track1.sign() < 0) { - // hPID.fill(HIST("Before/h1PID_TPC_neg_kaon"), track1.tpcNSigmaKa()); - // // hPID.fill(HIST("Before/h1PID_TPC_neg_pion"), track2.tpcNSigmaPi()); - // hPID.fill(HIST("Before/h1PID_TOF_neg_kaon"), track1.tofNSigmaKa()); - // // hPID.fill(HIST("Before/h1PID_TOF_neg_pion"), track2.tofNSigmaPi()); - // } else { - // hPID.fill(HIST("Before/h1PID_TPC_pos_kaon"), track1.tpcNSigmaKa()); - // // hPID.fill(HIST("Before/h1PID_TPC_pos_pion"), track2.tpcNSigmaPi()); - // hPID.fill(HIST("Before/h1PID_TOF_pos_kaon"), track1.tofNSigmaKa()); - // // hPID.fill(HIST("Before/h1PID_TOF_pos_pion"), track2.tofNSigmaPi()); - // } } if (cQAevents) { @@ -2601,60 +2603,33 @@ struct Kstarqa { } // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with kaon - if (!configGp.isapplypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (!configGp.isapplypTdepPID && !selectionPID(track1, 1)) // kaon continue; if (!configGp.isapplypTdepPID && !selectionPID(track2, 1)) // Track 2 is checked with kaon continue; - if (configGp.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (configGp.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // kaon continue; if (configGp.isapplypTdepPID && !selectionPIDPtDep(track2, 1)) // Track 2 is checked with kaon continue; rEventSelection.fill(HIST("tracksCheckData"), 2.5); - // if (cFakeTrack && isFakeTrack(track1, 1)) // Kaon - // continue; - // if (cFakeTrack && isFakeTrack(track2, 1)) // Pion - // continue; + if (configGp.cFakeTrack && isFakeTrack(track1)) // Kaon + continue; rEventSelection.fill(HIST("tracksCheckData"), 3.5); - - // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; rEventSelection.fill(HIST("tracksCheckData"), 4.5); - - /* if (configGp.isApplyParticleMID) { - if (selectionMID(track1, 0)) // Kaon misidentified as pion - continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton - continue; - if (selectionMID(track2, 0)) // Pion misidentified as pion - continue; - if (selectionMID(track2, 2)) // Pion misidentified as proton - continue; - } */ - rEventSelection.fill(HIST("tracksCheckData"), 5.5); if (cQAplots) { - // hPID.fill(HIST("After/hDcaxyPi"), track2.dcaXY()); hPID.fill(HIST("After/hDcaxyKa"), track1.dcaXY()); - // hPID.fill(HIST("After/hDcazPi"), track2.dcaZ()); hPID.fill(HIST("After/hDcazKa"), track1.dcaZ()); hPID.fill(HIST("After/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); - // hPID.fill(HIST("After/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); hPID.fill(HIST("After/hTOFnsigPi_mult_pt"), track2.tofNSigmaPi(), multiplicity, track2.pt()); hOthers.fill(HIST("hEta_after"), track1.eta()); hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); - // hPID.fill(HIST("After/hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); - // hPID.fill(HIST("After/hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); - // hPID.fill(HIST("After/hNsigmaPionTPC_after"), track2.pt(), track2.tpcNSigmaPi()); - // hPID.fill(HIST("After/hNsigmaPionTOF_after"), track2.pt(), track2.tofNSigmaPi()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi(), track2.pt()); } @@ -2668,13 +2643,6 @@ struct Kstarqa { daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); mother = daughter1 + daughter2; // Phi meson - /* if (configGp.isApplyCutsOnMother) { - if (mother.Pt() >= configGp.cMaxPtMotherCut) // excluding candidates in overflow - continue; - if (mother.M() >= configGp.cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } */ - if (cQAplots) { hOthers.fill(HIST("hKstar_rap_pt"), mother.Rapidity(), mother.Pt()); hOthers.fill(HIST("hKstar_eta_pt"), mother.Eta(), mother.Pt()); @@ -2708,28 +2676,6 @@ struct Kstarqa { if (!selectionPID(t1, 1) || !selectionPID(t2, 1)) continue; - // if (std::abs(t1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (std::abs(t2.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (cFakeTrack && isFakeTrack(t1, 1)) // Kaon - // continue; - // if (cFakeTrack && isFakeTrack(t2, 1)) // Kaon - // continue; - - /* if (configGp.isApplyParticleMID) { - if (selectionMID(t1, 0)) // Kaon misidentified as pion - continue; - if (selectionMID(t1, 2)) // Kaon misidentified as proton - continue; - if (selectionMID(t2, 0)) // Pion misidentified as pion - continue; - if (selectionMID(t2, 2)) // Pion misidentified as proton - continue; - } */ - if (!selectionPair(t1, t2)) { continue; } @@ -2846,13 +2792,6 @@ struct Kstarqa { continue; } - /* if (configGp.isApplyCutsOnMother) { - if (mcParticle.pt() >= configGp.cMaxPtMotherCut) // excluding candidates in overflow - continue; - if ((std::sqrt(mcParticle.e() * mcParticle.e() - mcParticle.p() * mcParticle.p())) >= configGp.cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } */ - if (std::abs(mcParticle.pdgCode()) != o2::constants::physics::kPhi) { continue; } @@ -3143,39 +3082,13 @@ struct Kstarqa { continue; } rEventSelection.fill(HIST("recMCparticles"), 12.5); - - /* if (configGp.isApplyParticleMID) { - if (selectionMID(track1, 0)) // Kaon misidentified as pion - continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton - continue; - if (selectionMID(track2, 0)) // Kaon misidentified as pion - continue; - if (selectionMID(track2, 2)) // Kaon misidentified as proton - continue; - } */ rEventSelection.fill(HIST("recMCparticles"), 13.5); - - // if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; - - // if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > configGp.ctrackRapidity) - // continue; rEventSelection.fill(HIST("recMCparticles"), 14.5); if (cQAplots) { hPID.fill(HIST("After/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); - // hPID.fill(HIST("After/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); - // hPID.fill(HIST("After/hTOFnsigPi_mult_pt"), track2.tofNSigmaPi(), multiplicity, track2.pt()); } - /* if (configGp.isApplyCutsOnMother) { - if (mothertrack1.pt() >= configGp.cMaxPtMotherCut) // excluding candidates in overflow - continue; - if ((std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())) >= configGp.cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } */ - if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { hInvMass.fill(HIST("h1KSRecsplit"), mothertrack1.pt()); continue; From a410b2ded83f88270479fc3d6b9dfbe858c3a26f Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Tue, 26 May 2026 19:34:28 +0200 Subject: [PATCH 290/449] [PWGLF] Finer binning for the DCA histograms in nucleiUtils (#16392) --- PWGLF/Utils/nucleiUtils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Utils/nucleiUtils.h b/PWGLF/Utils/nucleiUtils.h index bce4b560dda..f389b6bfaec 100644 --- a/PWGLF/Utils/nucleiUtils.h +++ b/PWGLF/Utils/nucleiUtils.h @@ -441,8 +441,8 @@ void createHistogramRegistryNucleus(o2::framework::HistogramRegistry& registry) registry.add(fmt::format("{}/hPtReconstructed", cNames[index]).c_str(), (fmt::format("{} - reconstructed variables;", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); Counts")).c_str(), o2::framework::HistType::kTH1F, {{400, -10.0f, 10.0f}}); registry.add(fmt::format("{}/h2PtVsCentralityReconstructed", cNames[index]).c_str(), (fmt::format("{} - reconstructed variables;", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH2F, {{400, -10.0f, 10.0f}, {20, 0.0f, 100.0f}}); registry.add(fmt::format("{}/h3PhiVsEtaVsCentralityReconstructed", cNames[index]).c_str(), (fmt::format("{} - reconstructed variables;", cNames[index]) + std::string("#phi (radians); #eta; CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH3F, {{40, 0, o2::constants::math::TwoPI}, {40, -1.0f, 1.f}, {20, 0.0f, 100.0f}}); - registry.add(fmt::format("{}/h3DCAxyVsPtVsCentrality", cNames[index]).c_str(), (fmt::format(";", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); DCA_{xy} (cm); CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH3F, {{400, -10.0f, 10.0f}, {200, -0.5f, 0.5f}, {20, 0.0f, 100.0f}}); - registry.add(fmt::format("{}/h3DCAzVsPtVsCentrality", cNames[index]).c_str(), (fmt::format("{};", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); DCA_{z} (cm); CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH3F, {{400, -10.0f, 10.0f}, {200, -0.5f, 0.5f}, {20, 0.0f, 100.0f}}); + registry.add(fmt::format("{}/h3DCAxyVsPtVsCentrality", cNames[index]).c_str(), (fmt::format(";", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); DCA_{xy} (cm); CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH3F, {{400, -10.0f, 10.0f}, {400, -0.1f, 0.1f}, {20, 0.0f, 100.0f}}); + registry.add(fmt::format("{}/h3DCAzVsPtVsCentrality", cNames[index]).c_str(), (fmt::format("{};", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c}); DCA_{z} (cm); CentralityFT0C (%)")).c_str(), o2::framework::HistType::kTH3F, {{400, -10.0f, 10.0f}, {400, -0.1f, 0.1f}, {20, 0.0f, 100.0f}}); registry.add(fmt::format("{}/h3NsigmaTPC_preselectionVsCentrality", cNames[index]).c_str(), (fmt::format("Nsigma{} TPC distribution;", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c});") + fmt::format("n#sigma_{{TPC}}({}); CentralityFT0C (%)", cNames[index])).c_str(), o2::framework::HistType::kTH3F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}, {20, 0.0f, 100.0f}}); registry.add(fmt::format("{}/h3NsigmaTPCVsCentrality", cNames[index]).c_str(), (fmt::format("Nsigma{} TPC distribution;", cNames[index]) + std::string("#it{p}_{T} / |#it{Z}| (GeV/#it{c});") + fmt::format("n#sigma_{{TPC}}({}); Centrality FT0C (%)", cNames[index])).c_str(), o2::framework::HistType::kTH3F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}, {20, 0.0f, 100.0f}}); registry.add(fmt::format("{}/h3NsigmaITS_preselectionVsCentrality", cNames[index]).c_str(), (fmt::format("Nsigma{} ITS distribution;", cNames[index]) + std::string("signed #it{p}_{T} / |#it{Z}| (GeV/#it{c});") + fmt::format("n#sigma_{{ITS}}({}); Centrality FT0C (%)", cNames[index])).c_str(), o2::framework::HistType::kTH3F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}, {20, 0.0f, 100.0f}}); From a153da31326bc1a41069a8b0b1976a4813134443 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 26 May 2026 19:35:06 +0200 Subject: [PATCH 291/449] [PWGLF] Add tree producer for coalescence studies (#16390) --- PWGLF/TableProducer/Nuspex/CMakeLists.txt | 5 + .../Nuspex/coalescenceTreeProducer.cxx | 673 ++++++++++++++++++ 2 files changed, 678 insertions(+) create mode 100644 PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index 1d3c88d03fa..40ac3c39879 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -123,3 +123,8 @@ o2physics_add_dpl_workflow(photon-deuteron SOURCES photonDeuteron.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(coalescence-tree-producer + SOURCES coalescenceTreeProducer.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx new file mode 100644 index 00000000000..ad1e91f18ff --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx @@ -0,0 +1,673 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file coalescenceTreeProducer.cxx +/// \brief Tree producer for deuteron, triton, helium-3, and hypertriton +/// coalescence studies. +/// +/// The task loops over generated MC particles and builds bound-state +/// candidates according to the selected species. For each candidate, +/// the constituent particles are boosted to the candidate rest frame, +/// propagated to a common time, and used to compute the Jacobi relative +/// momenta. +/// +/// Candidate triplets/pairs are stored in a reduced tree if: +/// - p_rho < pRhoMax +/// - p_lambda < pLambdaMax (for three-body coalescence only) +/// +/// The output tree stores the kinematic and space-time coordinates of +/// the constituent baryons for offline coalescence studies. +/// +/// \author Alberto Calivà + +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/InitContext.h" +#include "Framework/Logger.h" +#include "Framework/OutputObjHeader.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +struct CoalescenceTreeProducer { + + // Supported bound-state species + enum BoundStateSpecies { + kDeuteron = 0, + kTriton = 1, + kHelium3 = 2, + kHypertriton = 3 + }; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Analysis parameters + Configurable zVtx{"zVtx", 10.f, "Maximum |z vertex| in cm"}; + Configurable etaMax{"etaMax", 1.5f, "Maximum |eta| for generated particles"}; + Configurable pRhoMax{"pRhoMax", 1.0f, "Maximum Jacobi p_rho in GeV/c"}; + Configurable pLambdaMax{"pLambdaMax", 1.0f, "Maximum Jacobi p_lambda in GeV/c"}; + Configurable boundStateSpecies{"boundStateSpecies", kHypertriton, "Species selector: 0 = deuteron, 1 = triton, 2 = helium3, 3 = hypertriton"}; + + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + + OutputObj treeBoundState{"treeBoundState"}; + + int64_t eventID; // Event ID + int64_t idB1, idB2, idB3; // MC particle IDs of the constituent baryons + + int pdgB1, pdgB2, pdgB3; + int chargeB1, chargeB2, chargeB3; + + // Space-time coordinates and momentum components of the constituent baryons in the lab frame + float xB1, yB1, zB1, tB1, pxB1, pyB1, pzB1; + float xB2, yB2, zB2, tB2, pxB2, pyB2, pzB2; + float xB3, yB3, zB3, tB3, pxB3, pyB3, pzB3; + + static constexpr double MassP = o2::constants::physics::MassProton; + static constexpr double MassN = o2::constants::physics::MassNeutron; + static constexpr double MassL = o2::constants::physics::MassLambda0; + + struct Particle { + int64_t id; + int pdg; + int charge; + float x; + float y; + float z; + float t; + float px; + float py; + float pz; + float mass; + }; + + void init(InitContext&) + { + registry.add("eventCounter", "event Counter", HistType::kTH1F, {{5, 0, 5, "counter"}}); + registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(1, "Before z-vertex cut"); + registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(2, "After z-vertex cut"); + registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(3, "After non-empty lists"); + + // Tree for pairs/triplets. + // For deuterons only the first two baryons are stored. + // For three-body states, the third-baryon branches are also created. + treeBoundState->Branch("eventID", &eventID); + + treeBoundState->Branch("idB1", &idB1); + treeBoundState->Branch("idB2", &idB2); + + treeBoundState->Branch("pdgB1", &pdgB1); + treeBoundState->Branch("pdgB2", &pdgB2); + + treeBoundState->Branch("chargeB1", &chargeB1); + treeBoundState->Branch("chargeB2", &chargeB2); + + treeBoundState->Branch("xB1", &xB1); + treeBoundState->Branch("yB1", &yB1); + treeBoundState->Branch("zB1", &zB1); + treeBoundState->Branch("tB1", &tB1); + treeBoundState->Branch("pxB1", &pxB1); + treeBoundState->Branch("pyB1", &pyB1); + treeBoundState->Branch("pzB1", &pzB1); + + treeBoundState->Branch("xB2", &xB2); + treeBoundState->Branch("yB2", &yB2); + treeBoundState->Branch("zB2", &zB2); + treeBoundState->Branch("tB2", &tB2); + treeBoundState->Branch("pxB2", &pxB2); + treeBoundState->Branch("pyB2", &pyB2); + treeBoundState->Branch("pzB2", &pzB2); + + if (static_cast(boundStateSpecies) != kDeuteron) { + treeBoundState->Branch("idB3", &idB3); + treeBoundState->Branch("pdgB3", &pdgB3); + treeBoundState->Branch("chargeB3", &chargeB3); + + treeBoundState->Branch("xB3", &xB3); + treeBoundState->Branch("yB3", &yB3); + treeBoundState->Branch("zB3", &zB3); + treeBoundState->Branch("tB3", &tB3); + treeBoundState->Branch("pxB3", &pxB3); + treeBoundState->Branch("pyB3", &pyB3); + treeBoundState->Branch("pzB3", &pzB3); + } + } + + int chargeFromPdg(int pdg) const + { + int charge(0); + if (pdg == PDG_t::kProton) { + charge = 1; + } + if (pdg == PDG_t::kProtonBar) { + charge = -1; + } + return charge; + } + + double massFromPdg(int pdg) const + { + switch (std::abs(pdg)) { + case PDG_t::kProton: + return MassP; + case PDG_t::kNeutron: + return MassN; + case PDG_t::kLambda0: + return MassL; + default: + return -1.; + } + } + + template + Particle makeParticle(T const& p) + { + const int pdg = p.pdgCode(); + return {p.globalIndex(), + pdg, + chargeFromPdg(pdg), + p.vx(), + p.vy(), + p.vz(), + p.vt(), + p.px(), + p.py(), + p.pz(), + static_cast(massFromPdg(pdg))}; + } + + ROOT::Math::PxPyPzMVector makeFourVector(Particle const& p) + { + return ROOT::Math::PxPyPzMVector{p.px, p.py, p.pz, p.mass}; + } + + void storePair(Particle const& b1, Particle const& b2) + { + idB1 = b1.id; + idB2 = b2.id; + + pdgB1 = b1.pdg; + pdgB2 = b2.pdg; + + chargeB1 = b1.charge; + chargeB2 = b2.charge; + + xB1 = b1.x; + yB1 = b1.y; + zB1 = b1.z; + tB1 = b1.t; + pxB1 = b1.px; + pyB1 = b1.py; + pzB1 = b1.pz; + + xB2 = b2.x; + yB2 = b2.y; + zB2 = b2.z; + tB2 = b2.t; + pxB2 = b2.px; + pyB2 = b2.py; + pzB2 = b2.pz; + + treeBoundState->Fill(); + } + + void storeTriplet(Particle const& b1, Particle const& b2, Particle const& b3) + { + idB1 = b1.id; + idB2 = b2.id; + idB3 = b3.id; + + pdgB1 = b1.pdg; + pdgB2 = b2.pdg; + pdgB3 = b3.pdg; + + chargeB1 = b1.charge; + chargeB2 = b2.charge; + chargeB3 = b3.charge; + + xB1 = b1.x; + yB1 = b1.y; + zB1 = b1.z; + tB1 = b1.t; + pxB1 = b1.px; + pyB1 = b1.py; + pzB1 = b1.pz; + + xB2 = b2.x; + yB2 = b2.y; + zB2 = b2.z; + tB2 = b2.t; + pxB2 = b2.px; + pyB2 = b2.py; + pzB2 = b2.pz; + + xB3 = b3.x; + yB3 = b3.y; + zB3 = b3.z; + tB3 = b3.t; + pxB3 = b3.px; + pyB3 = b3.py; + pzB3 = b3.pz; + + treeBoundState->Fill(); + } + + bool passTwoBodySkim(Particle const& b1, Particle const& b2) + { + auto p4B1 = makeFourVector(b1); + auto p4B2 = makeFourVector(b2); + + auto candidate = p4B1 + p4B2; + + // BoostToCM() returns the boost vector needed to go from the lab frame + // to the candidate center-of-mass frame. + auto betaCandidate = candidate.BoostToCM(); + ROOT::Math::Boost boostToRest(betaCandidate); + + auto p4B1Star = boostToRest(p4B1); + auto p4B2Star = boostToRest(p4B2); + + /* + // Space-time propagation block. + // Not needed for the present skim because the selection is based only on + // the relative momentum pRho in the candidate rest frame. + // + // This block can be re-enabled later if one wants to apply coordinate-space + // or full phase-space coalescence selections, e.g. cuts on relative distance + // after propagation to a common time. + + ROOT::Math::XYZTVector x4B1{b1.x, b1.y, b1.z, b1.t}; + ROOT::Math::XYZTVector x4B2{b2.x, b2.y, b2.z, b2.t}; + + auto x4B1Star = boostToRest(x4B1); + auto x4B2Star = boostToRest(x4B2); + + const double tMax = std::max(x4B1Star.T(), x4B2Star.T()); + + ROOT::Math::XYZVector rB1{x4B1Star.X(), x4B1Star.Y(), x4B1Star.Z()}; + ROOT::Math::XYZVector rB2{x4B2Star.X(), x4B2Star.Y(), x4B2Star.Z()}; + + ROOT::Math::XYZVector vB1 = p4B1Star.Vect() / p4B1Star.E(); + ROOT::Math::XYZVector vB2 = p4B2Star.Vect() / p4B2Star.E(); + + rB1 += vB1 * (tMax - x4B1Star.T()); + rB2 += vB2 * (tMax - x4B2Star.T()); + */ + + const ROOT::Math::XYZVector pB1Star = p4B1Star.Vect(); + const ROOT::Math::XYZVector pB2Star = p4B2Star.Vect(); + + const double m12 = b1.mass + b2.mass; + + ROOT::Math::XYZVector pRho = (b2.mass * pB1Star - b1.mass * pB2Star) / m12; + + if (pRho.R() > pRhoMax) { + return false; + } + return true; + } + + bool passThreeBodySkim(Particle const& b1, Particle const& b2, Particle const& b3) + { + auto p4B1 = makeFourVector(b1); + auto p4B2 = makeFourVector(b2); + auto p4B3 = makeFourVector(b3); + + auto candidate = p4B1 + p4B2 + p4B3; + + // BoostToCM() returns the boost vector needed to go from the lab frame + // to the candidate center-of-mass frame. + auto betaCandidate = candidate.BoostToCM(); + ROOT::Math::Boost boostToRest(betaCandidate); + + auto p4B1Star = boostToRest(p4B1); + auto p4B2Star = boostToRest(p4B2); + auto p4B3Star = boostToRest(p4B3); + + /* + // Space-time propagation block. + // Not needed for the present skim because the selection is based only on + // the Jacobi relative momenta pRho and pLambda in the candidate rest frame. + // + // This block can be re-enabled later if one wants to apply coordinate-space + // or full phase-space coalescence selections, e.g. cuts on relative distances + // after propagation to a common time. + + ROOT::Math::XYZTVector x4B1{b1.x, b1.y, b1.z, b1.t}; + ROOT::Math::XYZTVector x4B2{b2.x, b2.y, b2.z, b2.t}; + ROOT::Math::XYZTVector x4B3{b3.x, b3.y, b3.z, b3.t}; + + auto x4B1Star = boostToRest(x4B1); + auto x4B2Star = boostToRest(x4B2); + auto x4B3Star = boostToRest(x4B3); + + const double tMax = std::max({x4B1Star.T(), x4B2Star.T(), x4B3Star.T()}); + + ROOT::Math::XYZVector rB1{x4B1Star.X(), x4B1Star.Y(), x4B1Star.Z()}; + ROOT::Math::XYZVector rB2{x4B2Star.X(), x4B2Star.Y(), x4B2Star.Z()}; + ROOT::Math::XYZVector rB3{x4B3Star.X(), x4B3Star.Y(), x4B3Star.Z()}; + + ROOT::Math::XYZVector vB1 = p4B1Star.Vect() / p4B1Star.E(); + ROOT::Math::XYZVector vB2 = p4B2Star.Vect() / p4B2Star.E(); + ROOT::Math::XYZVector vB3 = p4B3Star.Vect() / p4B3Star.E(); + + rB1 += vB1 * (tMax - x4B1Star.T()); + rB2 += vB2 * (tMax - x4B2Star.T()); + rB3 += vB3 * (tMax - x4B3Star.T()); + */ + + const ROOT::Math::XYZVector pB1Star = p4B1Star.Vect(); + const ROOT::Math::XYZVector pB2Star = p4B2Star.Vect(); + const ROOT::Math::XYZVector pB3Star = p4B3Star.Vect(); + + const double m12 = b1.mass + b2.mass; + const double mTot = b1.mass + b2.mass + b3.mass; + + ROOT::Math::XYZVector pRho = (b2.mass * pB1Star - b1.mass * pB2Star) / m12; + ROOT::Math::XYZVector pLambda = (b3.mass * (pB1Star + pB2Star) - m12 * pB3Star) / mTot; + + if (pRho.R() > pRhoMax) { + return false; + } + + if (pLambda.R() > pLambdaMax) { + return false; + } + + return true; + } + + void buildPairs(std::vector const& b1Candidates, + std::vector const& b2Candidates) + { + if (b1Candidates.empty() || b2Candidates.empty()) { + return; + } + + for (const auto& b1 : b1Candidates) { + for (const auto& b2 : b2Candidates) { + if (!passTwoBodySkim(b1, b2)) { + continue; + } + + storePair(b1, b2); + } + } + } + + void buildTriplets(std::vector const& b1Candidates, + std::vector const& b2Candidates, + std::vector const& b3Candidates, + bool identicalB1B2 = false, + bool identicalB2B3 = false) + { + if (b1Candidates.empty() || b2Candidates.empty() || b3Candidates.empty()) { + return; + } + + if (identicalB1B2) { + for (size_t iB1 = 0; iB1 < b1Candidates.size(); ++iB1) { + for (size_t iB2 = iB1 + 1; iB2 < b2Candidates.size(); ++iB2) { + for (const auto& b3 : b3Candidates) { + const auto& b1 = b1Candidates[iB1]; + const auto& b2 = b2Candidates[iB2]; + + if (!passThreeBodySkim(b1, b2, b3)) { + continue; + } + + storeTriplet(b1, b2, b3); + } + } + } + return; + } + + if (identicalB2B3) { + for (const auto& b1 : b1Candidates) { + for (size_t iB2 = 0; iB2 < b2Candidates.size(); ++iB2) { + for (size_t iB3 = iB2 + 1; iB3 < b3Candidates.size(); ++iB3) { + const auto& b2 = b2Candidates[iB2]; + const auto& b3 = b3Candidates[iB3]; + + if (!passThreeBodySkim(b1, b2, b3)) { + continue; + } + + storeTriplet(b1, b2, b3); + } + } + } + return; + } + + for (const auto& b1 : b1Candidates) { + for (const auto& b2 : b2Candidates) { + for (const auto& b3 : b3Candidates) { + if (!passThreeBodySkim(b1, b2, b3)) { + continue; + } + + storeTriplet(b1, b2, b3); + } + } + } + } + + template + void selectGeneratedParticles(McParticles const& mcParticlesThisMcColl, + std::vector& protons, + std::vector& antiProtons, + std::vector& neutrons, + std::vector& antiNeutrons, + std::vector& lambdas, + std::vector& antiLambdas) + { + for (const auto& particle : mcParticlesThisMcColl) { + if (!particle.isPhysicalPrimary()) { + continue; + } + + if (std::fabs(particle.eta()) > etaMax) { + continue; + } + + const int pdg = particle.pdgCode(); + + if (pdg == PDG_t::kProton) { + protons.push_back(makeParticle(particle)); + } else if (pdg == PDG_t::kProtonBar) { + antiProtons.push_back(makeParticle(particle)); + } else if (pdg == PDG_t::kNeutron) { + neutrons.push_back(makeParticle(particle)); + } else if (pdg == PDG_t::kNeutronBar) { + antiNeutrons.push_back(makeParticle(particle)); + } else if (pdg == PDG_t::kLambda0) { + lambdas.push_back(makeParticle(particle)); + } else if (pdg == PDG_t::kLambda0Bar) { + antiLambdas.push_back(makeParticle(particle)); + } + } + } + + void fillDeuteron(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) + { + // Deuteron: p + n + buildPairs(protons, neutrons); + + // anti-deuteron: anti-p + anti-n + buildPairs(antiProtons, antiNeutrons); + } + + void fillHelium3(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) + { + // 3He: p + p + n + buildTriplets(protons, protons, neutrons, true, false); + + // anti-3He: anti-p + anti-p + anti-n + buildTriplets(antiProtons, antiProtons, antiNeutrons, true, false); + } + + void fillTriton(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) + { + // Triton: p + n + n + buildTriplets(protons, neutrons, neutrons, false, true); + + // anti-triton: anti-p + anti-n + anti-n + buildTriplets(antiProtons, antiNeutrons, antiNeutrons, false, true); + } + + void fillHypertriton(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons, + std::vector const& lambdas, + std::vector const& antiLambdas) + { + // Hypertriton: p + n + Lambda + buildTriplets(protons, neutrons, lambdas); + + // anti-hypertriton: anti-p + anti-n + anti-Lambda + buildTriplets(antiProtons, antiNeutrons, antiLambdas); + } + + bool hasDeuteronCandidates(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) const + { + return (!protons.empty() && !neutrons.empty()) || + (!antiProtons.empty() && !antiNeutrons.empty()); + } + + bool hasHelium3Candidates(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) const + { + constexpr std::size_t minimumSizeContainer = 2; + return (protons.size() >= minimumSizeContainer && !neutrons.empty()) || + (antiProtons.size() >= minimumSizeContainer && !antiNeutrons.empty()); + } + + bool hasTritonCandidates(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons) const + { + constexpr std::size_t minimumSizeContainer = 2; + return (!protons.empty() && neutrons.size() >= minimumSizeContainer) || + (!antiProtons.empty() && antiNeutrons.size() >= minimumSizeContainer); + } + + bool hasHypertritonCandidates(std::vector const& protons, + std::vector const& antiProtons, + std::vector const& neutrons, + std::vector const& antiNeutrons, + std::vector const& lambdas, + std::vector const& antiLambdas) const + { + return (!protons.empty() && !neutrons.empty() && !lambdas.empty()) || + (!antiProtons.empty() && !antiNeutrons.empty() && !antiLambdas.empty()); + } + + void processCoalescence(aod::McCollision const& collision, aod::McParticles const& mcParticles) + { + registry.fill(HIST("eventCounter"), 0.5); + + if (std::fabs(collision.posZ()) > zVtx) { + return; + } + + registry.fill(HIST("eventCounter"), 1.5); + + eventID = collision.globalIndex(); + + std::vector protons; + std::vector antiProtons; + std::vector neutrons; + std::vector antiNeutrons; + std::vector lambdas; + std::vector antiLambdas; + + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + + selectGeneratedParticles(mcParticlesThisMcColl, + protons, + antiProtons, + neutrons, + antiNeutrons, + lambdas, + antiLambdas); + + switch (boundStateSpecies) { + case kDeuteron: + if (!hasDeuteronCandidates(protons, antiProtons, neutrons, antiNeutrons)) { + return; + } + registry.fill(HIST("eventCounter"), 2.5); + fillDeuteron(protons, antiProtons, neutrons, antiNeutrons); + break; + case kHelium3: + if (!hasHelium3Candidates(protons, antiProtons, neutrons, antiNeutrons)) { + return; + } + registry.fill(HIST("eventCounter"), 2.5); + fillHelium3(protons, antiProtons, neutrons, antiNeutrons); + break; + case kTriton: + if (!hasTritonCandidates(protons, antiProtons, neutrons, antiNeutrons)) { + return; + } + registry.fill(HIST("eventCounter"), 2.5); + fillTriton(protons, antiProtons, neutrons, antiNeutrons); + break; + case kHypertriton: + if (!hasHypertritonCandidates(protons, antiProtons, neutrons, antiNeutrons, lambdas, antiLambdas)) { + return; + } + registry.fill(HIST("eventCounter"), 2.5); + fillHypertriton(protons, antiProtons, neutrons, antiNeutrons, lambdas, antiLambdas); + break; + default: + LOGF(fatal, "Unknown boundStateSpecies=%d. Use 0 = deuteron, 1 = triton, 2 = helium3, 3 = hypertriton", static_cast(boundStateSpecies)); + } + } + PROCESS_SWITCH(CoalescenceTreeProducer, processCoalescence, "process coalescence", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 4343494e96c58e43017a420757b03490d5deac02 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Tue, 26 May 2026 19:40:15 +0200 Subject: [PATCH 292/449] [Common] Add interaction rate histograms (#16399) --- Common/Tasks/centralityStudy.cxx | 40 ++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/Common/Tasks/centralityStudy.cxx b/Common/Tasks/centralityStudy.cxx index 892756cc68e..298a7e57eaf 100644 --- a/Common/Tasks/centralityStudy.cxx +++ b/Common/Tasks/centralityStudy.cxx @@ -244,6 +244,7 @@ struct centralityStudy { histos.add("hNGlobalTracks", "hNGlobalTracks", kTH1D, {axisMultUltraFineGlobalTracks}); histos.add("hNMFTTracks", "hNMFTTracks", kTH1D, {axisMultUltraFineMFTTracks}); histos.add("hNPVContributors", "hNPVContributors", kTH1D, {axisMultUltraFinePVContributors}); + histos.add("hInteractionRate", "hInteractionRate", kTH1D, {axisInteractionRate}); histos.add("hFT0CvsPVz_Collisions", "hFT0CvsPVz_Collisions", kTProfile, {axisPVz}); histos.add("hFT0AvsPVz_Collisions", "hFT0AvsPVz_Collisions", kTProfile, {axisPVz}); @@ -332,6 +333,8 @@ struct centralityStudy { histos.add("hFT0A_BCs", "hFT0A_BCs", kTH1D, {axisMultUltraFineFT0A}); histos.add("hFT0M_BCs", "hFT0M_BCs", kTH1D, {axisMultUltraFineFT0M}); histos.add("hFV0A_BCs", "hFV0A_BCs", kTH1D, {axisMultUltraFineFV0A}); + histos.add("hInteractionRate_BCs", "hInteractionRate_BCs", kTH1D, {axisInteractionRate}); + histos.add("hFV0AT0C_BCs", "hFV0AT0C_BCs", kTH1D, {axisMultUltraFineFV0AT0C}); histos.add("hScaledFT0M_BCs", "hScaledFT0M_BCs", kTH1D, {axisMultUltraFineScaledFT0M}); histos.add("hScaledFV0AT0C_BCs", "hScaledFV0AT0C_BCs", kTH1D, {axisMultUltraFineScaledFV0AT0C}); @@ -494,6 +497,7 @@ struct centralityStudy { histPointers.insert({histPath + "hPVzProfileCoVsTime", histos.add((histPath + "hPVzProfileCoVsTime").c_str(), "hPVzProfileCoVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); histPointers.insert({histPath + "hPVzProfileBcVsTime", histos.add((histPath + "hPVzProfileBcVsTime").c_str(), "hPVzProfileBcVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); histPointers.insert({histPath + "hIRProfileVsTime", histos.add((histPath + "hIRProfileVsTime").c_str(), "hIRProfileVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); + histPointers.insert({histPath + "hInteractionRate", histos.add((histPath + "hInteractionRate").c_str(), "hInteractionRate", {kTH1D, {{axisInteractionRate}}})}); } } @@ -861,24 +865,26 @@ struct centralityStudy { if constexpr (requires { collision.has_multBC(); }) { if (collision.has_multBC()) { - initRun(collision); auto multbc = collision.template multBC_as(); uint64_t bcTimestamp = multbc.timestamp(); - const float hoursAfterStartOfRun = static_cast(bcTimestamp - startOfRunTimestamp) / 3600000.0; const float interactionRate = mRateFetcher.fetch(ccdb.service, bcTimestamp, mRunNumber, irSource.value, irCrashOnNull) / 1000.; // kHz - - if (studies.doTimeStudies && studies.doRunByRunHistograms) { - getHist(TH2, histPath + "hFT0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0A()); - getHist(TH2, histPath + "hFT0CVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0C()); - getHist(TH2, histPath + "hFT0MVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0M()); - getHist(TH2, histPath + "hFV0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0A()); - getHist(TH2, histPath + "hFV0AOuterVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0AOuter()); - getHist(TH2, histPath + "hMFTTracksVsTime")->Fill(hoursAfterStartOfRun, collision.mftNtracks()); - getHist(TH2, histPath + "hNGlobalVsTime")->Fill(hoursAfterStartOfRun, collision.multNTracksGlobal()); - getHist(TH2, histPath + "hNTPVContributorsVsTime")->Fill(hoursAfterStartOfRun, collision.multPVTotalContributors()); - getHist(TProfile, histPath + "hPVzProfileCoVsTime")->Fill(hoursAfterStartOfRun, collision.multPVz()); - getHist(TProfile, histPath + "hPVzProfileBcVsTime")->Fill(hoursAfterStartOfRun, multbc.multFT0PosZ()); - getHist(TProfile, histPath + "hIRProfileVsTime")->Fill(hoursAfterStartOfRun, interactionRate); + histos.fill(HIST("hInteractionRate"), interactionRate); + if (studies.doRunByRunHistograms) { + getHist(TH1, histPath + "hInteractionRate")->Fill(interactionRate); + if (studies.doTimeStudies) { + const float hoursAfterStartOfRun = static_cast(bcTimestamp - startOfRunTimestamp) / 3600000.0; + getHist(TH2, histPath + "hFT0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0A()); + getHist(TH2, histPath + "hFT0CVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0C()); + getHist(TH2, histPath + "hFT0MVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0M()); + getHist(TH2, histPath + "hFV0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0A()); + getHist(TH2, histPath + "hFV0AOuterVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0AOuter()); + getHist(TH2, histPath + "hMFTTracksVsTime")->Fill(hoursAfterStartOfRun, collision.mftNtracks()); + getHist(TH2, histPath + "hNGlobalVsTime")->Fill(hoursAfterStartOfRun, collision.multNTracksGlobal()); + getHist(TH2, histPath + "hNTPVContributorsVsTime")->Fill(hoursAfterStartOfRun, collision.multPVTotalContributors()); + getHist(TProfile, histPath + "hPVzProfileCoVsTime")->Fill(hoursAfterStartOfRun, collision.multPVz()); + getHist(TProfile, histPath + "hPVzProfileBcVsTime")->Fill(hoursAfterStartOfRun, multbc.multFT0PosZ()); + getHist(TProfile, histPath + "hIRProfileVsTime")->Fill(hoursAfterStartOfRun, interactionRate); + } } } } @@ -1007,6 +1013,10 @@ struct centralityStudy { histos.fill(HIST("hFV0A_BCs"), multbc.multFV0A() * scale.factorFV0A); histos.fill(HIST("hFV0AT0C_BCs"), (multbc.multFV0A() + multbc.multFT0C()) * scale.factorFV0AT0C); + uint64_t bcTimestamp = multbc.timestamp(); + const float interactionRate = mRateFetcher.fetch(ccdb.service, bcTimestamp, mRunNumber, irSource.value, irCrashOnNull) / 1000.; // kHz + histos.fill(HIST("hInteractionRate_BCs"), interactionRate); + if (studies.do2DPlots) { histos.fill(HIST("hFT0AVsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multFT0A() * scale.factorFT0A); histos.fill(HIST("hFV0AVsFT0C_BCs"), multbc.multFT0C() * scale.factorFT0C, multbc.multFV0A() * scale.factorFV0A); From e9978ffc8c11bc049e1a066fe5f0bc55600e6e5d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 26 May 2026 19:51:29 +0200 Subject: [PATCH 293/449] [PWGEM/Dilepton] update event table for taggingHFE (#16401) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 2 +- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 8f6cac72a92..1aa3463ad14 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -201,7 +201,7 @@ DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of } // namespace emmlevent DECLARE_SOA_TABLE(EMMLEvents, "AOD", "EMMLEVENT", //! - o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange); + o2::soa::Index<>, collision::Chi2, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange); // iterators using EMMLEvent = EMMLEvents::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 0b25521a7b6..35713b58593 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -2549,7 +2549,7 @@ struct taggingHFE { } // end of main electron sample if (npos + nele > 0) { // fill eventTable only if at least 1 electron or positron exists. - eventTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + eventTable(collision.chi2(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); } electronIds.clear(); From 0bf7b88258a2a3d7820a009fca20bb739e91ed25 Mon Sep 17 00:00:00 2001 From: tutripat <73981392+tutripat@users.noreply.github.com> Date: Tue, 26 May 2026 20:05:28 +0200 Subject: [PATCH 294/449] [PWGLF] Updating event cut (#16379) Co-authored-by: ALICE Action Bot --- .../PseudorapidityDensityMFT.cxx | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx index c548d6a45fa..c765142dbac 100644 --- a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx @@ -119,7 +119,6 @@ static constexpr TrackSelectionFlags::flagtype TrackSelectionDca = // using MFTTracksLabeled = soa::Join; // replace your alias with the extension included: using FullBCs = soa::Join; - using MFTTracksLabeled = soa::Join useEvSel{"useEvSel", true, "use event selection"}; Configurable useNoSameBunchPileup{"useNoSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable useGoodItsLayersAll{"useGoodItsLayersAll", true, "all ITS layers are in a good state"}; Configurable useNoCollInRofStandard{"useNoCollInRofStandard", true, "Require evsel::kNoCollInRofStrict in processGenReco"}; Configurable useNoCollInRofStrict{"useNoCollInRofStrict", true, "Require evsel::kNoCollInRofStrict in processGenReco"}; Configurable useNoCollInTimeRangeStrict{"useNoCollInTimeRangeStrict", true, "Require evsel::kNoCollInTimeRangeStrict in processGenReco"}; @@ -511,6 +512,7 @@ struct PseudorapidityDensityMFT { auto* x = h->GetXaxis(); x->SetBinLabel(static_cast(GenRecoCutBin::AllRecoCollisions), "All reco collisions (loop entry)"); x->SetBinLabel(static_cast(GenRecoCutBin::RctMFT), "myChecker (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::UseGoodItsLayersAll), "kIsGoodItsLayersAll"); x->SetBinLabel(static_cast(GenRecoCutBin::UseContBestCollisionIndex), "useContBestcollisionIndex"); x->SetBinLabel(static_cast(GenRecoCutBin::HasMcCollision), "has_mcCollision()"); x->SetBinLabel(static_cast(GenRecoCutBin::VzWindow), "Vz window"); @@ -2175,12 +2177,6 @@ struct PseudorapidityDensityMFT { } fillGenRecoCut(step.bin); } - - if (useRctMFT && !myChecker(collision)) { - return false; - } - fillGenRecoCut(GenRecoCutBin::RctMFT); - return true; }; @@ -2194,6 +2190,17 @@ struct PseudorapidityDensityMFT { } fillGenRecoCut(GenRecoCutBin::HasMcCollision); + if (useRctMFT && !myChecker(collision)) { + continue; + } + fillGenRecoCut(GenRecoCutBin::RctMFT); + + if (useGoodItsLayersAll && + !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + fillGenRecoCut(GenRecoCutBin::UseGoodItsLayersAll); + registry.fill(HIST("Purity/reco/CollisionNumContrib"), collision.numContrib()); if (useCont && collision.globalIndex() != mcCollision.bestCollisionIndex()) { @@ -2487,6 +2494,12 @@ struct PseudorapidityDensityMFT { } fillGenRecoCut(GenRecoCutBin::RctMFT); + if (useGoodItsLayersAll && + !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + fillGenRecoCut(GenRecoCutBin::UseGoodItsLayersAll); + registry.fill(HIST("Purity/reco/CollisionNumContrib"), collision.numContrib()); if (useCont && collision.globalIndex() != mcCollision.bestCollisionIndex()) { From 6275ea912308a381ed018d248ec996543abedcdc Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Wed, 27 May 2026 03:38:35 +0800 Subject: [PATCH 295/449] [PWGCF] flowDirectedFlowTask.cxx: update to BCsWithTimestamps (#16366) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/CMakeLists.txt | 2 +- PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx | 39 +++++++---------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index 0f5f97f64fb..64f235e7337 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -114,7 +114,7 @@ o2physics_add_dpl_workflow(pid-flow-pt-corr PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(flow-gpol-ese +o2physics_add_dpl_workflow(flow-directed-flow-task SOURCES flowDirectedFlowTask.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx index 28f32417010..253174ef5bb 100644 --- a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx +++ b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx @@ -146,7 +146,6 @@ struct flowDirectedFlowTask { using EventCandidates = soa::Filtered>; using AllTrackCandidates = soa::Filtered>; using ResoV0s = aod::V0Datas; - using BCsRun3 = soa::Join; void init(InitContext&) { @@ -222,17 +221,6 @@ struct flowDirectedFlowTask { histos.add("hSparseAntiLambdaAvgUyQ1", "AntiLambda vs q1", HistType::kTHnSparseF, axesPolSPQ1, true); } - float getPhiInRange(float phi) - { - while (phi <= -o2::constants::math::PI) { - phi += o2::constants::math::TwoPI; - } - while (phi > o2::constants::math::PI) { - phi -= o2::constants::math::TwoPI; - } - return phi; - } - template bool eventSelected(TCollision collision) { @@ -388,9 +376,6 @@ struct flowDirectedFlowTask { if (std::abs(v0.yLambda()) > cfgV0Rap) { return false; } - if (std::abs(v0.eta()) > 0.8) { - return false; - } return true; } @@ -439,12 +424,12 @@ struct flowDirectedFlowTask { const float cosThetaStar = daughterStar.Pz() / daughterStar.P(); const float sinThetaStar = std::sqrt(std::max(0.0, 1.0 - cosThetaStar * cosThetaStar)); - const float sinPhiStar = std::sin(getPhiInRange(phiStar)); - const float cosPhiStar = std::cos(getPhiInRange(phiStar)); + const float sinPhiStar = std::sin(phiStar); + const float cosPhiStar = std::cos(phiStar); - float polEP_A = std::sin(getPhiInRange(phiStar - psiA)); - float polEP_C = std::sin(getPhiInRange(phiStar - psiC)); - float polEP = std::sin(getPhiInRange(phiStar - psiFull)); + float polEP_A = std::sin(phiStar - psiA); + float polEP_C = std::sin(phiStar - psiC); + float polEP = std::sin(phiStar - psiFull); const float qxFull = qxC - qxA; const float qyFull = qyC - qyA; @@ -464,8 +449,8 @@ struct flowDirectedFlowTask { polEP_A /= accDen; polEP_C /= accDen; - const float cosPsi = std::cos(getPhiInRange(psiFull)); - const float sinPsi = std::sin(getPhiInRange(psiFull)); + const float cosPsi = std::cos(psiFull); + const float sinPsi = std::sin(psiFull); if (isLambda) { histos.fill(HIST("hSparseLambdaPolSPQ1"), mass, v0.pt(), polSP, centrality, q1, wgt); @@ -502,7 +487,7 @@ struct flowDirectedFlowTask { } } - void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& tracks, ResoV0s const& v0s, BCsRun3 const&) + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& tracks, ResoV0s const& v0s, aod::BCsWithTimestamps const&) { if (!eventSelected(collision)) { return; @@ -539,7 +524,7 @@ struct flowDirectedFlowTask { float dotAC = qxA * qxC + qyA * qyC; float resDot = dotAC / (magA * magC); - histos.fill(HIST("hpResCosAC"), centrality, std::cos(getPhiInRange(psiA - psiC))); + histos.fill(HIST("hpResCosAC"), centrality, std::cos(psiA - psiC)); histos.fill(HIST("hpResDotAC"), centrality, resDot); histos.fill(HIST("hpQxAQxC"), centrality, qxA * qxC); histos.fill(HIST("hpQyAQyC"), centrality, qyA * qyC); @@ -563,9 +548,9 @@ struct flowDirectedFlowTask { histos.fill(HIST("hV1SPAQ1"), centrality, track.pt(), track.eta(), q1, v1SPA); histos.fill(HIST("hV1SPCQ1"), centrality, track.pt(), track.eta(), q1, v1SPC); - histos.fill(HIST("hV1EPFullQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiFull))); - histos.fill(HIST("hV1EPAQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiA))); - histos.fill(HIST("hV1EPCQ1"), centrality, track.pt(), track.eta(), q1, std::cos(getPhiInRange(phi - psiC))); + histos.fill(HIST("hV1EPFullQ1"), centrality, track.pt(), track.eta(), q1, std::cos(phi - psiFull)); + histos.fill(HIST("hV1EPAQ1"), centrality, track.pt(), track.eta(), q1, std::cos(phi - psiA)); + histos.fill(HIST("hV1EPCQ1"), centrality, track.pt(), track.eta(), q1, std::cos(phi - psiC)); } for (const auto& v0 : v0s) { From fee4bd8123aaba10f3d063fa8c6bf50f47a3f7c9 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 26 May 2026 22:19:27 +0200 Subject: [PATCH 296/449] [PWGEM/Dilepton] put pair.pt back in taggingHFE (#16402) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 9 +++++---- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 24 ++++++++++++------------ PWGEM/Dilepton/Utils/SemiCharmTag.h | 4 ++++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 1aa3463ad14..a211af95777 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -259,7 +259,8 @@ DECLARE_SOA_COLUMN(V0Type, v0Type, uint8_t); //! v0 type, 0 = K0S, 1 = DECLARE_SOA_COLUMN(CascadeType, cascadeType, uint8_t); //! cascade type, 0 = XiMunus, 1 = OmegaMinus // LH pair variables -DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming pion +DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming kaon +DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pt of LH DECLARE_SOA_COLUMN(PtSVL, ptSVL, float); //! pT of lepton at SV DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV @@ -304,7 +305,7 @@ DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! // pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, // pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, @@ -318,7 +319,7 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, @@ -332,7 +333,7 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 35713b58593..fb5f97b5260 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1762,7 +1762,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -1823,7 +1823,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -1902,7 +1902,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -1965,7 +1965,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2033,7 +2033,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2101,7 +2101,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2198,7 +2198,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -2260,7 +2260,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -2338,7 +2338,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2401,7 +2401,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2469,7 +2469,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2537,7 +2537,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index a174ca3fedc..10aa317ec58 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -35,6 +35,7 @@ namespace o2::aod::pwgem::dilepton::utils struct LHPair { // struct to store electron-hadron pair information float mass{-999.f}; + float pt{-999.f}; float dca2legs{-999.f}; float cospa{-999.f}; float cospaXY{-999.f}; @@ -167,6 +168,7 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton ROOT::Math::PxPyPzMVector v2(pvec1[0], pvec1[1], pvec1[2], o2::constants::physics::MassKaonCharged); ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); + pair.pt = v12.Pt(); // float tmp = v12.P() * std::sin(std::acos(pair.cospa)); // LOGF(info, "pair.ptFD = %f, tmp = %f", pair.ptFD, tmp); @@ -293,6 +295,7 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); + pair.pt = v12.Pt(); pair.isOK = true; return pair; @@ -420,6 +423,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); + pair.pt = v12.Pt(); pair.isOK = true; return pair; From 8a09cd21dee376635affdd1357bb9d553db07f90 Mon Sep 17 00:00:00 2001 From: Zoltan Varga <91464454+zovarga@users.noreply.github.com> Date: Tue, 26 May 2026 16:34:36 -0400 Subject: [PATCH 297/449] [PWGJE] improve Lund plane MC collision handling and pthard weighting (#16367) --- PWGJE/Tasks/jetLundPlane.cxx | 85 +++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/PWGJE/Tasks/jetLundPlane.cxx b/PWGJE/Tasks/jetLundPlane.cxx index 69c3af0fe1c..ade6f2ed3b9 100644 --- a/PWGJE/Tasks/jetLundPlane.cxx +++ b/PWGJE/Tasks/jetLundPlane.cxx @@ -55,8 +55,14 @@ namespace o2::aod { // Parent table: one row per collision stored in the MiniAOD DECLARE_SOA_COLUMN(MiniCollTag, miniCollTag, uint8_t); +DECLARE_SOA_COLUMN(MiniCollMcCollisionId, miniCollMcCollisionId, int64_t); +DECLARE_SOA_COLUMN(MiniCollWeight, miniCollWeight, float); +DECLARE_SOA_COLUMN(MiniCollPtHard, miniCollPtHard, float); DECLARE_SOA_TABLE(MiniCollisions, "AOD", "MINICOLL", - MiniCollTag); + MiniCollTag, + MiniCollMcCollisionId, + MiniCollWeight, + MiniCollPtHard); // MiniJets -> MiniCollisions DECLARE_SOA_INDEX_COLUMN_CUSTOM(MiniCollision, miniCollision, "MINICOLLS"); @@ -148,6 +154,12 @@ struct JetMatchInfo { float otherPt{}; }; +struct McEventInfo { + int64_t mcCollisionId{-1}; + float weight{1.f}; + float ptHard{-1.f}; +}; + inline float deltaPhi(float phi1, float phi2) { return RecoDecay::constrainAngle(phi1 - phi2, -o2::constants::math::PI); @@ -405,6 +417,9 @@ struct JetLundPlaneUnfolding { (aod::jet::eta < jetEtaMax.node()) && (aod::jet::r == nround(jetR.node() * 100.f)); + // Reconstructed collisions grouped by their associated MC collision. + PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; + // Type aliases using RecoJets = soa::Join; using DetJetsMatched = soa::Join(0)); + outMiniCollisions(static_cast(0), int64_t{-1}, 1.f, -1.f); miniCollIdx = outMiniCollisions.lastIndex(); } for (auto const& jet : jets) { @@ -559,9 +574,10 @@ struct JetLundPlaneUnfolding { // MC PROCESSING (det + part + response) - void processMC(DetJetsMatched const& detJets, - PartJetsMatched const& partJets, - aod::JetCollisions const&, + void processMC(soa::Filtered const& detJets, + soa::Filtered const& partJets, + soa::Filtered const& collisions, + aod::JetMcCollisions const& mcCollisions, aod::JetTracks const& tracks, aod::JetParticles const& particles) { @@ -571,6 +587,7 @@ struct JetLundPlaneUnfolding { std::unordered_map truthMatchedById; std::unordered_map> truthSplittingsById; std::unordered_map truthBestDet; + std::unordered_set acceptedTruthJetKeys; std::unordered_set detSplittingsWritten; std::unordered_set truthSplittingsWritten; auto h6 = registry.get(HIST("hLundResponse6D")); @@ -583,6 +600,21 @@ struct JetLundPlaneUnfolding { std::unordered_map detJetToMiniJetIdx; std::unordered_map partJetToMiniJetIdx; + std::unordered_map mcEventInfoById; + for (auto const& mcCollision : mcCollisions) { + const int64_t mcCollisionId = mcCollision.globalIndex(); + mcEventInfoById.emplace(mcCollisionId, + McEventInfo{mcCollisionId, mcCollision.weight(), mcCollision.ptHard()}); + } + + std::unordered_map mcEventInfoByDetCollisionId; + for (auto const& collision : collisions) { + auto mcInfoIt = mcEventInfoById.find(collision.mcCollisionId()); + if (mcInfoIt != mcEventInfoById.end()) { + mcEventInfoByDetCollisionId.emplace(collision.globalIndex(), mcInfoIt->second); + } + } + // --- Truth pass --- // Fill inclusive truth histograms, cache truth splittings, write all accepted // truth jets to MiniJets, and determine the best detector candidate for each truth jet. @@ -591,10 +623,22 @@ struct JetLundPlaneUnfolding { continue; } + auto collisionsPerMCPJet = collisions.sliceBy(CollisionsPerMCPCollision, partJet.mcCollisionId()); + if (collisionsPerMCPJet.size() < 1) { + continue; + } + + auto partMcInfoIt = mcEventInfoById.find(partJet.mcCollisionId()); + if (partMcInfoIt == mcEventInfoById.end()) { + continue; + } + const auto partMcInfo = partMcInfoIt->second; + registry.fill(HIST("hJetPtTruthAll"), partJet.pt()); fillJetCountSummary(4); const uint64_t truthJetKey = partJet.globalIndex(); + acceptedTruthJetKeys.insert(truthJetKey); auto spl = getPrimarySplittings(partJet, particles); truthSplittingsById[truthJetKey] = spl; @@ -607,7 +651,7 @@ struct JetLundPlaneUnfolding { int partMiniCollIdx = -1; auto collIt = partMiniCollByKey.find(partCollKey); if (collIt == partMiniCollByKey.end()) { - outMiniCollisions(static_cast(0)); + outMiniCollisions(static_cast(0), partMcInfo.mcCollisionId, partMcInfo.weight, partMcInfo.ptHard); partMiniCollIdx = outMiniCollisions.lastIndex(); partMiniCollByKey.emplace(partCollKey, partMiniCollIdx); } else { @@ -629,7 +673,7 @@ struct JetLundPlaneUnfolding { JetMatchInfo bestDet{}; bool foundDet = false; - for (auto const& candDetJet : partJet.template matchedJetGeo_as()) { + for (auto const& candDetJet : partJet.template matchedJetGeo_as>()) { if (!passJetFiducial(candDetJet, rWanted)) { continue; } @@ -659,13 +703,19 @@ struct JetLundPlaneUnfolding { } // --- Detector loop --- - // Write all accepted detector jets to MiniJets. A final matched pair is accepted only + // Write accepted detector jets to MiniJets. A final matched pair is accepted only // if the detector jet and truth jet are mutual best matches under the same cuts. for (auto const& detJet : detJets) { if (!passJetFiducial(detJet, rWanted)) { continue; } + auto detMcInfoIt = mcEventInfoByDetCollisionId.find(detJet.collisionId()); + if (detMcInfoIt == mcEventInfoByDetCollisionId.end()) { + continue; + } + const auto detMcInfo = detMcInfoIt->second; + registry.fill(HIST("hJetPtRecoAll"), detJet.pt()); fillJetCountSummary(1); @@ -680,7 +730,7 @@ struct JetLundPlaneUnfolding { int detMiniCollIdx = -1; auto collIt = detMiniCollByKey.find(detCollKey); if (collIt == detMiniCollByKey.end()) { - outMiniCollisions(static_cast(0)); + outMiniCollisions(static_cast(0), detMcInfo.mcCollisionId, detMcInfo.weight, detMcInfo.ptHard); detMiniCollIdx = outMiniCollisions.lastIndex(); detMiniCollByKey.emplace(detCollKey, detMiniCollIdx); } else { @@ -706,7 +756,12 @@ struct JetLundPlaneUnfolding { bool foundMatch = false; std::vector bestPartSpl; - for (auto const& candPartJet : detJet.template matchedJetGeo_as()) { + for (auto const& candPartJet : detJet.template matchedJetGeo_as>()) { + const uint64_t candTruthKey = candPartJet.globalIndex(); + if (acceptedTruthJetKeys.find(candTruthKey) == acceptedTruthJetKeys.end()) { + continue; + } + if (!passJetFiducial(candPartJet, rWanted)) { continue; } @@ -723,7 +778,6 @@ struct JetLundPlaneUnfolding { } if (!foundMatch || dR < bestTruth.dR) { - const uint64_t candTruthKey = candPartJet.globalIndex(); bestTruth.otherKey = candTruthKey; bestTruth.dR = dR; bestTruth.relPt = rel; @@ -813,6 +867,15 @@ struct JetLundPlaneUnfolding { continue; } + auto collisionsPerMCPJet = collisions.sliceBy(CollisionsPerMCPCollision, partJet.mcCollisionId()); + if (collisionsPerMCPJet.size() < 1) { + continue; + } + + if (mcEventInfoById.find(partJet.mcCollisionId()) == mcEventInfoById.end()) { + continue; + } + const uint64_t truthJetKey = partJet.globalIndex(); if (!truthMatchedById[truthJetKey]) { registry.fill(HIST("hJetPtTruthMiss"), partJet.pt()); From e8117ac5308221f0e9904d0b6288cbb7e4ec3692 Mon Sep 17 00:00:00 2001 From: Roberta Ferioli <142217183+Roberta-Ferioli@users.noreply.github.com> Date: Wed, 27 May 2026 01:43:23 +0200 Subject: [PATCH 298/449] [PWGCF] Add task for TrackTrackCascade analysis (#16371) Co-authored-by: ALICE Action Bot --- PWGCF/Femto/Core/closeTripletRejection.h | 73 ++++ PWGCF/Femto/Core/tripletBuilder.h | 284 ++++++++++++++++ PWGCF/Femto/Core/tripletCleaner.h | 43 +++ PWGCF/Femto/Core/tripletHistManager.h | 3 + PWGCF/Femto/Tasks/CMakeLists.txt | 5 + .../Tasks/femtoTripletTrackTrackCascade.cxx | 312 ++++++++++++++++++ 6 files changed, 720 insertions(+) create mode 100644 PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx diff --git a/PWGCF/Femto/Core/closeTripletRejection.h b/PWGCF/Femto/Core/closeTripletRejection.h index dd1bd0182c0..0e05c865a6f 100644 --- a/PWGCF/Femto/Core/closeTripletRejection.h +++ b/PWGCF/Femto/Core/closeTripletRejection.h @@ -46,6 +46,21 @@ constexpr char PrefixTrack2V0Se[] = "CPR_Track2V0/SE/"; constexpr char PrefixTrack1V0Me[] = "CPR_Track1V0/ME/"; constexpr char PrefixTrack2V0Me[] = "CPR_Track2V0/ME/"; +constexpr char PrefixTrack1CascadeSe[] = "CPR_Track1Cascade/SE/"; +constexpr char PrefixTrack2CascadeSe[] = "CPR_Track2Cascade/SE/"; +constexpr char PrefixTrack1CascadeMe[] = "CPR_Track1Cascade/ME/"; +constexpr char PrefixTrack2CascadeMe[] = "CPR_Track2Cascade/ME/"; + +constexpr char PrefixTrack1V0DaughterSe[] = "CPR_Track1V0Dau/SE/"; +constexpr char PrefixTrack2V0DaughterSe[] = "CPR_Track2V0Dau/SE/"; +constexpr char PrefixTrack1V0DaughterMe[] = "CPR_Track1V0Dau/ME/"; +constexpr char PrefixTrack2V0DaughterMe[] = "CPR_Track2V0Dau/ME/"; + +constexpr char PrefixTrack1CascadeBachelorSe[] = "CPR_Track1CascadeBachelor/SE/"; +constexpr char PrefixTrack2CascadeBachelorSe[] = "CPR_TrackCascadeBachelor/SE/"; +constexpr char PrefixTrack1CascadeBachelorMe[] = "CPR_TrackCascadeBachelor/ME/"; +constexpr char PrefixTrack2CascadeBachelorMe[] = "CPR_TrackCascadeBachelor/ME/"; + template @@ -151,6 +166,64 @@ class CloseTripletRejectionTrackTrackV0 closepairrejection::ClosePairRejectionTrackV0 mCtrTrack2V0; }; +template +class CloseTripletRejectionTrackTrackCascade +{ + public: + CloseTripletRejectionTrackTrackCascade() = default; + ~CloseTripletRejectionTrackTrackCascade() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& specs, + std::map> const& specsBachelor, + std::map> const& specsV0Daughter, + T1 const& confCpr, + T2 const& confCprBachelor, + T3 const& confCprV0Daughter, + int absChargeTrack1, + int absChargeTrack2) + { + mCtrTrack12.init(registry, specs, confCpr, absChargeTrack1, absChargeTrack2); + mCtrTrack1Cascade.init(registry, specsBachelor, specsV0Daughter, confCprBachelor, confCprV0Daughter, absChargeTrack1); + mCtrTrack2Cascade.init(registry, specsBachelor, specsV0Daughter, confCprBachelor, confCprV0Daughter, absChargeTrack2); + } + + void setMagField(float magField) + { + mCtrTrack12.setMagField(magField); + mCtrTrack1Cascade.setMagField(magField); + mCtrTrack2Cascade.setMagField(magField); + } + template + void setTriplet(T1 const& track1, T2 const& track2, T3 const& cascade, T4 const& trackTable) + { + mCtrTrack12.setPair(track1, track2, trackTable); + mCtrTrack1Cascade.setPair(track1, cascade, trackTable); + mCtrTrack2Cascade.setPair(track2, cascade, trackTable); + } + bool isCloseTriplet() const + { + return mCtrTrack12.isClosePair() || mCtrTrack1Cascade.isClosePair() || mCtrTrack2Cascade.isClosePair(); + } + + void fill(float q3) + { + mCtrTrack12.fill(q3); + mCtrTrack1Cascade.fill(q3); + mCtrTrack2Cascade.fill(q3); + } + + private: + closepairrejection::ClosePairRejectionTrackTrack mCtrTrack12; + closepairrejection::ClosePairRejectionTrackCascade mCtrTrack1Cascade; + closepairrejection::ClosePairRejectionTrackCascade mCtrTrack2Cascade; +}; + }; // namespace closetripletrejection }; // namespace o2::analysis::femto #endif // PWGCF_FEMTO_CORE_CLOSETRIPLETREJECTION_H_ diff --git a/PWGCF/Femto/Core/tripletBuilder.h b/PWGCF/Femto/Core/tripletBuilder.h index 909934a1b69..427ec4fbb20 100644 --- a/PWGCF/Femto/Core/tripletBuilder.h +++ b/PWGCF/Femto/Core/tripletBuilder.h @@ -16,10 +16,12 @@ #ifndef PWGCF_FEMTO_CORE_TRIPLETBUILDER_H_ #define PWGCF_FEMTO_CORE_TRIPLETBUILDER_H_ +#include "PWGCF/Femto/Core/cascadeHistManager.h" #include "PWGCF/Femto/Core/closeTripletRejection.h" #include "PWGCF/Femto/Core/collisionHistManager.h" #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/Core/tripletCleaner.h" #include "PWGCF/Femto/Core/tripletHistManager.h" @@ -623,6 +625,288 @@ class TripletTrackTrackV0Builder std::uniform_int_distribution<> mDist; }; +template +class TripletTrackTrackCascadeBuilder +{ + public: + TripletTrackTrackCascadeBuilder() = default; + ~TripletTrackTrackCascadeBuilder() = default; + + template + + void init(o2::framework::HistogramRegistry* registry, + T1 const& confCollisionBinning, + T2 const& confTrackSelection1, + T3 const& confTrackSelection2, + T4 const& confTrackCleaner, + T5 const& confCtr, + T6 const& confCascadeSelection, + T7 const& confCascadeCleaner, + T8 const& confCprBachelor, + T9 const& confCprV0Daughter, + T10 const& confMixing, + T11 const& confTripletBinning, + T12 const& confTripletCuts, + std::map>& colHistSpec, + std::map>& trackHistSpec1, + std::map>& trackHistSpec2, + std::map>& cascadeHistSpec, + std::map>& bachelorHistSpec, + std::map>& posDauHistSpec, + std::map>& negDauHistSpec, + std::map>& tripletHistSpec, + std::map>& cprHistSpecBachelor, + std::map>& cprHistSpecV0Daughter, + std::map>& ctrHistSpec) + { + // check if correlate the same tracks or not + mTrack1Track2AreSameSpecies = confMixing.particle12AreSameSpecies.value; + + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); + mTripletHistManagerSe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); + mTripletHistManagerMe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); + + mTc.template init(confTripletCuts); + + if (mTrack1Track2AreSameSpecies) { + // Track1 & Track2 & are the same particle species and track 3 is something else + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mCascadeHistManager.template init(registry, cascadeHistSpec, confCascadeSelection, bachelorHistSpec, posDauHistSpec, negDauHistSpec); + + mTrackCleaner.init(confTrackCleaner); + mCascadeCleaner.init(confCascadeCleaner); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); + mCtrSe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); + mCtrMe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + } else { + // all three tracks are different + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mTrackHistManager2.template init(registry, trackHistSpec2, confTrackSelection2); + mCascadeHistManager.template init(registry, cascadeHistSpec, confCascadeSelection, bachelorHistSpec, posDauHistSpec, negDauHistSpec); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, 1); + mCtrSe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, 1); + mCtrMe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value); + } + + // setup mixing + mMixingPolicy = static_cast(confMixing.policy.value); + mMixingDepth = confMixing.depth.value; + + // setup rng if necessary + if (confMixing.seed.value >= 0) { + uint64_t randomSeed = 0; + mMixIdenticalParticles = true; + if (confMixing.seed.value == 0) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } else { + randomSeed = static_cast(confMixing.seed.value); + } + mRng = std::mt19937(randomSeed); + mDist = std::uniform_int_distribution<>(tripletprocesshelpers::kOrder123, tripletprocesshelpers::kOrder213); + } + } + + // data + template + void processSameEvent(T1 const& col, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto cascadeSlice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || cascadeSlice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, cascadeSlice, trackTable, col, mTrackHistManager1, mCascadeHistManager, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto cascadeSlice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || cascadeSlice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, cascadeSlice, trackTable, col, mTrackHistManager1, mTrackHistManager2, mCascadeHistManager, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + // mc + template + void processSameEvent(T1 const& col, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8 const& mcMothers, T9 const& mcPartonicMothers, T10& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto cascadeSlice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || cascadeSlice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, cascadeSlice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mCascadeHistManager, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto cascadeSlice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || cascadeSlice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, cascadeSlice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager2, mCascadeHistManager, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + template + void processMixedEvent(T1 const& cols, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache, T7& binsVtxMult, T8& binsVtxCent, T9& binsVtxMultCent) + { + if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8& cache, T9& binsVtxMult, T10& binsVtxCent, T11& binsVtxMultCent) + { + if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + private: + colhistmanager::CollisionHistManager mColHistManager; + trackhistmanager::TrackHistManager mTrackHistManager1; + trackhistmanager::TrackHistManager mTrackHistManager2; + cascadehistmanager::CascadeHistManager mCascadeHistManager; + particlecleaner::ParticleCleaner mTrackCleaner; + particlecleaner::ParticleCleaner mCascadeCleaner; + triplethistmanager::TripletHistManager mTripletHistManagerSe; + triplethistmanager::TripletHistManager mTripletHistManagerMe; + + closetripletrejection::CloseTripletRejectionTrackTrackCascade mCtrSe; + closetripletrejection::CloseTripletRejectionTrackTrackCascade mCtrMe; + tripletcleaner::TrackTrackCascadeTripletCleaner mTc; + triplethistmanager::MixingPolicy mMixingPolicy = triplethistmanager::MixingPolicy::kVtxMult; + bool mTrack1Track2AreSameSpecies = false; + int mMixingDepth = 5; + bool mMixIdenticalParticles = false; + std::mt19937 mRng; + std::uniform_int_distribution<> mDist; +}; + } // namespace tripletbuilder } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/tripletCleaner.h b/PWGCF/Femto/Core/tripletCleaner.h index d6f38c78709..a92b78eccc6 100644 --- a/PWGCF/Femto/Core/tripletCleaner.h +++ b/PWGCF/Femto/Core/tripletCleaner.h @@ -99,6 +99,49 @@ class TrackTrackV0TripletCleaner : public paircleaner::BasePairCleaner } }; +class TrackTrackCascadeTripletCleaner : public paircleaner::BasePairCleaner +{ + public: + TrackTrackCascadeTripletCleaner() = default; + ~TrackTrackCascadeTripletCleaner() = default; + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& cascade, T4 const& trackTable) const + { + auto bachelor = trackTable.rawIteratorAt(cascade.bachelorId() - trackTable.offset()); + auto posDaughter = trackTable.rawIteratorAt(cascade.posDauId() - trackTable.offset()); + auto negDaughter = trackTable.rawIteratorAt(cascade.negDauId() - trackTable.offset()); + return this->isCleanTrackPair(track1, track2) && + this->isCleanTrackPair(track1, posDaughter) && + this->isCleanTrackPair(track1, negDaughter) && + this->isCleanTrackPair(track1, bachelor) && + this->isCleanTrackPair(track2, posDaughter) && + this->isCleanTrackPair(track2, negDaughter) && + this->isCleanTrackPair(track2, bachelor); + } + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& cascade, T4 const& trackTable, T5 const& partonicMothers) const + { + if (!this->isCleanTriplet(track1, track2, cascade, trackTable)) { + return false; + } + // pair is clean + // no check if we require common or non-common ancestry + if (mMixPairsWithCommonAncestor) { + return this->pairHasCommonAncestor(track1, track2, partonicMothers) && + this->pairHasCommonAncestor(track1, cascade, partonicMothers) && + this->pairHasCommonAncestor(track2, cascade, partonicMothers); + } + if (mMixPairsWithNonCommonAncestor) { + return this->pairHasNonCommonAncestor(track1, track2, partonicMothers) && + this->pairHasNonCommonAncestor(track1, cascade, partonicMothers) && + this->pairHasNonCommonAncestor(track2, cascade, partonicMothers); + } + return true; + } +}; + } // namespace tripletcleaner } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/tripletHistManager.h b/PWGCF/Femto/Core/tripletHistManager.h index 8e6674f0c10..c6dba6ce17a 100644 --- a/PWGCF/Femto/Core/tripletHistManager.h +++ b/PWGCF/Femto/Core/tripletHistManager.h @@ -199,6 +199,9 @@ constexpr char PrefixTrackTrackTrackMe[] = "TrackTrackTrack/ME/"; constexpr char PrefixTrackTrackLambdaSe[] = "TrackTrackLambda/SE/"; constexpr char PrefixTrackTrackLambdaMe[] = "TrackTrackLambda/ME/"; +constexpr char PrefixTrackTrackCascadeSe[] = "TrackTrackCascade/SE/"; +constexpr char PrefixTrackTrackCascadeMe[] = "TrackTrackCascade/ME/"; + constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; constexpr std::string_view McDir = "MC/"; diff --git a/PWGCF/Femto/Tasks/CMakeLists.txt b/PWGCF/Femto/Tasks/CMakeLists.txt index e2069762030..9f213c0645b 100644 --- a/PWGCF/Femto/Tasks/CMakeLists.txt +++ b/PWGCF/Femto/Tasks/CMakeLists.txt @@ -78,3 +78,8 @@ o2physics_add_dpl_workflow(femto-triplet-track-track-v0 SOURCES femtoTripletTrackTrackV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-triplet-track-track-cascade + SOURCES femtoTripletTrackTrackCascade.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx b/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx new file mode 100644 index 00000000000..d37e4741cf2 --- /dev/null +++ b/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx @@ -0,0 +1,312 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoTripletTrackTrackCascade.cxx +/// \brief Tasks that computes correlation between two tracks and a cascade +/// \author Roberta Ferioli roberta.ferioli@cern.ch, Raffaele Del Grande raffaele.del.grande@cern.ch, CTU Prague + +#include "PWGCF/Femto/Core/cascadeBuilder.h" +#include "PWGCF/Femto/Core/cascadeHistManager.h" +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/closeTripletRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/particleCleaner.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/trackBuilder.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/tripletBuilder.h" +#include "PWGCF/Femto/Core/tripletHistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoTripletTrackTrackCascade { + + // setup tables + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; + + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + using FemtoTracks = o2::soa::Join; + using FemtoXis = o2::soa::Join; + using FemtoOmegas = o2::soa::Join; + + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoXisWithLabel = o2::soa::Join; + using FemtoOmegasWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup tracks + trackbuilder::ConfTrackSelection1 confTrackSelections1; + trackhistmanager::ConfTrackBinning1 confTrackBinning1; + trackbuilder::ConfTrackSelection2 confTrackSelections2; + trackhistmanager::ConfTrackBinning2 confTrackBinning2; + + o2::framework::Partition trackPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Preslice perColtracks = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition trackWithLabelPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackWithLabelPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; + + // setup for daughters + trackhistmanager::ConfCascadePosDauBinning confPosDauBinning; + trackhistmanager::ConfCascadeNegDauBinning confNegDauBinning; + trackhistmanager::ConfCascadeBachelorBinning confBachelorBinning; + + // setup xis + cascadebuilder::ConfXiSelection confXiSelection; + cascadehistmanager::ConfXiBinning confXiBinning; + particlecleaner::ConfXiCleaner1 confXiCleaner; + particlecleaner::ConfTrackCleaner1 confTrackCleaner1; + particlecleaner::ConfTrackCleaner2 confTrackCleaner2; + + o2::framework::Partition xiPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice perColXis = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition xiWithLabelPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice perColXisWithLabel = o2::aod::femtobase::stored::fColId; + + // setup omegas + cascadebuilder::ConfOmegaSelection confOmegaSelection; + cascadehistmanager::ConfOmegaBinning confOmegaBinning; + particlecleaner::ConfOmegaCleaner1 confOmegaCleaner; + + o2::framework::Partition omegaPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice perColOmegas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition omegaWithLabelPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice perColOmegasWithLabel = o2::aod::femtobase::stored::fColId; + + // setup triplets + triplethistmanager::ConfTripletBinning confTripletBinning; + triplethistmanager::ConfTripletCuts confTripletCuts; + + closetripletrejection::ConfCtrTrackTrackTrack confCtr; + + tripletbuilder::TripletTrackTrackCascadeBuilder< + modes::Cascade::kXi, + trackhistmanager::PrefixTrack1, + trackhistmanager::PrefixTrack2, + cascadehistmanager::PrefixXi, + trackhistmanager::PrefixCascadeBachelor, + trackhistmanager::PrefixCascadePosDaughter, + trackhistmanager::PrefixCascadeNegDaughter, + triplethistmanager::PrefixTrackTrackCascadeSe, + triplethistmanager::PrefixTrackTrackCascadeMe, + closetripletrejection::PrefixTrack1Track2Se, + closetripletrejection::PrefixTrack1CascadeBachelorSe, + closetripletrejection::PrefixTrack2CascadeBachelorSe, + closetripletrejection::PrefixTrack1V0DaughterSe, + closetripletrejection::PrefixTrack2V0DaughterSe, + closetripletrejection::PrefixTrack1Track2Me, + closetripletrejection::PrefixTrack1CascadeBachelorMe, + closetripletrejection::PrefixTrack2CascadeBachelorMe, + closetripletrejection::PrefixTrack1V0DaughterMe, + closetripletrejection::PrefixTrack2V0DaughterMe> + tripletTrackTrackXiBuilder; + + tripletbuilder::TripletTrackTrackCascadeBuilder< + modes::Cascade::kOmega, + trackhistmanager::PrefixTrack1, + trackhistmanager::PrefixTrack2, + cascadehistmanager::PrefixOmega, + trackhistmanager::PrefixCascadeBachelor, + trackhistmanager::PrefixCascadePosDaughter, + trackhistmanager::PrefixCascadeNegDaughter, + triplethistmanager::PrefixTrackTrackCascadeSe, + triplethistmanager::PrefixTrackTrackCascadeMe, + closetripletrejection::PrefixTrack1Track2Se, + closetripletrejection::PrefixTrack1CascadeBachelorSe, + closetripletrejection::PrefixTrack2CascadeBachelorSe, + closetripletrejection::PrefixTrack1V0DaughterSe, + closetripletrejection::PrefixTrack2V0DaughterSe, + closetripletrejection::PrefixTrack1Track2Me, + closetripletrejection::PrefixTrack1CascadeBachelorMe, + closetripletrejection::PrefixTrack2CascadeBachelorMe, + closetripletrejection::PrefixTrack1V0DaughterMe, + closetripletrejection::PrefixTrack2V0DaughterMe> + tripletTrackTrackOmegaBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + triplethistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoTrackTrackCascade", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + // setup cpr + closepairrejection::ConfCprTrackCascadeBachelor confCprBachelor; + closepairrejection::ConfCprTrackV0Daughter confCprV0Daughter; + + void init(o2::framework::InitContext&) + { + if ((doprocessXiSameEvent + doprocessXiSameEventMc) > 1 || (doprocessXiMixedEvent + doprocessXiMixedEventMc) > 1 || (doprocessOmegaSameEvent + doprocessOmegaSameEventMc) > 1 || (doprocessOmegaMixedEvent + doprocessOmegaMixedEventMc) > 1) { + LOG(fatal) << "More than 1 same or mixed event process function is activated. Breaking..."; + } + bool processData = doprocessXiSameEvent || doprocessXiMixedEvent || doprocessOmegaSameEvent || doprocessOmegaMixedEvent; + bool processMc = doprocessXiSameEventMc || doprocessXiMixedEventMc || doprocessOmegaSameEventMc || doprocessOmegaMixedEventMc; + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is activated. Breaking..."; + } + + bool processXi = doprocessXiSameEvent || doprocessXiSameEventMc || doprocessXiMixedEvent || doprocessXiMixedEventMc; + bool processOmega = doprocessOmegaSameEvent || doprocessOmegaSameEventMc || doprocessOmegaMixedEvent || doprocessOmegaMixedEventMc; + + if (processXi && processOmega) { + LOG(fatal) << "Both xi-track and omega-track processing is enabled. Breaking..."; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; + + // setup histogram specs + std::map> colHistSpec; + std::map> trackHistSpec1; + std::map> trackHistSpec2; + std::map> bachelorHistSpec; + + std::map> posDauSpec; + std::map> negDauSpec; + std::map> xiHistSpec; + std::map> omegaHistSpec; + std::map> tripletTrackTrackCascadeHistSpec; + + std::map> cprHistSpecBachelor = closepairrejection::makeCprHistSpecMap(confCprBachelor); + std::map> cprHistSpecV0Daughter = closepairrejection::makeCprHistSpecMap(confCprV0Daughter); + std::map> ctrHistSpec = closepairrejection::makeCprHistSpecMap(confCtr); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); + omegaHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confOmegaBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + tripletTrackTrackCascadeHistSpec = triplethistmanager::makeTripletHistSpecMap(confTripletBinning); + + if (processXi) { + xiHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confXiBinning); + tripletTrackTrackXiBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confCtr, confXiSelection, confXiCleaner, confCprBachelor, confCprV0Daughter, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, xiHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, tripletTrackTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, ctrHistSpec); + } else { + omegaHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confOmegaBinning); + tripletTrackTrackOmegaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confCtr, confOmegaSelection, confOmegaCleaner, confCprBachelor, confCprV0Daughter, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, omegaHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, tripletTrackTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, ctrHistSpec); + } + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning2); + bachelorHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confBachelorBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + tripletTrackTrackCascadeHistSpec = triplethistmanager::makeTripletMcHistSpecMap(confTripletBinning); + if (processXi) { + xiHistSpec = cascadehistmanager::makeCascadeMcHistSpecMap(confXiBinning); + tripletTrackTrackXiBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confCtr, confXiSelection, confXiCleaner, confCprBachelor, confCprV0Daughter, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, xiHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, tripletTrackTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, ctrHistSpec); + } else { + omegaHistSpec = cascadehistmanager::makeCascadeMcHistSpecMap(confOmegaBinning); + tripletTrackTrackOmegaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confCtr, confOmegaSelection, confOmegaCleaner, confCprBachelor, confCprV0Daughter, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, omegaHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, tripletTrackTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, ctrHistSpec); + } + } + hRegistry.print(); + }; + + void processXiSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoXis const& /*xis*/) + { + tripletTrackTrackXiBuilder.processSameEvent(col, tracks, trackPartition1, trackPartition2, xiPartition, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processXiSameEvent, "Enable processing same event processing for tracks and xis", true); + + void processXiSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + tripletTrackTrackXiBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, xiWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processXiSameEventMc, "Enable processing same event processing for tracks and xis with mc information", false); + + void processXiMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoXis const& /*xis*/) + { + tripletTrackTrackXiBuilder.processMixedEvent(cols, tracks, trackPartition1, trackPartition2, xiPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processXiMixedEvent, "Enable processing mixed event processing for tracks and xis", true); + + void processXiMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& /*mcMothers*/, o2::aod::FMcPartMoths const& /*mcPartonicMothers*/) + { + tripletTrackTrackXiBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, xiWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processXiMixedEventMc, "Enable processing mixed event processing for tracks and xis with mc information", false); + + void processOmegaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoOmegas const& /*omegas*/) + { + tripletTrackTrackOmegaBuilder.processSameEvent(col, tracks, trackPartition1, trackPartition2, omegaPartition, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processOmegaSameEvent, "Enable processing same event processing for tracks and omegas", false); + + void processOmegaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoOmegasWithLabel const& /*omegas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + tripletTrackTrackOmegaBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, omegaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processOmegaSameEventMc, "Enable processing same event processing for tracks and omegas with mc information", false); + + void processOmegaMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoOmegas const& /*omegas*/) + { + tripletTrackTrackOmegaBuilder.processMixedEvent(cols, tracks, trackPartition1, trackPartition2, omegaPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processOmegaMixedEvent, "Enable processing mixed event processing for tracks and omegas", false); + + void processOmegaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& /*mcMothers*/, o2::aod::FMcPartMoths const& /*mcPartonicMothers*/) + { + tripletTrackTrackOmegaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, omegaWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processOmegaMixedEventMc, "Enable processing mixed event processing for tracks and omegas with mc information", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From 11cf51e72ba78eecf454b1d4e5a9ecf947bab077 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 27 May 2026 06:49:47 +0200 Subject: [PATCH 299/449] [Common] CTP: avoid useless work to count non-zero bits (#16400) --- Common/CCDB/ctpRateFetcher.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Common/CCDB/ctpRateFetcher.cxx b/Common/CCDB/ctpRateFetcher.cxx index 6cf7213f2e7..eb5fcc38f3e 100644 --- a/Common/CCDB/ctpRateFetcher.cxx +++ b/Common/CCDB/ctpRateFetcher.cxx @@ -95,9 +95,7 @@ double ctpRateFetcher::pileUpCorrection(double triggerRate) if (mLHCIFdata == nullptr) { LOG(fatal) << "No filling" << std::endl; } - auto bfilling = mLHCIFdata->getBunchFilling(); - std::vector bcs = bfilling.getFilledBCs(); - double nbc = bcs.size(); + double nbc = mLHCIFdata->getBunchFilling().getPattern().count(); double nTriggersPerFilledBC = triggerRate / nbc / constants::lhc::LHCRevFreq; double mu = -std::log(1 - nTriggersPerFilledBC); return mu * nbc * constants::lhc::LHCRevFreq; From 60647c8c164e8b141bc28dfb816457cc81898fc8 Mon Sep 17 00:00:00 2001 From: Igor Ptak <62450343+IgorPtak@users.noreply.github.com> Date: Wed, 27 May 2026 07:13:02 +0200 Subject: [PATCH 300/449] [PWGCF] Add Bertsch-Pratt LCMS decomposition for femto pairs (#16380) --- PWGCF/Femto/Core/pairHistManager.h | 82 +++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index a4fd9451ed2..dcea12be2b7 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -111,7 +112,11 @@ enum PairHist { // angular kDeltaEtaDeltaPhi, - + // Bertsch-Pratt 3D decomposition in LCMS + kQout, + kQside, + kQlong, + kQoutQsideQlong, kPairHistogramLast }; @@ -174,6 +179,10 @@ struct ConfPairBinning : o2::framework::ConfigurableGroup { o2::framework::Configurable transverseMassType{"transverseMassType", static_cast(modes::TransverseMassType::kAveragePdgMass), "Type of transverse mass (0-> Average Pdg Mass, 1-> Reduced Pdg Mass, 2-> Mt from combined 4 vector)"}; o2::framework::ConfigurableAxis binningDeltaEta{"binningDeltaEta", {{35, -1.6, 1.6}}, "Delta eta"}; o2::framework::ConfigurableAxis binningDeltaPhi{"binningDeltaPhi", {{35, -o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf}}, "Delta phi"}; + o2::framework::Configurable plotBertschPratt{"plotBertschPratt", false, "Enable 1D projections and 3D (q_out, q_side, q_long) Bertsch-Pratt histograms in LCMS"}; + o2::framework::ConfigurableAxis qout{"qout", {{300, -1.5f, 1.5f}}, "q_{out} (GeV/c) in LCMS"}; + o2::framework::ConfigurableAxis qside{"qside", {{300, -1.5f, 1.5f}}, "q_{side} (GeV/c) in LCMS"}; + o2::framework::ConfigurableAxis qlong{"qlong", {{300, -1.5f, 1.5f}}, "q_{long} (GeV/c) in LCMS"}; }; struct ConfPairCuts : o2::framework::ConfigurableGroup { @@ -250,6 +259,11 @@ constexpr std::array, kPairHistogramLast> {kMeVtz1VsMult1VsCent1VsVtz2VsMult2VsCent2, o2::framework::HistType::kTHnSparseF, "hVtz1VsMult1VsCent1VsVtz2VsMult2VsCent2", "Mixing bins; V_{z,1} (cm); multiplicity_{1}; centrality_{1} (%); V_{z,2} (cm); multiplicity_{2}; centrality_{2} (%)"}, // angular {kDeltaEtaDeltaPhi, o2::framework::HistType::kTH2F, "hDeltaEtaDeltaPhi", "#Delta#phi vs #Delta#eta; #Delta#phi; #Delta#eta"}, + // Bertsch-Pratt 3D decomposition in LCMS + {kQout, o2::framework::HistType::kTH1F, "hQout", "q_{out} in LCMS; q_{out} (GeV/#it{c}); Entries"}, + {kQside, o2::framework::HistType::kTH1F, "hQside", "q_{side} in LCMS; q_{side} (GeV/#it{c}); Entries"}, + {kQlong, o2::framework::HistType::kTH1F, "hQlong", "q_{long} in LCMS; q_{long} (GeV/#it{c}); Entries"}, + {kQoutQsideQlong, o2::framework::HistType::kTH3F, "hQoutQsideQlong", "Bertsch-Pratt 3D; q_{out} (GeV/#it{c}); q_{side} (GeV/#it{c}); q_{long} (GeV/#it{c})"}, }}; #define PAIR_HIST_ANALYSIS_MAP(confAnalysis, confMixing) \ @@ -294,7 +308,11 @@ constexpr std::array, kPairHistogramLast> {kMeMixingWindowRaw, {confMixing.particleBinning}}, \ {kMeMixingWindowEffective, {confMixing.particleBinning}}, \ {kMeNpart1VsNpart2, {confMixing.particleBinning, confMixing.particleBinning}}, \ - {kMeVtz1VsMult1VsCent1VsVtz2VsMult2VsCent2, {confMixing.vtxBins, confMixing.multBins, confMixing.centBins, confMixing.vtxBins, confMixing.multBins, confMixing.centBins}}, + {kMeVtz1VsMult1VsCent1VsVtz2VsMult2VsCent2, {confMixing.vtxBins, confMixing.multBins, confMixing.centBins, confMixing.vtxBins, confMixing.multBins, confMixing.centBins}}, \ + {kQout, {confAnalysis.qout}}, \ + {kQside, {confAnalysis.qside}}, \ + {kQlong, {confAnalysis.qlong}}, \ + {kQoutQsideQlong, {confAnalysis.qout, confAnalysis.qside, confAnalysis.qlong}}, #define PAIR_HIST_MC_MAP(conf) \ {kTrueKstarVsKstar, {conf.kstar, conf.kstar}}, \ @@ -388,6 +406,7 @@ class PairHistManager mPlotDalitz = ConfPairBinning.plotDalitz.value; mPlotDeltaEtaDeltaPhi = ConfPairBinning.plotDeltaEtaDeltaPhi.value; + mPlotBertschPratt = ConfPairBinning.plotBertschPratt.value; // transverse mass type mMtType = static_cast(ConfPairBinning.transverseMassType.value); @@ -488,6 +507,10 @@ class PairHistManager // set kstar mKstar = getKstar(mParticle1, mParticle2); + if (mPlotBertschPratt) { + std::tie(mQout, mQside, mQlong) = computeBertschPrattLCMS(mParticle1, mParticle2); + } + if (mPlotDeltaEtaDeltaPhi) { mDeltaEta = particle1.eta() - particle2.eta(); mDeltaPhi = RecoDecay::constrainAngle(particle1.phi() - particle2.phi(), -o2::constants::math::PIHalf); @@ -735,6 +758,12 @@ class PairHistManager if (mPlotDeltaEtaDeltaPhi) { mHistogramRegistry->add(analysisDir + getHistNameV2(kDeltaEtaDeltaPhi, HistTable), getHistDesc(kDeltaEtaDeltaPhi, HistTable), getHistType(kDeltaEtaDeltaPhi, HistTable), {Specs.at(kDeltaEtaDeltaPhi)}); } + if (mPlotBertschPratt) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQout, HistTable), getHistDesc(kQout, HistTable), getHistType(kQout, HistTable), {Specs.at(kQout)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQside, HistTable), getHistDesc(kQside, HistTable), getHistType(kQside, HistTable), {Specs.at(kQside)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQlong, HistTable), getHistDesc(kQlong, HistTable), getHistType(kQlong, HistTable), {Specs.at(kQlong)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQoutQsideQlong, HistTable), getHistDesc(kQoutQsideQlong, HistTable), getHistType(kQoutQsideQlong, HistTable), {Specs.at(kQoutQsideQlong)}); + } } void initMc(std::map> const& Specs) @@ -850,6 +879,12 @@ class PairHistManager if (mPlotDeltaEtaDeltaPhi) { mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kDeltaEtaDeltaPhi, HistTable)), mDeltaPhi, mDeltaEta); } + if (mPlotBertschPratt) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQout, HistTable)), mQout); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQside, HistTable)), mQside); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQlong, HistTable)), mQlong); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQoutQsideQlong, HistTable)), mQout, mQside, mQlong); + } } void fillMc() @@ -920,6 +955,43 @@ class PairHistManager return static_cast(0.5 * std::sqrt(std::max(0.0, kallen) / s)); } + std::tuple computeBertschPrattLCMS(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) + { + const ROOT::Math::PxPyPzEVector p1(part1); + const ROOT::Math::PxPyPzEVector p2(part2); + const ROOT::Math::PxPyPzEVector pSum = p1 + p2; + + const double tPx = pSum.Px(); + const double tPy = pSum.Py(); + const double tPz = pSum.Pz(); + const double tE = pSum.E(); + + const double tPt = std::sqrt(tPx * tPx + tPy * tPy); + const double tMt = std::sqrt(tE * tE - tPz * tPz); + + static constexpr double kMinTransverseMomentum = 1e-9; + if (tPt < kMinTransverseMomentum || tMt < kMinTransverseMomentum) { + return {0.0, 0.0, 0.0}; + } + + const double betaL = tPz / tE; + const double gammaL = tE / tMt; + + const double kout1 = (p1.Px() * tPx + p1.Py() * tPy) / tPt; + const double kside1 = (-p1.Px() * tPy + p1.Py() * tPx) / tPt; + const double klong1 = gammaL * (p1.Pz() - betaL * p1.E()); + + const double kout2 = (p2.Px() * tPx + p2.Py() * tPy) / tPt; + const double kside2 = (p2.Py() * tPx - p2.Px() * tPy) / tPt; + const double klong2 = gammaL * (p2.Pz() - betaL * p2.E()); + + float qOut = static_cast(kout1 - kout2); + float qSide = static_cast(kside1 - kside2); + float qLong = static_cast(klong1 - klong2); + + return {qOut, qSide, qLong}; + } + o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; bool mUsePdgMass = true; double mPdgMass1 = 0.; @@ -995,6 +1067,12 @@ class PairHistManager bool mPlotDalitz = false; bool mPlotDeltaEtaDeltaPhi = false; + bool mPlotBertschPratt = false; + + float mQout = 0.f; + float mQside = 0.f; + float mQlong = 0.f; + float mDeltaEta = 0.f; float mDeltaPhi = 0.f; From b5c8d9f28c4cdfe8034be2505e7e836448b204c4 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Wed, 27 May 2026 10:24:27 +0200 Subject: [PATCH 301/449] [PWGDQ] use correct momentum scaling when computing invariant mass (#16365) --- PWGDQ/Tasks/qaMatching.cxx | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 5da0840fcc2..b886909a3ea 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -1594,30 +1594,30 @@ struct QaMatching { } template - o2::dataformats::GlobalFwdTrack propagateToVertexMft(const TMFT& muon, + o2::dataformats::GlobalFwdTrack propagateToVertexMft(const TMFT& mftTrack, const TMCH& mchTrack, const C& collision) { // extrapolation with MCH tools auto mchTrackAtMFT = mExtrap.FwdtoMCH(fwdToTrackPar(mchTrack)); - o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrackAtMFT, muon.z()); + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrackAtMFT, mftTrack.z()); - auto muonTrackProp = mExtrap.FwdtoMCH(fwdToTrackPar(muon)); + auto mftTrackProp = mExtrap.FwdtoMCH(fwdToTrackPar(mftTrack)); // update global track momentum from the MCH track - double pRatio = muonTrackProp.p() / mchTrackAtMFT.p(); - double newInvBendMom = muonTrackProp.getInverseBendingMomentum() * pRatio; - muonTrackProp.setInverseBendingMomentum(newInvBendMom); - muonTrackProp.setCharge(mchTrackAtMFT.getCharge()); + double pRatio = mftTrackProp.p() / mchTrackAtMFT.p(); + double newInvBendMom = mftTrackProp.getInverseBendingMomentum() * pRatio; + mftTrackProp.setInverseBendingMomentum(newInvBendMom); + mftTrackProp.setCharge(mchTrackAtMFT.getCharge()); - o2::mch::TrackExtrap::extrapToVertex(muonTrackProp, + o2::mch::TrackExtrap::extrapToVertex(mftTrackProp, collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covYY()); - return mExtrap.MCHtoFwd(muonTrackProp); + return mExtrap.MCHtoFwd(mftTrackProp); } template @@ -2537,7 +2537,7 @@ struct QaMatching { void fillDimuonPlotsMc(const CollisionInfo& collisionInfo, C const& collisions, TMUON const& muonTracks, - TMFT const& /*mftTracks*/) + TMFT const& mftTracks) { std::vector muonPairs; std::vector globalMuonPairs; @@ -2577,8 +2577,10 @@ struct QaMatching { auto const& muonTrack2 = muonTracks.rawIteratorAt(candidates2[0].globalTrackId); auto matchScore1 = candidates1[0].matchScore; auto matchScore2 = candidates2[0].matchScore; - auto const& mchTrack1 = muonTrack1.template matchMCHTrack_as(); - auto const& mchTrack2 = muonTrack2.template matchMCHTrack_as(); + auto const& mchTrack1 = muonTracks.rawIteratorAt(candidates1[0].muonTrackId); + auto const& mchTrack2 = muonTracks.rawIteratorAt(candidates2[0].muonTrackId); + auto const& mftTrack1 = mftTracks.rawIteratorAt(candidates1[0].mftTrackId); + auto const& mftTrack2 = mftTracks.rawIteratorAt(candidates2[0].mftTrackId); int sign1 = mchTrack1.sign(); int sign2 = mchTrack2.sign(); @@ -2604,8 +2606,8 @@ struct QaMatching { double massMCH = getMuMuInvariantMass(propagateToVertexMch(mchTrack1, collision), propagateToVertexMch(mchTrack2, collision)); - double mass = getMuMuInvariantMass(propagateToVertexMch(muonTrack1, collision), - propagateToVertexMch(muonTrack2, collision)); + double mass = getMuMuInvariantMass(propagateToVertexMft(mftTrack1, mchTrack1, collision), + propagateToVertexMft(mftTrack2, mchTrack2, collision)); registryDimuon.get(HIST("dimuon/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(massMCH); registryDimuon.get(HIST("dimuon/invariantMass_ScaledMftKine_GlobalMuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/MC/invariantMass_MuonKine_GlobalMuonCuts_vs_match_type"))->Fill(massMCH, matchType); From bf2de2407d3d00fca9a41c75481e39e009431a80 Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Wed, 27 May 2026 11:28:19 +0200 Subject: [PATCH 302/449] [PWGCF] Fixing track count condition for [pT] Decorrelation (#16404) --- .../Tasks/radialFlowDecorr.cxx | 77 ++++++++++++++----- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 9df8a0b2c58..cded5d14896 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -76,7 +76,7 @@ struct RadialFlowDecorr { static constexpr int KnFt0cCell = 96; static constexpr int KIntM = 3; static constexpr int KIntK = 3; - static constexpr int KNEta = 17; + static constexpr int KNEta = 9; static constexpr float KFloatEpsilon = 1e-6f; static constexpr int KPiPlus = 211; static constexpr int KKPlus = 321; @@ -151,10 +151,10 @@ struct RadialFlowDecorr { static constexpr float KinvalidCentrality = -1.0f; inline static const std::vector etaLw = { -0.8, - -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; + -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6}; inline static const std::vector etaUp = { 0.8, - -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; + -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; Configurable cfgVtxZCut{"cfgVtxZCut", 10.f, "z-vertex range"}; Configurable cfgPtMin{"cfgPtMin", 0.2f, "min pT"}; @@ -187,6 +187,7 @@ struct RadialFlowDecorr { Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; Configurable cfgCutPtUpperPID{"cfgCutPtUpperPID", 6.0f, "Higher pT cut for identified particle analysis"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; + Configurable cfgMinTracksPerEtaBin{"cfgMinTracksPerEtaBin", 0, "Min weighted-track sum required in every narrow eta bin for inclusive species (0 = disabled)"}; Configurable cfgNsubsample{"cfgNsubsample", 10, "Number of subsamples"}; Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FT0M, 3-->FDDM, 4-->FV0A"}; Configurable cfgEvSelNoSameBunchPileup{"cfgEvSelNoSameBunchPileup", true, "Pileup removal"}; @@ -201,7 +202,7 @@ struct RadialFlowDecorr { Configurable cfgLinPupParam2{"cfgLinPupParam2", 3.0f, "(Lower) Linear Pileup Cut Const"}; Configurable cfgLinPupParam3{"cfgLinPupParam3", 3.0f, "(Lower) Linear Pileup Slope"}; - Configurable cfgNchPbMax{"cfgNchPbMax", 4000, "Max Nch range for PbPb collisions"}; + Configurable cfgNchPbMax{"cfgNchPbMax", 5000, "Max Nch range for PbPb collisions"}; Configurable cfgNchOMax{"cfgNchOMax", 800, "Max Nch range for OO collisions"}; Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->NeNe, 3-->OO, 4-->pp"}; @@ -222,21 +223,17 @@ struct RadialFlowDecorr { const AxisSpec vzAxis{5, -12.5, 12.5, "Vz"}; const AxisSpec chgAxis{3, -1.5, 1.5}; const AxisSpec pTAxis{{0.0, 0.2, 0.4, 0.6, 0.8, 1, 3, 5, 7, 10}, "pT Axis"}; - const AxisSpec etaAxis{{-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, "Eta"}; + const AxisSpec etaAxis{{-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}, "Eta"}; const AxisSpec phiAxis{KNbinsPhi, KPhiMin, TwoPI, "#phi"}; const AxisSpec etaBinAxis{KNEta + 1, -0.5, KNEta + 0.5, "#eta bin Number"}; const AxisSpec spBinAxis{KNsp + 1, -KBinOffset, static_cast(KNsp) + KBinOffset, "species index Number"}; - const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, - -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, - 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, - 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + const AxisSpec gapAxis{{-1.5, -1.3, -1.1, -0.9, -0.7, -0.5, -0.3, -0.1, + 0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5}, "Gap"}; - const AxisSpec sumAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, - -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, - 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, - 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + const AxisSpec sumAxis{{-1.5, -1.3, -1.1, -0.9, -0.7, -0.5, -0.3, -0.1, + 0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5}, "Sum"}; Configurable cfgRunMCGetNSig{"cfgRunMCGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; @@ -552,6 +549,32 @@ struct RadialFlowDecorr { return true; } + template + bool hasMinTracksInAllEtaBins(const double (&sw)[NspT][NetaT][NkT]) + { + const int minTracks = cfgMinTracksPerEtaBin; + if (minTracks <= 0) + return true; + for (std::size_t ieta = 1; ieta < NetaT; ++ieta) { + if (sw[kInclusiveIdx][ieta][1] < static_cast(minTracks)) + return false; + } + return true; + } + + template + bool hasMinTracksInAllEtaBins(const double (&sw)[NspT][NetaT]) + { + const int minTracks = cfgMinTracksPerEtaBin; + if (minTracks <= 0) + return true; + for (std::size_t ieta = 1; ieta < NetaT; ++ieta) { + if (sw[kInclusiveIdx][ieta] < static_cast(minTracks)) + return false; + } + return true; + } + template bool isTrackSelected(const T& trk) { @@ -1996,6 +2019,9 @@ struct RadialFlowDecorr { } } + if (!hasMinTracksInAllEtaBins(sumWiTruth) || !hasMinTracksInAllEtaBins(sumWiReco)) + return; + for (int isp = 0; isp < KNsp; ++isp) { histos.fill(HIST("MCReco/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiReco[isp][0]); histos.fill(HIST("MCReco/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiReco[isp][0]); @@ -2352,6 +2378,9 @@ struct RadialFlowDecorr { } } // trkslice + if (!hasMinTracksInAllEtaBins(sumWkTru) || !hasMinTracksInAllEtaBins(sumWkReco)) + return; + for (int ieta = 0; ieta < KNEta; ++ieta) { const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(mcCollision.multNTracksPV()); const int iby = ieta + 1; @@ -2546,9 +2575,12 @@ struct RadialFlowDecorr { float sum = (etaValA + etaValB); for (int isp = 0; isp < KNsp; ++isp) { - float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; - float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; - float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + float c2SubTru = (ietaA == ietaC) ? static_cast(c2Tru[isp][ietaA]) + : p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = (ietaA == ietaC) ? static_cast(c2Reco[isp][ietaA]) + : p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = (ietaA == ietaC) ? static_cast(c2RecoEffCor[isp][ietaA]) + : p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; @@ -3200,6 +3232,9 @@ struct RadialFlowDecorr { } } + if (!hasMinTracksInAllEtaBins(sumWi)) + return; + for (int isp = 0; isp < KNsp; ++isp) { if (sumWi[isp][0] < 1.0f) continue; @@ -3373,6 +3408,9 @@ struct RadialFlowDecorr { } } + if (!hasMinTracksInAllEtaBins(sumwk)) + return; + double amplFT0A = 0, amplFT0C = 0; if (coll.has_foundFT0()) { const auto& ft0 = coll.foundFT0(); @@ -3440,8 +3478,8 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covAC); } if (std::isfinite(covCA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covCA); - histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covCA); + histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaC, isp, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaC, isp, covCA); } if (std::isfinite(covFT0A)) { histos.fill(HIST("Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0A); @@ -3464,7 +3502,8 @@ struct RadialFlowDecorr { for (int isp = 0; isp < KNsp; ++isp) { - float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; + float c2Sub = (ietaA == ietaC) ? static_cast(c2[isp][ietaA]) + : p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; float cov = p1kBarMult[isp][ietaA] * p1kBar[isp][ietaC]; float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; From 737ef1726aea46d53c2cd01abb0ec9dd2479c496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Wed, 27 May 2026 12:36:36 +0200 Subject: [PATCH 303/449] [PWGHF] Fix includes (#16413) --- PWGHF/D2H/Macros/runMassFitter.C | 1 + PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 1 + PWGHF/D2H/Tasks/taskLc.cxx | 2 -- PWGHF/D2H/Tasks/taskUpcLc.cxx | 7 +------ PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx | 2 ++ PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx | 2 ++ 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 3b05aa6f9ed..b208e2dbf46 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -38,6 +38,7 @@ #include #include +#include #include #include #include diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 5279d032a1b..c2166cca266 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -52,6 +52,7 @@ #include #include #include +#include #include #include diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 805ae3f05ed..0334f01ada9 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -32,7 +32,6 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include #include @@ -45,7 +44,6 @@ #include #include #include -#include #include #include diff --git a/PWGHF/D2H/Tasks/taskUpcLc.cxx b/PWGHF/D2H/Tasks/taskUpcLc.cxx index fcf2200a1e3..33a84e3c4c5 100644 --- a/PWGHF/D2H/Tasks/taskUpcLc.cxx +++ b/PWGHF/D2H/Tasks/taskUpcLc.cxx @@ -17,7 +17,6 @@ /// \author Ran Tu , Fudan University #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/AliasTables.h" @@ -29,12 +28,11 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCHelpers.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include -#include +#include #include #include #include @@ -44,12 +42,9 @@ #include #include #include -#include #include #include -#include - #include #include #include diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index c29493df4a0..2818dc75f98 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -54,6 +54,8 @@ #include #include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index 3aa743aeeca..ecf43e86a6d 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -28,6 +28,7 @@ #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +// #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" @@ -57,6 +58,7 @@ #include #include #include +#include #include #include From 5893b2cdcd7f07283d037d01a3de1bc9d8df4769 Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Wed, 27 May 2026 13:19:29 +0200 Subject: [PATCH 304/449] [PWGHF] Simplify UPC Lc TTree output (#16406) --- PWGHF/D2H/Tasks/taskUpcLc.cxx | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskUpcLc.cxx b/PWGHF/D2H/Tasks/taskUpcLc.cxx index 33a84e3c4c5..74764b924ff 100644 --- a/PWGHF/D2H/Tasks/taskUpcLc.cxx +++ b/PWGHF/D2H/Tasks/taskUpcLc.cxx @@ -66,18 +66,15 @@ namespace full DECLARE_SOA_COLUMN(M, m, float); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(BkgScore, bkgScore, float); -DECLARE_SOA_COLUMN(PromptScore, promptScore, float); -DECLARE_SOA_COLUMN(FdScore, fdScore, float); DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); DECLARE_SOA_COLUMN(DecayLength, decayLength, float); DECLARE_SOA_COLUMN(Cpa, cpa, float); -DECLARE_SOA_COLUMN(PvContributors, pvContributors, float); -DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); +DECLARE_SOA_COLUMN(PvContributors, pvContributors, int); +DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); DECLARE_SOA_COLUMN(Vtz, vtz, float); -DECLARE_SOA_COLUMN(AmpFV0A, ampFV0A, float); DECLARE_SOA_COLUMN(AmpFT0A, ampFT0A, float); DECLARE_SOA_COLUMN(AmpFT0C, ampFT0C, float); DECLARE_SOA_COLUMN(ZdcTimeZNA, zdcTimeZNA, float); @@ -87,7 +84,6 @@ DECLARE_SOA_TABLE(HfUpcQa, "AOD", "HFUPCQA", full::PvContributors, full::Multiplicity, full::Vtz, - full::AmpFV0A, full::AmpFT0A, full::AmpFT0C, full::ZdcTimeZNA, @@ -97,9 +93,6 @@ DECLARE_SOA_TABLE(HfUpcLcBdtInfos, "AOD", "HFUPCLCBDTINFOS", full::M, full::Pt, full::BkgScore, - full::PromptScore, - full::FdScore, - full::AmpFV0A, full::AmpFT0A, full::AmpFT0C, full::ZdcTimeZNA, @@ -114,7 +107,6 @@ DECLARE_SOA_TABLE(HfUpcLcInfos, "AOD", "HFUPCLCINFOS", full::Chi2PCA, full::DecayLength, full::Cpa, - full::AmpFV0A, full::AmpFT0A, full::AmpFT0C, full::ZdcTimeZNA, @@ -251,9 +243,9 @@ struct HfTaskUpcLc { if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { registry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); registry.fill(HIST("Data/hUpcVtz"), collision.posZ()); - } - if (fillTreeUpcQa) { - rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + if (fillTreeUpcQa) { + rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + } } for (const auto& candidate : groupedLcCandidates) { @@ -271,7 +263,7 @@ struct HfTaskUpcLc { const auto chi2PCA = candidate.chi2PCA(); const auto cpa = candidate.cpa(); - double outputBkg(-1), outputPrompt(-1), outputFD(-1); + double outputBkg(-1); auto fillTHnData = [&](bool isPKPi) { const auto massLc = isPKPi ? HfHelper::invMassLcToPKPi(candidate) : HfHelper::invMassLcToPiKP(candidate); @@ -280,25 +272,23 @@ struct HfTaskUpcLc { const auto& mlProb = isPKPi ? candidate.mlProbLcToPKPi() : candidate.mlProbLcToPiKP(); if (mlProb.size() == NumberOfMlClasses) { outputBkg = mlProb[MlClassBackground]; /// bkg score - outputPrompt = mlProb[MlClassPrompt]; /// prompt score - outputFD = mlProb[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate if (fillTreeOnlySingleGap) { if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - rowCandUpcBdt(massLc, pt, outputBkg, outputPrompt, outputFD, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + rowCandUpcBdt(massLc, pt, outputBkg, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } } else { - rowCandUpcBdt(massLc, pt, outputBkg, outputPrompt, outputFD, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + rowCandUpcBdt(massLc, pt, outputBkg, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } } else { if (fillTreeOnlySingleGap) { if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } } else { - rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFV0A, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } } }; From cd8ece72495f5b027446d9935ee0b4ce75d77aa7 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 27 May 2026 14:21:33 +0200 Subject: [PATCH 305/449] [PWGEM/Dilepton] reduce data size for taggingHFE (#16419) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 24 ++++++------- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 48 ++++++++++++------------- PWGEM/Dilepton/Utils/SemiCharmTag.h | 48 ++++++++++++------------- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index a211af95777..86b24480660 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -263,14 +263,14 @@ DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming kao DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pt of LH DECLARE_SOA_COLUMN(PtSVL, ptSVL, float); //! pT of lepton at SV -DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV +// DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV DECLARE_SOA_COLUMN(PtSVH, ptSVH, float); //! pT of associated hadron at SV -DECLARE_SOA_COLUMN(PlSVH, plSVH, float); //! pL of associated hadron at SV +// DECLARE_SOA_COLUMN(PlSVH, plSVH, float); //! pL of associated hadron at SV -DECLARE_SOA_COLUMN(PtFDL, ptFDL, float); //! pT of lepton perpendicular to flight direction -DECLARE_SOA_COLUMN(PlFDL, plFDL, float); //! pL of lepton in parallel to flight direction -DECLARE_SOA_COLUMN(PtFDH, ptFDH, float); //! pT of associated hadron perpendicular to flight direction -DECLARE_SOA_COLUMN(PlFDH, plFDH, float); //! pL of associated hadron in parallel to flight direction +// DECLARE_SOA_COLUMN(PtFDL, ptFDL, float); //! pT of lepton perpendicular to flight direction +// DECLARE_SOA_COLUMN(PlFDL, plFDL, float); //! pL of lepton in parallel to flight direction +// DECLARE_SOA_COLUMN(PtFDH, ptFDH, float); //! pT of associated hadron perpendicular to flight direction +// DECLARE_SOA_COLUMN(PlFDH, plFDH, float); //! pL of associated hadron in parallel to flight direction DECLARE_SOA_COLUMN(PtFD, ptFD, float); //! visible momentum of LH pair perpendicular to flight direction = - missing pT due to neutrino perpendicular to flight direction DECLARE_SOA_COLUMN(PlFD, plFD, float); //! visible momentum of LH pair in parallel to flight direction @@ -305,8 +305,8 @@ DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! // pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, // pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, - emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, @@ -319,8 +319,8 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, - emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, @@ -333,8 +333,8 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PlSVL, emmllhpair::PtSVH, emmllhpair::PlSVH, - emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::PtFDL, emmllhpair::PlFDL, emmllhpair::PtFDH, emmllhpair::PlFDH, + emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, + emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index fb5f97b5260..d97f4837579 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1762,8 +1762,8 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, - eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, + eKpair.ptFD, eKpair.plFD, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, @@ -1823,8 +1823,8 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, - eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, + eKpair.ptFD, eKpair.plFD, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, @@ -1902,8 +1902,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, - eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, @@ -1965,8 +1965,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, - eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, @@ -2033,8 +2033,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, - eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, + eCpair.ptFD, eCpair.plFD, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, @@ -2101,8 +2101,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, - eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, + eCpair.ptFD, eCpair.plFD, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, @@ -2198,8 +2198,8 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, - eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, + eKpair.ptFD, eKpair.plFD, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, @@ -2260,8 +2260,8 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.plSVL, eKpair.ptSVH, eKpair.plSVH, - eKpair.ptFD, eKpair.plFD, eKpair.ptFDL, eKpair.plFDL, eKpair.ptFDH, eKpair.plFDH, + eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, + eKpair.ptFD, eKpair.plFD, eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, @@ -2338,8 +2338,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, - eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, @@ -2401,8 +2401,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.plSVL, eV0pair.ptSVH, eV0pair.plSVH, - eV0pair.ptFD, eV0pair.plFD, eV0pair.ptFDL, eV0pair.plFDL, eV0pair.ptFDH, eV0pair.plFDH, + eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, + eV0pair.ptFD, eV0pair.plFD, eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, @@ -2469,8 +2469,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, - eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, + eCpair.ptFD, eCpair.plFD, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, @@ -2537,8 +2537,8 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.plSVL, eCpair.ptSVH, eCpair.plSVH, - eCpair.ptFD, eCpair.plFD, eCpair.ptFDL, eCpair.plFDL, eCpair.ptFDH, eCpair.plFDH, + eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, + eCpair.ptFD, eCpair.plFD, eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index 10aa317ec58..b02b377330a 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -53,14 +53,14 @@ struct LHPair { // struct to store electron-hadron pair information float impParCZZ{-999.f}; float ptSVL{-999.f}; - float plSVL{-999.f}; + // float plSVL{-999.f}; float ptSVH{-999.f}; - float plSVH{-999.f}; + // float plSVH{-999.f}; - float ptFDL{-999.f}; - float plFDL{-999.f}; - float ptFDH{-999.f}; - float plFDH{-999.f}; + // float ptFDL{-999.f}; + // float plFDL{-999.f}; + // float ptFDH{-999.f}; + // float plFDH{-999.f}; float ptFD{-999.f}; float plFD{-999.f}; @@ -109,8 +109,8 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); - pair.plSVL = pvec0[2]; - pair.plSVH = pvec1[2]; + // pair.plSVL = pvec0[2]; + // pair.plSVH = pvec1[2]; pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); @@ -132,10 +132,10 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); - pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); - pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); - pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); - pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); + // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); @@ -228,8 +228,8 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); - pair.plSVL = pvec0[2]; - pair.plSVH = pvec1[2]; + // pair.plSVL = pvec0[2]; + // pair.plSVH = pvec1[2]; pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); @@ -251,10 +251,10 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); - pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); - pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); - pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); - pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); + // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); @@ -356,8 +356,8 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); - pair.plSVL = pvec0[2]; - pair.plSVH = pvec1[2]; + // pair.plSVL = pvec0[2]; + // pair.plSVH = pvec1[2]; pair.cospa = RecoDecay::cpa(vertex, svpos, pvecSum); pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); @@ -379,10 +379,10 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); - pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); - pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); - pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); - pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); + // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); + // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); + // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); + // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); // propagate the 2 prongs to the secondary vertex leptonParCov.propagateTo(vtx[0], fitter.getBz()); From 63111f2c09b139cec52ead2cc6a4b84358cd9dab Mon Sep 17 00:00:00 2001 From: Jinhyun Park <125851562+jinhyunni@users.noreply.github.com> Date: Wed, 27 May 2026 22:11:52 +0900 Subject: [PATCH 306/449] [PWGHF] [xic0omegac0] Update code to fix PID assignment in KFParticle (#16381) Co-authored-by: Jinhyun Park Co-authored-by: ALICE Action Bot --- .../candidateCreatorXic0Omegac0Qa.cxx | 79 +++++++++++++------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx index f531919ebd9..04dacbfc128 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx @@ -261,7 +261,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { int pdgIdOfV0DauPos{}, pdgIdOfV0DauNeg{}, pdgIdOfBach{}, pdgIdOfCharmBach{}; int pdgIdOfV0{}, pdgIdOfCascade{}, pdgIdOfCharmBaryon{}; - // Track PID - Used in DCAFitter + // Track PID: PID value of tracks defined under o2::track::PID namespace int trackPidOfCascade{}; // Mass of daughter tracks & V0s & cascades & charm baryons; @@ -362,20 +362,21 @@ struct HfCandidateCreatorXic0Omegac0Qa { massOfV0 = o2::constants::physics::MassLambda; massOfCascade = o2::constants::physics::MassOmegaMinus; } - LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - LOGF(info, "PDG ID of V0 positive daughter: %d", pdgIdOfV0DauPos); - LOGF(info, "PDG ID of V0 negative daughter: %d", pdgIdOfV0DauNeg); - LOGF(info, "PDG ID of Bachelor: %d", pdgIdOfBach); - LOGF(info, "PDG ID of Charm Bachelor: %d", pdgIdOfCharmBach); - LOGF(info, "-------------------------------------------"); - LOGF(info, "PDG ID of V0: %d", pdgIdOfV0); - LOGF(info, "PDG ID of Cascade: %d", pdgIdOfCascade); - LOGF(info, "PDG ID of Charm Baryon: %d", pdgIdOfCharmBaryon); - LOGF(info, "-------------------------------------------"); - LOGF(info, "Mass of V0 set as: %f", massOfV0); - LOGF(info, "Mass of CharmBach set as: %f", massOfCharmBach); - LOGF(info, "Mass of Casc as: %f", massOfCascade); - LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + LOGF(info, " Chosen reconstruction info: ToXiPi(%d)/ ToOmegaPi(%d)/ ToOmegaKa(%d)", xipiEnabledDca + xipiEnabledKf, omegapiEnabledDca + omegapiEnabledKf, omegakaEnabledDca + omegakaEnabledKf); + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + LOGF(info, " PDG ID of V0 positive daughter: %d", pdgIdOfV0DauPos); + LOGF(info, " PDG ID of V0 negative daughter: %d", pdgIdOfV0DauNeg); + LOGF(info, " PDG ID of V0: %d", pdgIdOfV0); + LOGF(info, " PDG ID of Bachelor: %d", pdgIdOfBach); + LOGF(info, " PDG ID of Cascade: %d", pdgIdOfCascade); + LOGF(info, " PDG ID of Charm Bachelor: %d", pdgIdOfCharmBach); + LOGF(info, " PDG ID of Charm Baryon: %d", pdgIdOfCharmBaryon); + LOGF(info, "-----------------------------------------------------------------------"); + LOGF(info, " Mass of V0 set as: %f", massOfV0); + LOGF(info, " Mass of CharmBach set as: %f", massOfCharmBach); + LOGF(info, " Mass of Casc as: %f", massOfCascade); + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); // Add histogram to indicate which sv method was used registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {kTH1F, {{2, 0.0, 2.0}}}); @@ -491,6 +492,30 @@ struct HfCandidateCreatorXic0Omegac0Qa { } // end of initialization + // helper function to convert PDG of KFParticle object into appropriate track PID. + // exclusively used to make input of getTrackParCovFromKFP() + // \brief kfPdg is Pdg value of KFParticle object + o2::track::PID::ID convertPDGIntoPID(const int kfPdg) + { + switch (std::abs(kfPdg)) { + case kPiPlus: + return o2::track::PID::Pion; + case kKPlus: + return o2::track::PID::Kaon; + case kProton: + return o2::track::PID::Proton; + case kLambda0: + return o2::track::PID::Lambda; + case kXiMinus: + return o2::track::PID::XiMinus; + case kOmegaMinus: + return o2::track::PID::OmegaMinus; + default: + LOGF(fatal, "Undefined PDG value from KFParticle given for conversion(%d). Replace it with PID of Pion", kfPdg); + return o2::track::PID::Pion; + } + } + // template function for running charm baryon reconstruction with DCAFitter /// \brief centEstimator is for different centrality estimators /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmeagaK @@ -934,6 +959,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { const KFPTrack kfTrackBach = createKFPTrackFromTrack(bachTrack); bool isAnti = (bachTrack.signed1Pt() > 0 ? true : false); + int bachCharge = (bachTrack.signed1Pt() > 0 ? +1 : -1); KFParticle kfPos(kfTrack0, (isAnti ? -pdgIdOfV0DauNeg : pdgIdOfV0DauPos)); KFParticle kfNeg(kfTrack1, (isAnti ? -pdgIdOfV0DauPos : pdgIdOfV0DauNeg)); @@ -1082,6 +1108,18 @@ struct HfCandidateCreatorXic0Omegac0Qa { kfCharmBaryonToPv.SetProductionVertex(kfPv); //----------Reconstruct information after vertex fit---------- + auto trackParCovV0DauPos = getTrackParCovFromKFP(kfPos, convertPDGIntoPID(kfPos.GetPDG()), 1); + auto trackParCovV0DauNeg = getTrackParCovFromKFP(kfNeg, convertPDGIntoPID(kfNeg.GetPDG()), -1); + auto trackParCovBach = getTrackParCovFromKFP(kfBachToCasc, convertPDGIntoPID(kfBachToCasc.GetPDG()), bachCharge); + auto trackParCovCharmBach = getTrackParCovFromKFP(kfCharmBachToCharmBaryon, convertPDGIntoPID(kfCharmBachToCharmBaryon.GetPDG()), -bachCharge); + auto trackParCovCasc = getTrackParCovFromKFP(kfCascToCharmBaryon, convertPDGIntoPID(kfCascToCharmBaryon.GetPDG()), bachCharge); + + trackParCovV0DauPos.setAbsCharge(1); + trackParCovV0DauNeg.setAbsCharge(1); + trackParCovBach.setAbsCharge(1); + trackParCovCharmBach.setAbsCharge(1); + trackParCovCasc.setAbsCharge(1); + std::array vertexV0 = {kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}; std::array vertexCasc = {kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}; @@ -1098,17 +1136,6 @@ struct HfCandidateCreatorXic0Omegac0Qa { std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; - auto trackParCovV0DauPos = getTrackParCovFromKFP(kfPos, kfPos.GetPDG(), 1); - auto trackParCovV0DauNeg = getTrackParCovFromKFP(kfNeg, kfNeg.GetPDG(), -1); - auto trackParCovBach = getTrackParCovFromKFP(kfBachToCasc, kfBachToCasc.GetPDG(), (isAnti ? 1 : -1)); - auto trackParCovCharmBach = getTrackParCovFromKFP(kfCharmBachToCharmBaryon, kfCharmBachToCharmBaryon.GetPDG(), (isAnti ? -1 : 1)); - auto trackParCovCasc = getTrackParCovFromKFP(kfCascToCharmBaryon, kfCascToCharmBaryon.GetPDG(), (isAnti ? 1 : -1)); - trackParCovV0DauPos.setAbsCharge(1); - trackParCovV0DauNeg.setAbsCharge(1); - trackParCovBach.setAbsCharge(1); - trackParCovCharmBach.setAbsCharge(1); - trackParCovCasc.setAbsCharge(1); - //----------Calculate physical quantities and fill candidate table---------- // impact parameters From 39720334cc785effee10639cf4cce3e012e381ec Mon Sep 17 00:00:00 2001 From: Pravata Panigrahi <158029188+pravatp98@users.noreply.github.com> Date: Wed, 27 May 2026 19:01:37 +0530 Subject: [PATCH 307/449] [PWGCF] nchCumulantsId: Make axes configurable (#16368) Co-authored-by: ALICE Action Bot --- .../EbyEFluctuations/Tasks/nchCumulantsId.cxx | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index 0e23058ea7d..3241efacbc6 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -21,19 +21,30 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include +#include +#include +#include +#include #include +#include #include using namespace o2; @@ -112,6 +123,17 @@ struct NchCumulantsId { Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "max cut for pT"}; Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "min cut for pT"}; + ConfigurableAxis axisNch{"axisNch", {1200, -60.0, 60.0}, "Net_charge_dN"}; + ConfigurableAxis axisPosCh{"axisPosCh", {3010, -0.5, 300.5}, "Pos_charge"}; + ConfigurableAxis axisNegCh{"axisNegCh", {3010, -0.5, 300.5}, "Neg_charge"}; + ConfigurableAxis axisNt{"axisNt", {8010, -0.5, 800.5}, "Mult_midRap_Nch"}; + ConfigurableAxis axisPrCh{"axisPrCh", {3010, -0.5, 300.5}, "Pr_charge"}; + ConfigurableAxis axisAPrCh{"axisAPrCh", {3010, -0.5, 300.5}, "APr_charge"}; + ConfigurableAxis axisKaCh{"axisKaCh", {3010, -0.5, 300.5}, "Ka_charge"}; + ConfigurableAxis axisAKaCh{"axisAKaCh", {3010, -0.5, 300.5}, "AKa_charge"}; + ConfigurableAxis axisPiCh{"axisPiCh", {3010, -0.5, 300.5}, "Pion_Positive"}; + ConfigurableAxis axisAPiCh{"axisAPiCh", {3010, -0.5, 300.5}, "Pion_Negative"}; + Configurable checkCollPosZMc{"checkCollPosZMc", false, "checkCollPosZMc"}; Configurable flagUnusedVariableError{"flagUnusedVariableError", false, "flagUnusedVariableError"}; Configurable cfgDoRejectionForId{"cfgDoRejectionForId", false, "Apply rejection cut before PID selection (selTrackForId)"}; @@ -121,7 +143,7 @@ struct NchCumulantsId { Configurable cfgEvSel03doIsGoodITSLayersAll{"cfgEvSel03doIsGoodITSLayersAll", true, "apply kIsGoodITSLayersAll"}; // Configurables for particle Identification - Configurable cfgId01CheckVetoCut{"cfgId01CheckVetoCut", false, "cfgId01CheckVetoCut"}; + Configurable cfgId01CheckVetoCut{"cfgId01CheckVetoCut", true, "cfgId01CheckVetoCut"}; Configurable cfgId02DoElRejection{"cfgId02DoElRejection", true, "cfgId02DoElRejection"}; Configurable cfgId03DoDeRejection{"cfgId03DoDeRejection", false, "cfgId03DoDeRejection"}; Configurable cfgId04DoPdependentId{"cfgId04DoPdependentId", true, "cfgId04DoPdependentId"}; @@ -246,17 +268,6 @@ struct NchCumulantsId { const AxisSpec axisTOFNSigma = {200, -10.0, 10.0, "n#sigma_{TOF}"}; const AxisSpec axisTOFExpMom = {200, 0.0f, 10.0f, "#it{p}_{tofExpMom} (GeV/#it{c})"}; - const AxisSpec axisNch(100, -50, 50, "Net_charge_dN"); - const AxisSpec axisPosCh(101, -1, 100, "Pos_charge"); - const AxisSpec axisNegCh(101, -1, 100, "Neg_charge"); - const AxisSpec axisNt(201, -1, 200, "Mult_midRap_Nch"); - const AxisSpec axisPrCh(101, -1, 100, "Pr_charge"); - const AxisSpec axisAPrCh(101, -1, 100, "APr_charge"); - const AxisSpec axisKaCh(101, -1, 100, "Ka_charge"); - const AxisSpec axisAKaCh(101, -1, 100, "AKa_charge"); - const AxisSpec axisPiCh(101, -1, 100, "Pion_Positive"); - const AxisSpec axisAPiCh(101, -1, 100, "Pion_Negative"); - const AxisSpec axisIdTag = {32, -0.5f, 31.5f, "idTag"}; const AxisSpec axisMcTag = {32, -0.5f, 31.5f, "mcTag"}; From 9de4a56991ad68b8a2b6ed48fc18e30b7468a7df Mon Sep 17 00:00:00 2001 From: glegras <71757105+glegras@users.noreply.github.com> Date: Wed, 27 May 2026 15:47:39 +0200 Subject: [PATCH 308/449] [PWGDQ] optimizations in dalitz-selection (#16373) --- PWGDQ/Tasks/DalitzSelection.cxx | 297 +++++++++++++++++++++++--------- 1 file changed, 211 insertions(+), 86 deletions(-) diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index 317015a044f..26162822fd7 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -70,9 +70,14 @@ using MyBarrelTracks = soa::Join; +using MyBarrelTracksNoTOF = soa::Join; + // constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision; constexpr static uint32_t EventFillMapWithCent = VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionCent; constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackPID; +constexpr static uint32_t TrackFillMapNoTOF = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackTPCPID; struct DalitzSelection { Produces dalitzbits; @@ -89,10 +94,11 @@ struct DalitzSelection { Configurable fConfigTrackCutsJSON{"cfgTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; Configurable fConfigTrackCutsProbeJSON{"cfgTrackCutsProbeJSON", "", "Additional list of barrel track cuts for the probe in JSON format"}; Configurable fConfigPairCutsJSON{"cfgPairCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; - Configurable fConfigBarrelTrackPINLow{"cfgBarrelLowPIN", 0.1f, "Low pt cut for Dalitz tracks in the barrel"}; + Configurable fConfigPtLow{"cfgLowPt", 0.1f, "Low pt cut for Dalitz tracks in the barrel"}; Configurable fConfigEtaCut{"cfgEtaCut", 0.9f, "Eta cut for Dalitz tracks in the barrel"}; Configurable fConfigTPCNSigLow{"cfgTPCNSigElLow", -3.f, "Low TPCNSigEl cut for Dalitz tracks in the barrel"}; Configurable fConfigTPCNSigHigh{"cfgTPCNSigElHigh", 3.f, "High TPCNsigEl cut for Dalitz tracks in the barrel"}; + Configurable fConfigTrackSel{"cfgTrackSel", 0, "track selection requirement: 0: all, 1: reject ITS only, 2: reject TPC only, 3: reject ITS only and TPC only"}; } fConfigCuts; // histograms @@ -121,7 +127,7 @@ struct DalitzSelection { o2::parameters::GRPMagField* grpmag = nullptr; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - Filter filterBarrelTrack = o2::aod::track::tpcInnerParam >= fConfigCuts.fConfigBarrelTrackPINLow && nabs(o2::aod::track::eta) <= fConfigCuts.fConfigEtaCut && o2::aod::pidtpc::tpcNSigmaEl <= fConfigCuts.fConfigTPCNSigHigh && o2::aod::pidtpc::tpcNSigmaEl >= fConfigCuts.fConfigTPCNSigLow; + Filter filterBarrelTrack = (o2::aod::track::pt >= fConfigCuts.fConfigPtLow) && (nabs(o2::aod::track::eta) <= fConfigCuts.fConfigEtaCut) && ((o2::aod::pidtpc::tpcNSigmaEl <= fConfigCuts.fConfigTPCNSigHigh && o2::aod::pidtpc::tpcNSigmaEl >= fConfigCuts.fConfigTPCNSigLow) || ((o2::aod::track::v001::detectorMap & 2) == 0)) && ((fConfigCuts.fConfigTrackSel != 1 && fConfigCuts.fConfigTrackSel != 3) || ((o2::aod::track::v001::detectorMap & 2) != 0)) && ((fConfigCuts.fConfigTrackSel != 2 && fConfigCuts.fConfigTrackSel != 3) || ((o2::aod::track::v001::detectorMap & 1) != 0)); OutputObj fOutputList{"output"}; //! the histogram manager output list OutputObj fStatsList{"Statistics"}; //! skimming statistics @@ -142,10 +148,12 @@ struct DalitzSelection { std::vector fPairCuts; bool fIsTagAndProbe; // whether we are doing tag and probe, or just symmetric cuts + bool fIsOutputRequested; + bool fSkipEvent; // speed up by skipping next step of event if no track/pair is selected HistogramManager* fHistMan; - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& context) { fIsTagAndProbe = false; VarManager::SetDefaultVarNames(); @@ -303,17 +311,52 @@ struct DalitzSelection { VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); + + // autodetect whether the dalitz bits are requested + fIsOutputRequested = false; + auto& workflows = context.services().template get(); + // autodetect this table in other devices + for (o2::framework::DeviceSpec const& device : workflows.devices) { + // Check if this device subscribed to the dalitz table + for (auto const& input : device.inputs) { + if (o2::framework::DataSpecUtils::partialMatch(input.matcher, o2::header::DataOrigin("AOD"))) { + std::string tableName = "DalitzBits"; + if (input.matcher.binding == tableName) { + LOGF(info, "Device %s has subscribed to %s", device.name, "DalitzBits"); + fIsOutputRequested = true; + } + } + } + } } - template + template void runTrackSelection(TTracks const& tracksBarrel, TEvent const& collision) { + + fSkipEvent = true; for (const auto& track1 : tracksBarrel) { uint8_t filterMap = uint8_t(0); uint8_t filterMapProbe = uint8_t(0); int fullTrackIdx = 0; if constexpr (isReassoc) { - auto const& fullTrack = track1.template track_as(); + auto const& fullTrack = track1.template track_as(); + // Basic filter cuts which cannot be applied directly in case of reassoc + if (fullTrack.pt() < fConfigCuts.fConfigPtLow) { + continue; + } + if (std::fabs(fullTrack.eta()) > fConfigCuts.fConfigEtaCut) { + continue; + } + if (fullTrack.hasTPC() && (fullTrack.tpcNSigmaEl() < fConfigCuts.fConfigTPCNSigLow || fullTrack.tpcNSigmaEl() > fConfigCuts.fConfigTPCNSigHigh)) { + continue; + } + if ((fConfigCuts.fConfigTrackSel == 1 || fConfigCuts.fConfigTrackSel == 3) && !fullTrack.hasTPC()) { + continue; + } + if ((fConfigCuts.fConfigTrackSel == 2 || fConfigCuts.fConfigTrackSel == 3) && !fullTrack.hasITS()) { + continue; + } VarManager::FillTrack(fullTrack); VarManager::FillTrackCollision(fullTrack, collision); fullTrackIdx = fullTrack.globalIndex(); @@ -325,6 +368,7 @@ struct DalitzSelection { for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { if ((*cut).IsSelected(VarManager::fgValues)) { filterMap |= (uint8_t(1) << i); + fSkipEvent = false; } } if (fIsTagAndProbe) { @@ -344,115 +388,145 @@ struct DalitzSelection { } // end loop over tracks } - template + template void runDalitzPairing(TTracks const& tracks1, TTracks const& tracks2, TEvent collision) { if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { - // keep track of selections from previous events to check if the track was already selected or not - fDalitzmapAmbiguity = fDalitzmap; - fDalitzmapProbeAmbiguity = fDalitzmapProbe; + fDalitzmapAmbiguity.clear(); + fDalitzmapProbeAmbiguity.clear(); } + fSkipEvent = true; - for (const auto& [track1, track2] : o2::soa::combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { - + for (const auto& track1 : tracks1) { int trackIdx1; - int trackIdx2; - bool isLikeSign; + bool isTrack1P; + if constexpr (isReassoc) { - auto const& fullTrack1 = track1.template track_as(); - auto const& fullTrack2 = track2.template track_as(); + auto const& fullTrack1 = track1.template track_as(); trackIdx1 = fullTrack1.globalIndex(); - trackIdx2 = fullTrack2.globalIndex(); - isLikeSign = (fullTrack1.sign() * fullTrack2.sign() > 0); + isTrack1P = fullTrack1.sign() > 0; } else { trackIdx1 = track1.globalIndex(); - trackIdx2 = track2.globalIndex(); - isLikeSign = (track1.sign() * track2.sign() > 0); + isTrack1P = track1.sign() > 0; } - if (trackIdx1 == trackIdx2) { - continue; - } - if (!fIsTagAndProbe && trackIdx1 >= trackIdx2) { - continue; - } - if (!fConfigOptions.fConfigEnableLikeSign && isLikeSign) { + if (!fTrackmap[trackIdx1]) { continue; } - uint8_t twoTracksFilterMap = fTrackmap[trackIdx1] & (fIsTagAndProbe ? fTrackmapProbe[trackIdx2] : fTrackmap[trackIdx2]); - if (!twoTracksFilterMap) { - continue; - } + for (const auto& track2 : tracks2) { + int trackIdx2; + bool isLikeSign; + if constexpr (isReassoc) { + auto const& fullTrack2 = track2.template track_as(); + trackIdx2 = fullTrack2.globalIndex(); + isLikeSign = (isTrack1P && (fullTrack2.sign() > 0)) || (!isTrack1P && (fullTrack2.sign() < 0)); + } else { + trackIdx2 = track2.globalIndex(); + isLikeSign = (isTrack1P && (track2.sign() > 0)) || (!isTrack1P && (track2.sign() < 0)); + } - // pairing - if constexpr (isReassoc) { - auto const& fullTrack1 = track1.template track_as(); - auto const& fullTrack2 = track2.template track_as(); - VarManager::FillPair(fullTrack1, fullTrack2); - } else { - VarManager::FillPair(track1, track2); - } + if (trackIdx1 == trackIdx2) { + continue; + } + if (!fIsTagAndProbe && trackIdx1 >= trackIdx2) { + continue; + } + if (!fConfigOptions.fConfigEnableLikeSign && isLikeSign) { + continue; + } - // Fill pair selection map and fill pair histogram - int icut = 0; - auto trackCut = fTrackCuts.begin(); - for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, icut++) { - if (!(twoTracksFilterMap & (uint8_t(1) << icut))) { + uint8_t twoTracksFilterMap = fTrackmap[trackIdx1] & (fIsTagAndProbe ? fTrackmapProbe[trackIdx2] : fTrackmap[trackIdx2]); + if (!twoTracksFilterMap) { continue; } - if ((*pairCut).IsSelected(VarManager::fgValues)) { - bool isPairAlreadySelected = false; - if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { - // if we remove double counting and the pair is already selected, we don't fill the histograms - std::pair iPair(trackIdx1, trackIdx2); - if (fAmbiguousPairs.find(iPair) != fAmbiguousPairs.end()) { - if (fAmbiguousPairs[iPair] & (static_cast(1) << icut)) { // if this pair is already stored with this cut - isPairAlreadySelected = true; + + // pairing + if constexpr (isReassoc) { + auto const& fullTrack1 = track1.template track_as(); + auto const& fullTrack2 = track2.template track_as(); + VarManager::FillPair(fullTrack1, fullTrack2); + } else { + VarManager::FillPair(track1, track2); + } + + // Fill pair selection map and fill pair histogram + int icut = 0; + auto trackCut = fTrackCuts.begin(); + for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, icut++) { + if (!(twoTracksFilterMap & (uint8_t(1) << icut))) { + continue; + } + if ((*pairCut).IsSelected(VarManager::fgValues)) { + fSkipEvent = false; + bool isPairAlreadySelected = false; + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + // if we remove double counting and the pair is already selected, we don't fill the histograms + std::pair iPair(trackIdx1, trackIdx2); + if (fAmbiguousPairs.find(iPair) != fAmbiguousPairs.end()) { + if (fAmbiguousPairs[iPair] & (static_cast(1) << icut)) { // if this pair is already stored with this cut + isPairAlreadySelected = true; + } else { + fAmbiguousPairs[iPair] |= static_cast(1) << icut; + } } else { - fAmbiguousPairs[iPair] |= static_cast(1) << icut; + fAmbiguousPairs[iPair] = static_cast(1) << icut; } - } else { - fAmbiguousPairs[iPair] = static_cast(1) << icut; } - } - if (!isLikeSign) { - fDalitzmap[trackIdx1] |= (uint8_t(1) << icut); - if (fIsTagAndProbe) { - fDalitzmapProbe[trackIdx2] |= (uint8_t(1) << icut); - if (fConfigOptions.fQA && !isPairAlreadySelected) { - fHistMan->FillHistClass(Form("Pair_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + if (!isLikeSign) { + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + // if we want to remove double-counting, we fill separately the map for this event and for previous ones, in order to check if it was previously selected + fDalitzmapAmbiguity[trackIdx1] |= (uint8_t(1) << icut); + } else { + fDalitzmap[trackIdx1] |= (uint8_t(1) << icut); + } + if (fIsTagAndProbe) { + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + fDalitzmapProbeAmbiguity[trackIdx1] |= (uint8_t(1) << icut); + } else { + fDalitzmapProbe[trackIdx2] |= (uint8_t(1) << icut); + } + if (fConfigOptions.fQA && !isPairAlreadySelected) { + fHistMan->FillHistClass(Form("Pair_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } + } else { + if (isReassoc & fConfigOptions.fRemoveDoubleCounting) { + fDalitzmapAmbiguity[trackIdx1] |= (uint8_t(1) << icut); + } else { + fDalitzmap[trackIdx2] |= (uint8_t(1) << icut); + } + if (fConfigOptions.fQA && !isPairAlreadySelected) { + fHistMan->FillHistClass(Form("Pair_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + } } } else { - fDalitzmap[trackIdx2] |= (uint8_t(1) << icut); if (fConfigOptions.fQA && !isPairAlreadySelected) { - fHistMan->FillHistClass(Form("Pair_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); + fHistMan->FillHistClass(fIsTagAndProbe ? Form("PairLS_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()) : Form("PairLS_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } - } - } else { - if (fConfigOptions.fQA && !isPairAlreadySelected) { - fHistMan->FillHistClass(fIsTagAndProbe ? Form("PairLS_%s_%s_%s", (*trackCut).GetName(), fTrackCutsProbe.at(icut).GetName(), (*pairCut).GetName()) : Form("PairLS_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); - } - } // end if like-sign - } // end if isSelected - } // end cut loop + } // end if like-sign + } // end if isSelected + } // end cut loop + } } // end of tracksP,N loop // Fill Hists - if (fConfigOptions.fQA) { + if (fConfigOptions.fQA && !fSkipEvent) { for (const auto& track : tracks1) { uint8_t filterMap; uint8_t filterMapProbe; if constexpr (isReassoc) { - auto const& fullTrack = track.template track_as(); + auto const& fullTrack = track.template track_as(); filterMap = fDalitzmap[fullTrack.globalIndex()]; filterMapProbe = fDalitzmapProbe[fullTrack.globalIndex()]; if (fConfigOptions.fRemoveDoubleCounting) { // we remove track selections which were already selected before - uint8_t previousFilterMap = fDalitzmapAmbiguity[fullTrack.globalIndex()]; - uint8_t previousFilterMapProbe = fDalitzmapProbeAmbiguity[fullTrack.globalIndex()]; - filterMap &= ~previousFilterMap; - filterMapProbe &= ~previousFilterMapProbe; + uint8_t currentFilterMap = fDalitzmapAmbiguity[fullTrack.globalIndex()]; + uint8_t currentFilterMapProbe = fDalitzmapProbeAmbiguity[fullTrack.globalIndex()]; + filterMap = currentFilterMap & ~filterMap; + filterMapProbe = currentFilterMapProbe & ~filterMapProbe; + // Then only we can fill the final map + fDalitzmap[fullTrack.globalIndex()] |= fDalitzmapAmbiguity[fullTrack.globalIndex()]; + fDalitzmapProbe[fullTrack.globalIndex()] |= fDalitzmapProbeAmbiguity[fullTrack.globalIndex()]; } if (!filterMap && !filterMapProbe) { @@ -537,7 +611,6 @@ struct DalitzSelection { bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); if (isEventSelected) { - reinterpret_cast(fStatsList->At(0))->Fill(0); auto bc = collision.template bc_as(); @@ -548,13 +621,17 @@ struct DalitzSelection { } auto groupedFilteredTracks = filteredTracks.sliceBy(perCollision, collision.globalIndex()); - runTrackSelection(groupedFilteredTracks, nullptr); - runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks, nullptr); + runTrackSelection(groupedFilteredTracks, nullptr); + if (!fSkipEvent) { + runDalitzPairing(groupedFilteredTracks, groupedFilteredTracks, nullptr); + } } } - for (const auto& track : tracks) { // Fill dalitz bits - dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + if (fIsOutputRequested) { + for (const auto& track : tracks) { // Fill dalitz bits + dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + } } } @@ -587,13 +664,60 @@ struct DalitzSelection { } auto groupedTracksAssoc = trackAssocs.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - runTrackSelection(groupedTracksAssoc, collision); - runDalitzPairing(groupedTracksAssoc, groupedTracksAssoc, collision); + runTrackSelection(groupedTracksAssoc, collision); + if (!fSkipEvent) { + runDalitzPairing(groupedTracksAssoc, groupedTracksAssoc, collision); + } } } - for (const auto& track : tracks) { // Fill dalitz bits - dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + if (fIsOutputRequested) { + for (const auto& track : tracks) { // Fill dalitz bits + dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + } + } + } + + void processFullTracksWithAssocNoTOF(MyEventsWithCent const& collisions, aod::BCsWithTimestamps const&, MyBarrelTracksNoTOF const& tracks, TrackAssoc const& trackAssocs) + { + + const int pairType = VarManager::kDecayToEE; + fDalitzmap.clear(); + fDalitzmapProbe.clear(); + fDalitzmapAmbiguity.clear(); + fDalitzmapProbeAmbiguity.clear(); + fAmbiguousPairs.clear(); + + for (const auto& collision : collisions) { + fTrackmap.clear(); + fTrackmapProbe.clear(); + VarManager::ResetValues(VarManager::kNRunWiseVariables, VarManager::kNBarrelTrackVariables); + VarManager::FillEvent(collision); + bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); + + if (isEventSelected) { + + reinterpret_cast(fStatsList->At(0))->Fill(0); + + auto bc = collision.template bc_as(); + + if (fCurrentRun != bc.runNumber()) { + initNewRun(bc.timestamp()); + fCurrentRun = bc.runNumber(); + } + + auto groupedTracksAssoc = trackAssocs.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + runTrackSelection(groupedTracksAssoc, collision); + if (!fSkipEvent) { + runDalitzPairing(groupedTracksAssoc, groupedTracksAssoc, collision); + } + } + } + + if (fIsOutputRequested) { + for (const auto& track : tracks) { // Fill dalitz bits + dalitzbits(fIsTagAndProbe ? fDalitzmapProbe[track.globalIndex()] : fDalitzmap[track.globalIndex()]); + } } } @@ -601,6 +725,7 @@ struct DalitzSelection { { } + PROCESS_SWITCH(DalitzSelection, processFullTracksWithAssocNoTOF, "Run Dalitz selection on AO2D tables with reassociation and without TOF PID", false); PROCESS_SWITCH(DalitzSelection, processFullTracksWithAssoc, "Run Dalitz selection on AO2D tables with reassociation", false); PROCESS_SWITCH(DalitzSelection, processFullTracks, "Run Dalitz selection on AO2D tables", false); PROCESS_SWITCH(DalitzSelection, processDummy, "Do nothing", false); From 54c471f791cf9fa20163a698e2ace901cb0a16a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Wed, 27 May 2026 16:07:40 +0200 Subject: [PATCH 309/449] [PWGUD] Fix includes (#16416) --- PWGUD/DataModel/UDTruegapsideTables.h | 9 --------- PWGUD/TableProducer/trueGapProducer.cxx | 2 -- PWGUD/TableProducer/upcCandProducerSemiFwd.cxx | 5 +++++ PWGUD/Tasks/flowLongRangeCorrUpc.cxx | 4 +++- PWGUD/Tasks/upcFwdJpsiRl.cxx | 6 ++++-- PWGUD/Tasks/upcSemiFwdJpsiRl.cxx | 5 +++-- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/PWGUD/DataModel/UDTruegapsideTables.h b/PWGUD/DataModel/UDTruegapsideTables.h index 79255e3dc78..e0d2ff0d639 100644 --- a/PWGUD/DataModel/UDTruegapsideTables.h +++ b/PWGUD/DataModel/UDTruegapsideTables.h @@ -19,15 +19,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include namespace o2::aod { diff --git a/PWGUD/TableProducer/trueGapProducer.cxx b/PWGUD/TableProducer/trueGapProducer.cxx index bb059d15b78..da5a6e45203 100644 --- a/PWGUD/TableProducer/trueGapProducer.cxx +++ b/PWGUD/TableProducer/trueGapProducer.cxx @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include #include #include diff --git a/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx b/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx index 958c2e8e796..cb6146aee7b 100644 --- a/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx +++ b/PWGUD/TableProducer/upcCandProducerSemiFwd.cxx @@ -20,6 +20,10 @@ #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include #include #include @@ -45,6 +49,7 @@ #include #include +#include #include #include #include diff --git a/PWGUD/Tasks/flowLongRangeCorrUpc.cxx b/PWGUD/Tasks/flowLongRangeCorrUpc.cxx index 4b2aafbdaf4..bf6bc60ef98 100644 --- a/PWGUD/Tasks/flowLongRangeCorrUpc.cxx +++ b/PWGUD/Tasks/flowLongRangeCorrUpc.cxx @@ -21,6 +21,7 @@ #include "Common/Core/RecoDecay.h" +#include #include #include // o2::ft0::Geometry #include @@ -35,9 +36,10 @@ #include #include +#include #include -#include +#include #include #include #include diff --git a/PWGUD/Tasks/upcFwdJpsiRl.cxx b/PWGUD/Tasks/upcFwdJpsiRl.cxx index 8f42e1e8cb4..82a21c69137 100644 --- a/PWGUD/Tasks/upcFwdJpsiRl.cxx +++ b/PWGUD/Tasks/upcFwdJpsiRl.cxx @@ -29,14 +29,16 @@ #include #include #include +#include #include #include #include #include #include -#include -#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include diff --git a/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx b/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx index eb77adce860..e9e1dfe834a 100644 --- a/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx +++ b/PWGUD/Tasks/upcSemiFwdJpsiRl.cxx @@ -32,8 +32,9 @@ #include #include -#include -#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include From 4a4e3f0dd9dae050bdbf5658564a65144dcef58f Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Wed, 27 May 2026 16:48:20 +0200 Subject: [PATCH 310/449] [PWGHF] Add track info in Sc task output. (#16418) Co-authored-by: Mattia Faggin --- PWGHF/D2H/Tasks/taskSigmac.cxx | 622 ++++++++++++++++++++++++++++----- 1 file changed, 533 insertions(+), 89 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index 8bfbff280cb..1cb94c20c5c 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -67,11 +67,15 @@ struct HfTaskSigmac { Configurable addSoftPiDcaToSigmacSparse{"addSoftPiDcaToSigmacSparse", false, "enable the filling of soft-pion dcaXY, dcaZ in the Σc0,++ THnSparse"}; Configurable addMassDiffAbsLambdaCToSigmacSparse{"addMassDiffAbsLambdaCToSigmacSparse", false, "enable the filling of |M(pkpi, piKp) - M(LambdaC)| in the Σc0,++ THnSparse"}; Configurable deltaMassSigmacRecoMax{"deltaMassSigmacRecoMax", 1000, "Maximum allowed value for Sigmac deltaMass. Conceived to reduce the output size (i.e. reject background above a certain threshold)"}; + Configurable ptMinSc{"ptMinSc", -1.f, "Minimum accepted value for SigmaC-hadron pt (GeV/c)"}; bool isMc{}; + bool storeTrackProp{}; static constexpr std::size_t NDaughters{2u}; using RecoLc = soa::Join; + using TracksWithExtra = soa::Join; + using TracksWMcWithExtra = soa::Join; /// THn for candidate Λc+ and Σc0,++ cut variation ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {16, 0, 16}, ""}; @@ -87,6 +91,9 @@ struct HfTaskSigmac { ConfigurableAxis thnConfigAxisBdtScoreLcNonPrompt{"thnConfigAxisBdtScoreLcNonPrompt", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisSoftPiAbsDca{"thnConfigAxisSoftPiAbsDca", {14, 0., 0.07}, ""}; ConfigurableAxis thnConfigAxisMassDiffAbsLambdaC{"thnConfigAxisMassDiffAbsLambdaC", {12, 0, 0.06}, ""}; + ConfigurableAxis thnConfigAxisAbsEtaTrackMin{"thnConfigAxisAbsEtaTrackMin", {3, 0.f, 0.3f}, "min |#it{#eta_{track}}|"}; + ConfigurableAxis thnConfigAxisNumItsClsMin{"thnConfigAxisNumItsClsMin", {4, 3.5f, 7.5f}, "min #it{N}_{cls ITS}"}; + ConfigurableAxis thnConfigAxisNumTpcClsMin{"thnConfigAxisNumTpcClsMin", {3, 79.5f, 140.5f}, "min #it{N}_{cls TPC}"}; /// analysis histograms HistogramRegistry registry{ @@ -136,27 +143,40 @@ struct HfTaskSigmac { void init(InitContext&) { - /// To be considered in the future, let's keep the possibility to run in MC also with "data-like" mode (just for TH1 objects) - // std::array processes {doprocessDataWoMl, doprocessDataWithMl, doprocessMcWoMl, doprocessMcWithMl}; - // if( std::accumulate(processes.begin(), processes.end(), 0) != 1 ) { - // LOG(fatal) << "One and only one process function must be enabled. Fix it!"; - // } - - // avoid 2 enabled process functions on data - if (doprocessDataWoMl && doprocessDataWithMl) { - LOG(fatal) << "processDataWoMl and processDataWithMl both enabled. Fix it!"; + // avoid more than one enabled process functions on data + std::array processesData = {doprocessDataWoMl, doprocessDataWithMl, doprocessDataWithMlWithTrackInfo}; + if (std::accumulate(processesData.begin(), processesData.end(), 0) > 1) { + LOG(fatal) << "one and only one process function in data can be enabled. Fix it!"; } - // avoid 2 enabled process functions on MC - if (doprocessMcWoMl && doprocessMcWithMl) { - LOG(fatal) << "processMcWoMl and processMcWithMl both enabled. Fix it!"; + // avoid more than one enabled process functions on MC + std::array processesMc = {doprocessMcWoMl, doprocessMcWithMl, doprocessMcWithMlWithTrackInfo}; + if (std::accumulate(processesMc.begin(), processesMc.end(), 0) > 1) { + LOG(fatal) << "one and only one process function in MC can be enabled. Fix it!"; } // avoid that in data no ML is used while in MC yes, and viceversa - if ((doprocessDataWithMl && doprocessMcWoMl) || (doprocessDataWoMl && doprocessMcWithMl)) { + if (((doprocessDataWithMl || doprocessDataWithMlWithTrackInfo) && doprocessMcWoMl) || (doprocessDataWoMl && (doprocessMcWithMl || doprocessMcWithMlWithTrackInfo))) { LOG(fatal) << "process functions with and w/o ML enabled not consistently between data and MC. Fix it! processDataWoMl: " << doprocessDataWoMl << "processDataWithMl: " << doprocessDataWithMl << "processMcWoMl: " << doprocessMcWoMl << "processMcWithMl: " << doprocessMcWithMl; } + // avoid that in data track info get stored while in MC not, and viceversa + if ((doprocessDataWithMlWithTrackInfo && doprocessMcWithMl) || (doprocessDataWithMl && doprocessMcWithMlWithTrackInfo)) { + LOG(fatal) << "process functions with and w/o storage of track information enabled not consistently between data and MC. Fix it! processDataWithMlWithTrackInfo: " << doprocessDataWithMlWithTrackInfo << "processDataWithMl: " << doprocessDataWithMl << "processMcWithMlWithTrackInfo: " << doprocessMcWithMlWithTrackInfo << "processMcWithMl: " << doprocessMcWithMl; + } + /// establish if the analysis is done on Data or MC - isMc = doprocessMcWoMl || doprocessMcWithMl; + isMc = doprocessMcWoMl || doprocessMcWithMl || doprocessMcWithMlWithTrackInfo; + + /// establish if the output THnSparse should include track information + storeTrackProp = doprocessDataWithMlWithTrackInfo || doprocessMcWithMlWithTrackInfo; + + LOG(info) << "### doprocessDataWoMl: " << doprocessDataWoMl; + LOG(info) << "### doprocessDataWithMl: " << doprocessDataWithMl; + LOG(info) << "### doprocessDataWithMlWithTrackInfo: " << doprocessDataWithMlWithTrackInfo; + LOG(info) << "### doprocessMcWoMl: " << doprocessMcWoMl; + LOG(info) << "### doprocessMcWithMl: " << doprocessMcWithMl; + LOG(info) << "### doprocessMcWithMlWithTrackInfo: " << doprocessMcWithMlWithTrackInfo; + LOG(info) << "+++ isMc: " << isMc; + LOG(info) << "+++ storeTrackProp: " << storeTrackProp; const AxisSpec thnAxisMassLambdaC{configAxisMassLambdaC, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPtLambdaC{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"}; @@ -180,6 +200,9 @@ struct HfTaskSigmac { const AxisSpec thnAxisSigmaCParticleAntiparticle = {o2::aod::hf_cand_sigmac::Conjugated::NConjugated, -0.5f, +o2::aod::hf_cand_sigmac::Conjugated::NConjugated - 0.5f, "bin 1: particle, bin 2: antiparticle"}; const AxisSpec axisDeltaMassSigmaC{configAxisDeltaMassSigmaC, "#it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2})"}; const AxisSpec thnAxisMassDiffAbsLambdaC{thnConfigAxisMassDiffAbsLambdaC, "|#it{M}(pK#pi or piK#pi) - #it{M}(#Lambda_{c})| (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisAbsEtaTrackMin{thnConfigAxisAbsEtaTrackMin, "min |#it{#eta_{track}}|"}; + const AxisSpec thnAxisNumItsClsMin{thnConfigAxisNumItsClsMin, "min #it{N}_{cls ITS}"}; + const AxisSpec thnAxisNumTpcClsMin{thnConfigAxisNumTpcClsMin, "min #it{N}_{cls TPC}"}; registry.add("Data/hDeltaMassSc0", "#Sigma_{c}^{0} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{0}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); registry.add("Data/hDeltaMassScPlusPlus", "#Sigma_{c}^{++} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{++}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); registry.add("Data/hDeltaMassSc0PlusPlus", "#Sigma_{c}^{0,++} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); @@ -291,14 +314,22 @@ struct HfTaskSigmac { /// THn for candidate Λc+ and Σc0,++ cut variation if (enableTHnSc || enableTHnLc) { + + /// force the setting of a minimum pt value for SigmaC in case we want to store the track info, to reduce the output size + if (storeTrackProp && ptMinSc < 0.f) { + LOG(fatal) << "Storage of track properties enabled, but no constraints on minimum pt(Sc) are defined. Please specify the minimum pt for Sc candidates to be stored in the output THnSparse"; + } + std::vector axesLambdaCWithMl = {thnAxisPtLambdaC, thnAxisMassLambdaC, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcNonPrompt, thnAxisOriginMc, thnAxisChannel}; std::vector axesSigmaCWithMl = {thnAxisPtLambdaC, axisDeltaMassSigmaC, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcNonPrompt, thnAxisOriginMc, thnAxisChannel, thnAxisPtSigmaC, thnAxisChargeSigmaC}; std::vector axesLambdaCWoMl = {thnAxisPtLambdaC, thnAxisMassLambdaC, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisCPAXY, thnAxisOriginMc, thnAxisChannel}; std::vector axesSigmaCWoMl = {thnAxisPtLambdaC, axisDeltaMassSigmaC, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisCPAXY, thnAxisOriginMc, thnAxisChannel, thnAxisPtSigmaC, thnAxisChargeSigmaC}; if (isMc) { + /// MC analysis registry.add("MC/generated/hnLambdaCGen", "THn for Lambdac gen", HistType::kTHnSparseF, {thnAxisGenPtLambdaC, thnAxisGenPtLambdaCBMother, thnAxisOriginMc, thnAxisChannel}); registry.add("MC/generated/hnSigmaCGen", "THn for Sigmac gen", HistType::kTHnSparseF, {thnAxisGenPtSigmaC, thnAxisGenPtSigmaCBMother, thnAxisOriginMc, thnAxisChannel, thnAxisGenPtLambdaC, thnAxisChargeSigmaC, thnAxisGenSigmaCSpecies, thnAxisSigmaCParticleAntiparticle}); - if (doprocessMcWithMl) { + if (doprocessMcWithMl || doprocessMcWithMlWithTrackInfo) { + /// MC analysis with ML info axesLambdaCWithMl.push_back(thnAxisGenPtLambdaCBMother); axesSigmaCWithMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWithMl.push_back(thnAxisGenSigmaCSpecies); @@ -310,6 +341,14 @@ struct HfTaskSigmac { if (addMassDiffAbsLambdaCToSigmacSparse) { axesSigmaCWithMl.push_back(thnAxisMassDiffAbsLambdaC); } + if (storeTrackProp) { + axesLambdaCWithMl.push_back(thnAxisAbsEtaTrackMin); + axesSigmaCWithMl.push_back(thnAxisAbsEtaTrackMin); + axesLambdaCWithMl.push_back(thnAxisNumItsClsMin); + axesSigmaCWithMl.push_back(thnAxisNumItsClsMin); + axesLambdaCWithMl.push_back(thnAxisNumTpcClsMin); + axesSigmaCWithMl.push_back(thnAxisNumTpcClsMin); + } // enable THnSparse for Λc+ if (enableTHnLc) { registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); @@ -319,6 +358,7 @@ struct HfTaskSigmac { registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); } } else { + /// MC analysis w/o ML info axesLambdaCWoMl.push_back(thnAxisGenPtLambdaCBMother); axesSigmaCWoMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWoMl.push_back(thnAxisGenSigmaCSpecies); @@ -340,7 +380,9 @@ struct HfTaskSigmac { } } } else { - if (doprocessDataWithMl) { + /// data analysis + if (doprocessDataWithMl || doprocessDataWithMlWithTrackInfo) { + /// data analysis with ML info if (addSoftPiDcaToSigmacSparse) { axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaZ); @@ -348,6 +390,14 @@ struct HfTaskSigmac { if (addMassDiffAbsLambdaCToSigmacSparse) { axesSigmaCWithMl.push_back(thnAxisMassDiffAbsLambdaC); } + if (storeTrackProp) { + axesLambdaCWithMl.push_back(thnAxisAbsEtaTrackMin); + axesSigmaCWithMl.push_back(thnAxisAbsEtaTrackMin); + axesLambdaCWithMl.push_back(thnAxisNumItsClsMin); + axesSigmaCWithMl.push_back(thnAxisNumItsClsMin); + axesLambdaCWithMl.push_back(thnAxisNumTpcClsMin); + axesSigmaCWithMl.push_back(thnAxisNumTpcClsMin); + } // enable THnSparse for Λc+ if (enableTHnLc) { registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); @@ -357,6 +407,7 @@ struct HfTaskSigmac { registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); } } else { + /// data analysis w/o ML info if (addSoftPiDcaToSigmacSparse) { axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaZ); @@ -378,13 +429,38 @@ struct HfTaskSigmac { }; /// end init + /// @brief Function to retrieve information about track properties + /// @param prongTracks is the vector of daughter tracks + /// @param etaMin is the minimum eta + /// @param nItsClsMin is the minumum number of clusters in ITS + /// @param nTpcClsMin is the minumum number of clusters in TPC + template + void getTrackingInfo(std::vector const& prongTracks, float& etaMin, int& nItsClsMin, int& nTpcClsMin) + { + etaMin = 10.f; + nItsClsMin = 10; + nTpcClsMin = 1000; + + for (const auto& track : prongTracks) { + if (std::abs(track.eta()) < etaMin) { + etaMin = std::abs(track.eta()); + } + if (track.itsNCls() < nItsClsMin) { + nItsClsMin = track.itsNCls(); + } + if (track.tpcNClsCrossedRows() < nTpcClsMin) { + nTpcClsMin = track.tpcNClsCrossedRows(); + } + } + } + /// @brief function to fill the histograms needed in analysis (data) /// @param candidatesSc are the reconstructed candidate Σc0,++ /// @param - template + template void fillHistosData(aod::HfCandSc const& candidatesSc, CandsLc const& candidatesLc, - aod::Tracks const&) + TRK const&) { /// loop over the candidate Σc0,++ @@ -408,9 +484,14 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1().pt()), etaSoftPi(candSc.prong1().eta()), phiSoftPi(candSc.prong1().phi()); + const auto& trackSoftPi = candSc.template prong1_as(); + double ptSoftPi(trackSoftPi.pt()), etaSoftPi(trackSoftPi.eta()), phiSoftPi(trackSoftPi.phi()); double decLengthLc(candidateLc.decayLength()), decLengthXYLc(candidateLc.decayLengthXY()); double cpaLc(candidateLc.cpa()), cpaXYLc(candidateLc.cpaXY()); + /// exclude already candidate Σc0,++ outside the accepted pt range + if (ptMinSc > 0.f && ptSc < ptMinSc) { + continue; + } /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder if (TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); @@ -485,27 +566,68 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } } } else { @@ -611,27 +733,68 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } } } else { @@ -685,7 +848,28 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0); + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info note stored + /// optional axes enabled: none + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0); + } } else { /// fill w/o BDT information registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0); @@ -701,7 +885,28 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0); + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info note stored + /// optional axes enabled: none + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), 0, 0); + } } else { /// fill w/o BDT information registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0); @@ -734,13 +939,13 @@ struct HfTaskSigmac { /// @param candidatesSc are the reconstructed candidate Σc0,++ with MC info /// @param mcParticles are the generated particles with flags wheter they are Σc0,++ or not /// @param - template + template void fillHistosMc(soa::Join const& candidatesSc, soa::Join const& mcParticlesSc, soa::Join const& mcParticlesLc, aod::McParticles const& mcParticles, // this establishes the type of particle obtained with the .mcParticle() getter CandsLc const& candidatesLc, - aod::TracksWMc const&) + TRK const&) { /// loop over Sc generated particles @@ -786,6 +991,10 @@ struct HfTaskSigmac { /// Get information about origin (prompt, non-prompt) /// Get information about decay Λc+ channel (direct, resonant) double ptGenSc(particle.pt()), etaGenSc(particle.eta()), phiGenSc(particle.phi()); + /// exclude already candidate Σc0,++ outside the accepted pt range + if (ptMinSc > 0.f && ptGenSc < ptMinSc) { + continue; + } double ptGenScBMother(-1.); auto arrayDaughtersIds = particle.daughtersIds(); if (arrayDaughtersIds.size() != NDaughters) { @@ -970,21 +1179,21 @@ struct HfTaskSigmac { int indexMcScRec = -1; if (isTrueSc0Reco) { // Σc0(2455) - indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaC0, true); + indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaC0, true); sigmacSpecies = o2::aod::hf_cand_sigmac::Sc2455; } else if (isTrueScStar0Reco) { // Σc0(2520) - indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCStar0, true); + indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCStar0, true); sigmacSpecies = o2::aod::hf_cand_sigmac::Sc2520; } auto particleSc = mcParticles.rawIteratorAt(indexMcScRec); // Get the corresponding MC particle for Lc - auto arrayDaughtersLc = std::array{candidateLc.template prong0_as(), candidateLc.template prong1_as(), candidateLc.template prong2_as()}; + auto arrayDaughtersLc = std::array{candidateLc.template prong0_as(), candidateLc.template prong1_as(), candidateLc.template prong2_as()}; int8_t sign = 0; int const indexMcLcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, o2::constants::physics::Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); auto particleLc = mcParticles.rawIteratorAt(indexMcLcRec); // Get the corresponding MC particle for soft pion - auto particleSoftPi = candSc.prong1_as().mcParticle(); + auto particleSoftPi = candSc.prong1_as().mcParticle(); // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ @@ -992,16 +1201,20 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); + double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); double ptGenSc(particleSc.pt()), ptGenLc(particleLc.pt()), ptGenSoftPi(particleSoftPi.pt()); double decLengthLc(candidateLc.decayLength()), decLengthXYLc(candidateLc.decayLengthXY()); double cpaLc(candidateLc.cpa()), cpaXYLc(candidateLc.cpaXY()); int const origin = candSc.originMcRec(); auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± channel = remapResoChannelLc(channel); + /// exclude already candidate Σc0,++ outside the accepted pt range + if (ptMinSc > 0.f && ptSc < ptMinSc) { + continue; + } /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); massLc = HfHelper::invMassLcToPKPi(candidateLc); massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candidateLc)); @@ -1075,27 +1288,69 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + const auto& trackSoftPi = candSc.template prong1_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } else { @@ -1128,7 +1383,7 @@ struct HfTaskSigmac { } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { massSc = HfHelper::invMassScRecoLcToPiKP(candSc, candidateLc); massLc = HfHelper::invMassLcToPiKP(candidateLc); massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candidateLc)); @@ -1202,27 +1457,69 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + const auto& trackSoftPi = candSc.template prong1_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } else { @@ -1261,21 +1558,21 @@ struct HfTaskSigmac { int indexMcScRec = -1; if (isTrueScPlusPlusReco) { // Σc0(2455) - indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCPlusPlus, true); + indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCPlusPlus, true); sigmacSpecies = o2::aod::hf_cand_sigmac::Sc2455; } else if (isTrueScStarPlusPlusReco) { // Σc0(2520) - indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCStarPlusPlus, true); + indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), o2::constants::physics::Pdg::kSigmaCStarPlusPlus, true); sigmacSpecies = o2::aod::hf_cand_sigmac::Sc2520; } auto particleSc = mcParticles.rawIteratorAt(indexMcScRec); // Get the corresponding MC particle for Lc - auto arrayDaughtersLc = std::array{candidateLc.template prong0_as(), candidateLc.template prong1_as(), candidateLc.template prong2_as()}; + auto arrayDaughtersLc = std::array{candidateLc.template prong0_as(), candidateLc.template prong1_as(), candidateLc.template prong2_as()}; int8_t sign = 0; int const indexMcLcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, o2::constants::physics::Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); auto particleLc = mcParticles.rawIteratorAt(indexMcLcRec); // Get the corresponding MC particle for soft pion - auto particleSoftPi = candSc.prong1_as().mcParticle(); + auto particleSoftPi = candSc.prong1_as().mcParticle(); // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ @@ -1283,7 +1580,7 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); + double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); double ptGenSc(particleSc.pt()), ptGenLc(particleLc.pt()), ptGenSoftPi(particleSoftPi.pt()); double decLengthLc(candidateLc.decayLength()), decLengthXYLc(candidateLc.decayLengthXY()); double cpaLc(candidateLc.cpa()), cpaXYLc(candidateLc.cpaXY()); @@ -1292,7 +1589,7 @@ struct HfTaskSigmac { channel = remapResoChannelLc(channel); /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); massLc = HfHelper::invMassLcToPKPi(candidateLc); massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candidateLc)); @@ -1366,27 +1663,69 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + const auto& trackSoftPi = candSc.template prong1_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } else { @@ -1419,7 +1758,7 @@ struct HfTaskSigmac { } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { massSc = HfHelper::invMassScRecoLcToPiKP(candSc, candidateLc); massLc = HfHelper::invMassLcToPiKP(candidateLc); massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candidateLc)); @@ -1491,27 +1830,69 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + const auto& trackSoftPi = candSc.template prong1_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2, trackSoftPi}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } if (addSoftPiDcaToSigmacSparse) { /// dcaXY,Z of soft pion track stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: dcaXY_softPi, dcaZ_softPi - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } } else { /// dcaXY,Z of soft pion track not stored if (addMassDiffAbsLambdaCToSigmacSparse) { /// difference |candidate mass - Lc mass| stored - /// optional axes enabled: massDiffLc - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } } else { /// difference |candidate mass - Lc mass| not stored - /// optional axes enabled: none - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } else { @@ -1562,8 +1943,8 @@ struct HfTaskSigmac { auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± channel = remapResoChannelLc(channel); int pdgAbs = -1; - if (candidateLc.template prong0_as().has_mcParticle()) { - pdgAbs = std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()); + if (candidateLc.template prong0_as().has_mcParticle()) { + pdgAbs = std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()); } if (candidateLc.isSelLcToPKPi() >= 1 && pdgAbs == kProton) { massLc = HfHelper::invMassLcToPKPi(candidateLc); @@ -1575,7 +1956,28 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart()); + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart(), absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart()); + } } else { /// fill w/o BDT information registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, candidateLc.ptBhadMotherPart()); @@ -1591,7 +1993,28 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart()); + /// track properties + float absEtaTrackMin{-1.f}; + int numItsClsMin{-1}, numTpcClsMin{-1}; + if constexpr (std::is_same_v) { + if (!storeTrackProp) { + /// this should never happen + LOG(fatal) << "getting track info but storeTrackProp=" << storeTrackProp << ". Not possible! Aborting ..."; + } + const auto& trackLcProng0 = candidateLc.template prong0_as(); + const auto& trackLcProng1 = candidateLc.template prong1_as(); + const auto& trackLcProng2 = candidateLc.template prong2_as(); + getTrackingInfo(std::vector{trackLcProng0, trackLcProng1, trackLcProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin); + } + if (storeTrackProp) { + /// track info stored + /// optional axes enabled: trackEtaMin, trackItsClstMin, trackTpcClstMin + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart(), absEtaTrackMin, numItsClsMin, numTpcClsMin); + } else { + /// track info not stored + /// optional axes enabled: none + registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, outputMl.at(0), outputMl.at(1), origin, channel, candidateLc.ptBhadMotherPart()); + } } else { /// fill w/o BDT information registry.get(HIST("hnLambdaC"))->Fill(ptLc, massLc, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, candidateLc.ptBhadMotherPart()); @@ -1621,6 +2044,15 @@ struct HfTaskSigmac { } PROCESS_SWITCH(HfTaskSigmac, processDataWithMl, "Process data with ML information on Lc", false); + /// @brief process function to fill the histograms needed in analysis with ML information (data), with specific settings to store single-track properties + void processDataWithMlWithTrackInfo(aod::HfCandSc const& candidatesSc, + soa::Join const& candidatesLc, + TracksWithExtra const& tracks) + { + fillHistosData(candidatesSc, candidatesLc, tracks); + } + PROCESS_SWITCH(HfTaskSigmac, processDataWithMlWithTrackInfo, "Process data with ML information on Lc, including also information about track properties", false); + /// @brief process function to fill the histograms needed in analysis w/o ML information (MC) void processMcWoMl(soa::Join const& candidatesSc, soa::Join const& mcParticlesSc, @@ -1644,6 +2076,18 @@ struct HfTaskSigmac { fillHistosMc(candidatesSc, mcParticlesSc, mcParticlesLc, mcParticles, candidatesLc, tracksWithMc); } PROCESS_SWITCH(HfTaskSigmac, processMcWithMl, "Process MC with ML information on Lc", false); + + /// @brief process function to fill the histograms needed in analysis with ML information (MC), with specific settings to store single-track properties + void processMcWithMlWithTrackInfo(soa::Join const& candidatesSc, + soa::Join const& mcParticlesSc, + soa::Join const& mcParticlesLc, + aod::McParticles const& mcParticles, // this establishes the type of particle obtained with the .mcParticle() getter + soa::Join const& candidatesLc, + TracksWMcWithExtra const& tracksWithMc) + { + fillHistosMc(candidatesSc, mcParticlesSc, mcParticlesLc, mcParticles, candidatesLc, tracksWithMc); + } + PROCESS_SWITCH(HfTaskSigmac, processMcWithMlWithTrackInfo, "Process MC with ML information on Lc, including also information about track properties", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 45caa2dbeced7b6aee9b55515ec918780d05f573 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Wed, 27 May 2026 17:24:42 +0200 Subject: [PATCH 311/449] [PWGCF] Fixes in femto framework (#16422) --- PWGCF/Femto/Core/pairHistManager.h | 9 +++---- PWGCF/Femto/Core/trackHistManager.h | 38 ++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index dcea12be2b7..68e8d2d01fd 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -28,7 +28,6 @@ #include #include -#include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include @@ -563,7 +562,7 @@ class PairHistManager // compute true kinematics mTrueKt = getKt(mTrueParticle1, mTrueParticle2); mTrueMt = getMt(mTrueParticle1, mTrueParticle2); - mTrueMt = getMinv(mTrueParticle1, mTrueParticle2); + mTrueMinv = getMinv(mTrueParticle1, mTrueParticle2); mTrueKstar = getKstar(mTrueParticle1, mTrueParticle2); } @@ -969,9 +968,9 @@ class PairHistManager const double tPt = std::sqrt(tPx * tPx + tPy * tPy); const double tMt = std::sqrt(tE * tE - tPz * tPz); - static constexpr double kMinTransverseMomentum = 1e-9; - if (tPt < kMinTransverseMomentum || tMt < kMinTransverseMomentum) { - return {0.0, 0.0, 0.0}; + static constexpr double MinTransverseMomentum = 1e-9; + if (tPt < MinTransverseMomentum || tMt < MinTransverseMomentum) { + return {0.0f, 0.0f, 0.0f}; } const double betaL = tPz / tE; diff --git a/PWGCF/Femto/Core/trackHistManager.h b/PWGCF/Femto/Core/trackHistManager.h index 9ce323841c1..c01704a4f4b 100644 --- a/PWGCF/Femto/Core/trackHistManager.h +++ b/PWGCF/Femto/Core/trackHistManager.h @@ -73,6 +73,8 @@ enum TrackHist { kPtVsDcaxy, kPtVsDcaz, kPtVsDca, + kPtVsDcaxyVsDcaz, // DCAxy vs DCAz vs pt for extraction of particle fraction + kPVsPTpc, // its pid kItsSignal, kItsElectron, @@ -199,6 +201,7 @@ struct ConfTrackQaBinning : o2::framework::ConfigurableGroup { o2::framework::Configurable plotHeliumPid{"plotHeliumPid", true, "Generate plots for Helium PID"}; o2::framework::Configurable plotOrigins{"plotOrigins", true, "MC ONLY: Plot pt vs DCAxy vs DCAz for different particle origins"}; o2::framework::Configurable> pdgCodesForMothersOfSecondary{"pdgCodesForMothersOfSecondary", {3122}, "MC ONLY: PDG codes of mothers of secondaries (Max 3 will be considered)"}; + o2::framework::Configurable plotDcaCorrelation{"plotDcaCorrelation", true, "Plot pt vs DCAxy vs DCAz"}; o2::framework::ConfigurableAxis itsCluster{"itsCluster", {{8, -0.5, 7.5}}, "ITS cluster"}; o2::framework::ConfigurableAxis itsClusterIb{"itsClusterIb", {{4, -0.5, 3.5}}, "ITS cluster in inner barrel"}; o2::framework::ConfigurableAxis tpcCrossedRows{"tpcCrossedRows", {{161, -0.5, 160.5}}, "TPC cluster"}; @@ -209,7 +212,7 @@ struct ConfTrackQaBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis dcaXy{"dcaXy", {{300, -0.3, 0.3}}, "DCA_xy"}; o2::framework::ConfigurableAxis dcaZ{"dcaZ", {{300, -0.3, 0.3}}, "DCA_Z"}; o2::framework::ConfigurableAxis dca{"dca", {{300, 0, 0.3}}, "DCA"}; - o2::framework::ConfigurableAxis p{"p", {{300, 0, 6}}, "Momentum axis"}; + o2::framework::ConfigurableAxis p{"p", {{300, 0, 6}}, "Momentum axis. Used for all PID histograms and momentum correlation histogram"}; o2::framework::ConfigurableAxis itsSignal{"itsSignal", {{150, 0, 15}}, "ITS Signal"}; o2::framework::ConfigurableAxis itsElectron{"itsElectron", {{300, -3, 3}}, "ITS PID for electron"}; o2::framework::ConfigurableAxis itsPion{"itsPion", {{300, -3, 3}}, "ITS PID for pion"}; @@ -306,6 +309,8 @@ constexpr std::array, kTrackHistLast> {kPtVsDcaxy, o2::framework::HistType::kTH2F, "hPtVsDcaxy", "p_{T} vs DCA_{XY}; p_{T} (GeV/#it{c}); DCA_{XY} (cm)"}, {kPtVsDcaz, o2::framework::HistType::kTH2F, "hPtVsDcaz", "p_{T} vs DCA_{Z}; p_{T} (GeV/#it{c}); DCA_{Z} (cm)"}, {kPtVsDca, o2::framework::HistType::kTH2F, "hPtVsDca", "p_{T} vs DCA; p_{T} (GeV/#it{c}); DCA (cm)"}, + {kPtVsDcaxyVsDcaz, o2::framework::HistType::kTHnSparseF, "hPtVsDcaxyVsDcaz", "Transverse momentum vs DCA_{xy} vs DCA_{z}; p_{T} (GeV/#it{c}); DCA_{XY} (cm); DCA_{Z} (cm);"}, + {kPVsPTpc, o2::framework::HistType::kTH2F, "hPVsPTpc", "Correlation p_{global} and p_{TPC}; p_{global} (GeV/#it{c}); p_{tpc} (GeV/#it{c})"}, {kItsSignal, o2::framework::HistType::kTH2F, "hItsSignal", "ITS Signal; p (GeV/#it{c}) ; x "}, {kItsElectron, o2::framework::HistType::kTH2F, "hItsPidElectron", "ITS PID Electron; p (GeV/#it{c}) ; n#sigma_{TPC,el}"}, {kItsPion, o2::framework::HistType::kTH2F, "hItsPidPion", "ITS PID Pion; p (GeV/#it{c}) ; n#sigma_{ITS,pi}"}, @@ -352,15 +357,15 @@ constexpr std::array, kTrackHistLast> {kTruePtVsPt, o2::framework::HistType::kTH2F, "hTruePtVsPt", "True transverse momentum vs transverse momentum; p_{T,True} (GeV/#it{c}); p_{T,True} (GeV/#it{c})"}, {kTrueEtaVsEta, o2::framework::HistType::kTH2F, "hTrueEtaVsEta", "True pseudorapdity vs pseudorapdity; #eta_{True}; #eta"}, {kTruePhiVsPhi, o2::framework::HistType::kTH2F, "hTruePhiVsPhi", "True azimuthal angle vs azimuthal angle; #varphi_{True}; #varphi"}, - {kNoMcParticle, o2::framework::HistType::kTHnSparseF, "hNoMcParticle", "Wrongly reconstructed particles; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, + {kNoMcParticle, o2::framework::HistType::kTHnSparseF, "hNoMcParticle", "Wrongly reconstructed particles; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, {kPrimary, o2::framework::HistType::kTHnSparseF, "hPrimary", "Primary particles; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kFromWrongCollision, o2::framework::HistType::kTHnSparseF, "hFromWrongCollision", "Particles associated to wrong collision; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kFromMaterial, o2::framework::HistType::kTHnSparseF, "hFromMaterial", "Particles from material; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kMissidentified, o2::framework::HistType::kTHnSparseF, "hMissidentified", "Missidentified particles (fake/wrong PDG code); p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kSecondary1, o2::framework::HistType::kTHnSparseF, "hFromSecondary1", "Particles from secondary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kSecondary2, o2::framework::HistType::kTHnSparseF, "hFromSecondary2", "Particles from seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kSecondary3, o2::framework::HistType::kTHnSparseF, "hFromSecondary3", "Particles from seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, - {kSecondaryOther, o2::framework::HistType::kTHnSparseF, "hFromSecondaryOther", "Particles from every other seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm)"}, + {kFromWrongCollision, o2::framework::HistType::kTHnSparseF, "hFromWrongCollision", "Particles associated to wrong collision; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kFromMaterial, o2::framework::HistType::kTHnSparseF, "hFromMaterial", "Particles from material; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kMissidentified, o2::framework::HistType::kTHnSparseF, "hMissidentified", "Missidentified particles (fake/wrong PDG code); p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kSecondary1, o2::framework::HistType::kTHnSparseF, "hFromSecondary1", "Particles from secondary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kSecondary2, o2::framework::HistType::kTHnSparseF, "hFromSecondary2", "Particles from seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kSecondary3, o2::framework::HistType::kTHnSparseF, "hFromSecondary3", "Particles from seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, + {kSecondaryOther, o2::framework::HistType::kTHnSparseF, "hFromSecondaryOther", "Particles from every other seconary decay; p_{T} (GeV/#it{c}); DCA_{xy} (cm); DCA_{z} (cm);"}, }}; #define TRACK_HIST_ANALYSIS_MAP(conf) \ @@ -394,6 +399,8 @@ constexpr std::array, kTrackHistLast> {kPtVsDcaxy, {confAnalysis.pt, confQa.dcaXy}}, \ {kPtVsDcaz, {confAnalysis.pt, confQa.dcaZ}}, \ {kPtVsDca, {confAnalysis.pt, confQa.dca}}, \ + {kPtVsDcaxyVsDcaz, {confAnalysis.pt, confQa.dcaXy, confQa.dcaZ}}, \ + {kPVsPTpc, {confQa.p, confQa.p}}, \ {kItsSignal, {confQa.p, confQa.itsSignal}}, \ {kItsElectron, {confQa.p, confQa.itsElectron}}, \ {kItsPion, {confQa.p, confQa.itsPion}}, \ @@ -633,6 +640,8 @@ class TrackHistManager mPlotHeliumPid = ConfBinningQa.plotHeliumPid.value; mMomentumType = static_cast(ConfBinningQa.momentumType.value); + mPlotDcaCorrelation = ConfBinningQa.plotDcaCorrelation.value; + mPlotOrigins = ConfBinningQa.plotOrigins.value; mPlotNSecondaries = ConfBinningQa.pdgCodesForMothersOfSecondary.value.size(); @@ -686,6 +695,11 @@ class TrackHistManager mHistogramRegistry->add(qaDir + getHistNameV2(kPtVsDcaxy, HistTable), getHistDesc(kPtVsDcaxy, HistTable), getHistType(kPtVsDcaxy, HistTable), {Specs.at(kPtVsDcaxy)}); mHistogramRegistry->add(qaDir + getHistNameV2(kPtVsDcaz, HistTable), getHistDesc(kPtVsDcaz, HistTable), getHistType(kPtVsDcaz, HistTable), {Specs.at(kPtVsDcaz)}); mHistogramRegistry->add(qaDir + getHistNameV2(kPtVsDca, HistTable), getHistDesc(kPtVsDca, HistTable), getHistType(kPtVsDca, HistTable), {Specs.at(kPtVsDca)}); + mHistogramRegistry->add(qaDir + getHistNameV2(kPVsPTpc, HistTable), getHistDesc(kPVsPTpc, HistTable), getHistType(kPVsPTpc, HistTable), {Specs.at(kPVsPTpc)}); + } + + if (mPlotDcaCorrelation) { + mHistogramRegistry->add(qaDir + getHistNameV2(kPtVsDcaxyVsDcaz, HistTable), getHistDesc(kPtVsDcaxyVsDcaz, HistTable), getHistType(kPtVsDcaxyVsDcaz, HistTable), {Specs.at(kPtVsDcaxyVsDcaz)}); } std::string pidDir = std::string(prefix) + std::string(PidDir); @@ -835,6 +849,11 @@ class TrackHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(QaDir) + HIST(getHistName(kPtVsDcaxy, HistTable)), mAbsCharge * track.pt(), track.dcaXY()); mHistogramRegistry->fill(HIST(prefix) + HIST(QaDir) + HIST(getHistName(kPtVsDcaz, HistTable)), mAbsCharge * track.pt(), track.dcaZ()); mHistogramRegistry->fill(HIST(prefix) + HIST(QaDir) + HIST(getHistName(kPtVsDca, HistTable)), mAbsCharge * track.pt(), track.dca()); + mHistogramRegistry->fill(HIST(prefix) + HIST(QaDir) + HIST(getHistName(kPVsPTpc, HistTable)), track.p(), track.tpcInnerParam()); + } + + if (mPlotDcaCorrelation) { + mHistogramRegistry->fill(HIST(prefix) + HIST(QaDir) + HIST(getHistName(kPtVsDcaxyVsDcaz, HistTable)), mAbsCharge * track.pt(), track.dcaXY(), track.dcaZ()); } float momentum = 0.f; @@ -1013,6 +1032,7 @@ class TrackHistManager bool mPlotDeuteronPid = false; bool mPlotTritonPid = false; bool mPlotHeliumPid = false; + bool mPlotDcaCorrelation = false; bool mPlotOrigins = false; int mPlotNSecondaries = 0; std::array mPdgCodesSecondaryMother = {0}; From 9e9a7c4e6239281a0a2325c121400d4e4e8914d3 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Wed, 27 May 2026 18:51:49 +0200 Subject: [PATCH 312/449] [PWGLF] Initialize variables, remove unused includes and use Particle constructor (#16405) --- .../Nuspex/coalescenceTreeProducer.cxx | 143 +++++++++--------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx index ad1e91f18ff..18a3d6bdd64 100644 --- a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx +++ b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx @@ -73,33 +73,75 @@ struct CoalescenceTreeProducer { OutputObj treeBoundState{"treeBoundState"}; - int64_t eventID; // Event ID - int64_t idB1, idB2, idB3; // MC particle IDs of the constituent baryons + int64_t eventID = 0; // Event ID + int64_t idB1 = 0, idB2 = 0, idB3 = 0; // MC particle IDs - int pdgB1, pdgB2, pdgB3; - int chargeB1, chargeB2, chargeB3; + int pdgB1 = 0, pdgB2 = 0, pdgB3 = 0; + int chargeB1 = 0, chargeB2 = 0, chargeB3 = 0; - // Space-time coordinates and momentum components of the constituent baryons in the lab frame - float xB1, yB1, zB1, tB1, pxB1, pyB1, pzB1; - float xB2, yB2, zB2, tB2, pxB2, pyB2, pzB2; - float xB3, yB3, zB3, tB3, pxB3, pyB3, pzB3; - - static constexpr double MassP = o2::constants::physics::MassProton; - static constexpr double MassN = o2::constants::physics::MassNeutron; - static constexpr double MassL = o2::constants::physics::MassLambda0; + // Space-time coordinates and momentum components + float xB1 = 0.f, yB1 = 0.f, zB1 = 0.f, tB1 = 0.f, pxB1 = 0.f, pyB1 = 0.f, pzB1 = 0.f; + float xB2 = 0.f, yB2 = 0.f, zB2 = 0.f, tB2 = 0.f, pxB2 = 0.f, pyB2 = 0.f, pzB2 = 0.f; + float xB3 = 0.f, yB3 = 0.f, zB3 = 0.f, tB3 = 0.f, pxB3 = 0.f, pyB3 = 0.f, pzB3 = 0.f; struct Particle { - int64_t id; - int pdg; - int charge; - float x; - float y; - float z; - float t; - float px; - float py; - float pz; - float mass; + int64_t id = 0; + int pdg = 0; + int charge = 0; + + float x = 0.f; + float y = 0.f; + float z = 0.f; + float t = 0.f; + + float px = 0.f; + float py = 0.f; + float pz = 0.f; + + float mass = 0.f; + + Particle() = default; + + template + explicit Particle(T const& p) + : id(p.globalIndex()), + pdg(p.pdgCode()), + charge(chargeFromPdg(pdg)), + x(p.vx()), + y(p.vy()), + z(p.vz()), + t(p.vt()), + px(p.px()), + py(p.py()), + pz(p.pz()), + mass(static_cast(massFromPdg(pdg))) + { + } + + static int chargeFromPdg(int pdg) + { + if (pdg == PDG_t::kProton) { + return 1; + } + if (pdg == PDG_t::kProtonBar) { + return -1; + } + return 0; + } + + static double massFromPdg(int pdg) + { + switch (std::abs(pdg)) { + case PDG_t::kProton: + return o2::constants::physics::MassProton; + case PDG_t::kNeutron: + return o2::constants::physics::MassNeutron; + case PDG_t::kLambda0: + return o2::constants::physics::MassLambda0; + default: + return -1.; + } + } }; void init(InitContext&) @@ -154,49 +196,6 @@ struct CoalescenceTreeProducer { } } - int chargeFromPdg(int pdg) const - { - int charge(0); - if (pdg == PDG_t::kProton) { - charge = 1; - } - if (pdg == PDG_t::kProtonBar) { - charge = -1; - } - return charge; - } - - double massFromPdg(int pdg) const - { - switch (std::abs(pdg)) { - case PDG_t::kProton: - return MassP; - case PDG_t::kNeutron: - return MassN; - case PDG_t::kLambda0: - return MassL; - default: - return -1.; - } - } - - template - Particle makeParticle(T const& p) - { - const int pdg = p.pdgCode(); - return {p.globalIndex(), - pdg, - chargeFromPdg(pdg), - p.vx(), - p.vy(), - p.vz(), - p.vt(), - p.px(), - p.py(), - p.pz(), - static_cast(massFromPdg(pdg))}; - } - ROOT::Math::PxPyPzMVector makeFourVector(Particle const& p) { return ROOT::Math::PxPyPzMVector{p.px, p.py, p.pz, p.mass}; @@ -496,17 +495,17 @@ struct CoalescenceTreeProducer { const int pdg = particle.pdgCode(); if (pdg == PDG_t::kProton) { - protons.push_back(makeParticle(particle)); + protons.emplace_back(particle); } else if (pdg == PDG_t::kProtonBar) { - antiProtons.push_back(makeParticle(particle)); + antiProtons.emplace_back(particle); } else if (pdg == PDG_t::kNeutron) { - neutrons.push_back(makeParticle(particle)); + neutrons.emplace_back(particle); } else if (pdg == PDG_t::kNeutronBar) { - antiNeutrons.push_back(makeParticle(particle)); + antiNeutrons.emplace_back(particle); } else if (pdg == PDG_t::kLambda0) { - lambdas.push_back(makeParticle(particle)); + lambdas.emplace_back(particle); } else if (pdg == PDG_t::kLambda0Bar) { - antiLambdas.push_back(makeParticle(particle)); + antiLambdas.emplace_back(particle); } } } From cd6bff5d9b5d33c031e290e8b6c4555f6b500ecd Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Wed, 27 May 2026 19:03:23 +0200 Subject: [PATCH 313/449] [PWGDQ] Adding the histograms with v2 computed with TPCpos and TPCneg (#16420) Co-authored-by: Lucamicheletti92 --- PWGDQ/Core/HistogramsLibrary.cxx | 10 ++++++++++ PWGDQ/Core/VarManager.h | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 9a9513634fd..33846186632 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1805,6 +1805,16 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Lxyz", "", false, 250, 0.0, 5.0, VarManager::kMass, 1000, 0.0, 5, VarManager::kVertexingLxyz); hm->AddHistogram(histClass, "Mass_OpeningAngle", "", false, 250, 0.0, 5.0, VarManager::kMass, 800, 0, 0.8, VarManager::kOpeningAngle); } + if (subGroupStr.Contains("flow-pos-neg-dimuon")) { + int varV2POS[6] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C, VarManager::kU2Q2POS, VarManager::kCos2DeltaPhiPOS}; + int varV2NEG[6] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C, VarManager::kU2Q2NEG, VarManager::kCos2DeltaPhiNEG}; + + int bins[6] = {250, 60, 6, 18, 200, 40}; + double minBins[6] = {0.0, 0.0, 2.5, 0.0, -10.0, -2.0}; + double maxBins[6] = {5.0, 30.0, 4.0, 90.0, 10.0, 2.0}; + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_V2POS", "", 6, varV2POS, bins, minBins, maxBins, 0, -1, kTRUE); + hm->AddHistogram(histClass, "Mass_Pt_centrFT0C_V2NEG", "", 6, varV2NEG, bins, minBins, maxBins, 0, -1, kTRUE); + } if (subGroupStr.Contains("flow-dimuon-high-mass")) { int varV2[6] = {VarManager::kMass, VarManager::kPt, VarManager::kRap, VarManager::kCentFT0C, VarManager::kU2Q2, VarManager::kCos2DeltaPhi}; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 9287ef77749..7dfb955aaa6 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -822,6 +822,8 @@ class VarManager : public TObject kWV2SP, kWV2EP, kU2Q2, + kU2Q2POS, + kU2Q2NEG, kU3Q3, kQ42XA, kQ42YA, @@ -906,6 +908,8 @@ class VarManager : public TObject kPsi2C, kRandomPsi2, kCos2DeltaPhi, + kCos2DeltaPhiPOS, + kCos2DeltaPhiNEG, kCos2DeltaPhiMu1, // cos(phi - phi1) for muon1 kCos2DeltaPhiMu2, ////cos(phi - phi2) for muon2 kCos3DeltaPhi, @@ -5751,6 +5755,8 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) // Compute the scalar product UQ using Q-vector from A, for second and third harmonic // Dilepton vn could be accessible after dividing this product with the R factor values[kU2Q2] = values[kQ2X0A] * TMath::Cos(2 * v12.Phi()) + values[kQ2Y0A] * TMath::Sin(2 * v12.Phi()); + values[kU2Q2POS] = values[kQ2X0APOS] * TMath::Cos(2 * v12.Phi()) + values[kQ2Y0APOS] * TMath::Sin(2 * v12.Phi()); + values[kU2Q2NEG] = values[kQ2X0ANEG] * TMath::Cos(2 * v12.Phi()) + values[kQ2Y0ANEG] * TMath::Sin(2 * v12.Phi()); values[kU3Q3] = values[kQ3X0A] * TMath::Cos(3 * v12.Phi()) + values[kQ3Y0A] * TMath::Sin(3 * v12.Phi()); values[kR2SP_AB] = (values[kQ2X0A] * values[kQ2X0B] + values[kQ2Y0A] * values[kQ2Y0B]); values[kR2SP_AC] = (values[kQ2X0A] * values[kQ2X0C] + values[kQ2Y0A] * values[kQ2Y0C]); @@ -5758,12 +5764,16 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kR3SP] = (values[kQ3X0B] * values[kQ3X0C] + values[kQ3Y0B] * values[kQ3Y0C]); float Psi2A = getEventPlane(2, values[kQ2X0A], values[kQ2Y0A]); + float Psi2APOS = getEventPlane(2, values[kQ2X0APOS], values[kQ2Y0APOS]); + float Psi2ANEG = getEventPlane(2, values[kQ2X0ANEG], values[kQ2Y0ANEG]); float Psi3A = getEventPlane(3, values[kQ3X0A], values[kQ3Y0A]); float Psi2B = getEventPlane(2, values[kQ2X0B], values[kQ2Y0B]); float Psi3B = getEventPlane(3, values[kQ3X0B], values[kQ3Y0B]); float Psi2C = getEventPlane(2, values[kQ2X0C], values[kQ2Y0C]); float Psi3C = getEventPlane(3, values[kQ3X0C], values[kQ3Y0C]); values[kCos2DeltaPhi] = TMath::Cos(2 * (v12.Phi() - Psi2A)); + values[kCos2DeltaPhiPOS] = TMath::Cos(2 * (v12.Phi() - Psi2APOS)); + values[kCos2DeltaPhiNEG] = TMath::Cos(2 * (v12.Phi() - Psi2ANEG)); values[kCos3DeltaPhi] = TMath::Cos(3 * (v12.Phi() - Psi3A)); values[kR2EP_AB] = TMath::Cos(2 * (Psi2A - Psi2B)); values[kR2EP_AC] = TMath::Cos(2 * (Psi2A - Psi2C)); From 4690bbe5dba7500a9dbfd1fb35af3544bf959745 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Thu, 28 May 2026 11:37:39 +0530 Subject: [PATCH 314/449] [PWGLF] Added extra MID condition (#16362) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 377 +++++++++++++------- 1 file changed, 251 insertions(+), 126 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index d1bba8d223d..d3e2f89fc8b 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -115,7 +115,6 @@ struct Kstar892LightIon { Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 15, "Number of mixed events per event"}; Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; - Configurable cfgRCRFC{"cfgRCRFC", 0.8f, "Crossed Rows to Findable Clusters"}; Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 36.0, "ITS Chi2/NCl"}; Configurable cfgTPCChi2NClMax{"cfgTPCChi2NClMax", 4.0, "TPC Chi2/NCl"}; Configurable cfgTPCChi2NClMin{"cfgTPCChi2NClMin", 0.0, "TPC Chi2/NCl"}; @@ -124,7 +123,7 @@ struct Kstar892LightIon { Configurable isGoldenChi2{"isGoldenChi2", false, "Apply golden chi2 cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; // Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cfgBetaCutTOF{"cfgBetaCutTOF", 0.0, "cut TOF beta"}; + Configurable cfgTOFBetaCut{"cfgTOFBetaCut", 0.0, "cut TOF beta"}; Configurable isAvoidsplitrackMC{"isAvoidsplitrackMC", true, "avoid split track in MC"}; @@ -143,6 +142,7 @@ struct Kstar892LightIon { Configurable isApplypTdepPIDwTOF{"isApplypTdepPIDwTOF", false, "Apply pT dependent PID with compulsory TOF condition in a pT range"}; Configurable isApplyMID{"isApplyMID", false, "Apply particle MID"}; Configurable isApplypTdepMID{"isApplypTdepMID", false, "Apply pT dependent particle MID"}; + Configurable isApplypTdepMIDComp{"isApplypTdepMIDComp", false, "Apply pT dependent particle MID by comparing the nsigma value"}; Configurable nsigmaCutTPCPi{"nsigmaCutTPCPi", 3.0, "TPC Nsigma cut for pions"}; Configurable nsigmaCutTPCKa{"nsigmaCutTPCKa", 3.0, "TPC Nsigma cut for kaons"}; @@ -151,8 +151,12 @@ struct Kstar892LightIon { Configurable nsigmaCutCombinedKa{"nsigmaCutCombinedKa", 3.0, "Combined Nsigma cut for kaon"}; Configurable nsigmaCutCombinedPi{"nsigmaCutCombinedPi", 3.0, "Combined Nsigma cut for pion"}; - Configurable nsigmaCutCombinedMID{"nsigmaCutCombinedMID", 3.0, "Combined Nsigma cut for pion in MID"}; - Configurable nsigmaCutTPCMID{"nsigmaCutTPCMID", 1.0, "MID Nsigma cut for pion in TPC"}; + Configurable nsigmaCutCombinedMID{"nsigmaCutCombinedMID", 3.0, "Combined Nsigma cut for pion and kaon in MID"}; + Configurable nsigmaCutTPCMID{"nsigmaCutTPCMID", 1.0, "MID Nsigma cut for pion and kaon in TPC"}; + + Configurable isApplyFakeTrack{"isApplyFakeTrack", false, "Fake track selection"}; + Configurable cfgFakeTrackCutKa{"cfgFakeTrackCutKa", 0.3, "Cut based on momentum difference in global and TPC tracks for kaons"}; + Configurable cfgFakeTrackCutPi{"cfgFakeTrackCutPi", 0.3, "Cut based on momentum difference in global and TPC tracks for pions"}; // Fixed variables float lowPtCutPID = 0.5; @@ -161,9 +165,6 @@ struct Kstar892LightIon { Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; Configurable selINELgt0MC{"selINELgt0MC", true, "Select INEL > 0?"}; - - Configurable invMassMinMID{"invMassMinMID", 0.6, "Minimum invariant mass for MID"}; - Configurable invMassMaxMID{"invMassMaxMID", 0.82, "Maximum invariant mass for MID"}; } selectionConfig; Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; @@ -173,7 +174,7 @@ struct Kstar892LightIon { // Confugrable for QA histograms Configurable cQAplots{"cQAplots", true, "cQAplots"}; - Configurable cQAevents{"cQAevents", true, "centrality dist, DCAxy, DCAz"}; + Configurable cQAevents{"cQAevents", true, "centrality dist, Vz, Event Cut hists"}; Configurable selectCentEstimator{"selectCentEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C, 3 - FV0A"}; @@ -210,7 +211,7 @@ struct Kstar892LightIon { int noOfDaughters = 2; - double pionPIDpTlow = 1, pionPIDpThigh = 2.5, kaonPIDpTlow = 0.7, kaonPIDpThigh = 2.5; + double pionPIDpTlow = 1.0, pionPIDpThigh = 2.5, kaonPIDpTlow = 0.7, kaonPIDpThigh = 2.5; TRandom* rn = new TRandom(); @@ -259,8 +260,10 @@ struct Kstar892LightIon { if (cQAplots) { hOthers.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); hOthers.add("hEta_after", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); - hOthers.add("hCRFC_after", "CRFC after distribution", kTH1F, {{100, 0.0f, 10.0f}}); - hOthers.add("hCRFC_before", "CRFC before distribution", kTH1F, {{100, 0.0f, 10.0f}}); + hOthers.add("hTOFBetaKa", "Beta distribution from TOF", kTH1F, {{50, 0.0f, 1.0f}}); + hOthers.add("hTOFBetaPi", "Beta distribution from TOF", kTH1F, {{50, 0.0f, 1.0f}}); + hOthers.add("hTPCpDiffKa", "Momentum difference between global and TPC tracks for Kaons", kTH2F, {{100, -1.0f, 1.0f}, ptAxis}); + hOthers.add("hTPCpDiffPi", "Momentum difference between global and TPC tracks for Kaons", kTH2F, {{100, -1.0f, 1.0f}, ptAxis}); hOthers.add("hKstar_rap_pt", "Pair rapidity distribution; y; p_{T}; Counts", kTH2F, {{400, -2.0f, 2.0f}, ptAxis}); hOthers.add("hKstar_eta_pt", "Pair eta distribution; #eta; p_{T}; Counts", kTH2F, {{400, -2.0f, 2.0f}, ptAxis}); @@ -281,11 +284,21 @@ struct Kstar892LightIon { hPID.add("Before/hTOFnsigKa_Neg_mult_pt", "TOF nsigma of K^{-} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("Before/hTOFnsigPi_Neg_mult_pt", "TOF nsigma of #pi^{-} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTPCnsigKa_Neg_mult_p", "TPC nsigma of K^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTPCnsigPi_Neg_mult_p", "TPC nsigma of #pi^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTOFnsigKa_Neg_mult_p", "TOF nsigma of K^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTOFnsigPi_Neg_mult_p", "TOF nsigma of #pi^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTPCnsigKa_Pos_mult_pt", "TPC nsigma of K^{+} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("Before/hTPCnsigPi_Pos_mult_pt", "TPC nsigma of #pi^{+} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("Before/hTOFnsigKa_Pos_mult_pt", "TOF nsigma of K^{+} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("Before/hTOFnsigPi_Pos_mult_pt", "TOF nsigma of #pi^{+} before PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTPCnsigKa_Pos_mult_p", "TPC nsigma of K^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTPCnsigPi_Pos_mult_p", "TPC nsigma of #pi^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTOFnsigKa_Pos_mult_p", "TOF nsigma of K^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("Before/hTOFnsigPi_Pos_mult_p", "TOF nsigma of #pi^{-} before PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hNsigma_TPC_TOF_Ka_pt", "N #sigma Kaon TPC TOF after", kTH3F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}, ptAxis}); hPID.add("After/hNsigma_TPC_TOF_Pi_pt", "N #sigma Pion TPC TOF after", kTH3F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}, ptAxis}); @@ -294,10 +307,20 @@ struct Kstar892LightIon { hPID.add("After/hTOFnsigKa_Neg_mult_pt", "TOF nsigma of K^{-} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("After/hTOFnsigPi_Neg_mult_pt", "TOF nsigma of #pi^{-} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTPCnsigKa_Neg_mult_p", "TPC nsigma of K^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTPCnsigPi_Neg_mult_p", "TPC nsigma of #pi^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTOFnsigKa_Neg_mult_p", "TOF nsigma of K^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTOFnsigPi_Neg_mult_p", "TOF nsigma of #pi^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTPCnsigKa_Pos_mult_pt", "TPC nsigma of K^{+} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("After/hTPCnsigPi_Pos_mult_pt", "TPC nsigma of #pi^{+} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("After/hTOFnsigKa_Pos_mult_pt", "TOF nsigma of K^{+} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); hPID.add("After/hTOFnsigPi_Pos_mult_pt", "TOF nsigma of #pi^{+} after PID with pt and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + + hPID.add("After/hTPCnsigKa_Pos_mult_p", "TPC nsigma of K^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTPCnsigPi_Pos_mult_p", "TPC nsigma of #pi^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTOFnsigKa_Pos_mult_p", "TOF nsigma of K^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); + hPID.add("After/hTOFnsigPi_Pos_mult_p", "TOF nsigma of #pi^{-} After PID with p and centrality", kTH3F, {{100, -10.0f, 10.0f}, centralityAxis, ptAxis}); } // KStar histograms @@ -373,7 +396,8 @@ struct Kstar892LightIon { } if (doprocessRecMisID) { - hMC.add("RecMisID/hMassMisID", "Reconstruction misidentification", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("RecMisID/hMassMisIDPiPi", "Reconstruction misidentification", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("RecMisID/hMassMisIDKK", "Reconstruction misidentification", kTH3F, {ptAxis, centralityAxis, invmassAxis}); } if (doprocessRecReflection) { @@ -532,8 +556,6 @@ struct Kstar892LightIon { return false; if (std::abs(candidate.dcaZ()) > selectionConfig.cfgCutDCAz) return false; - if (candidate.tpcCrossedRowsOverFindableCls() < selectionConfig.cfgRCRFC) - return false; if (candidate.itsNCls() < selectionConfig.cfgITScluster) return false; if (candidate.tpcNClsFound() < selectionConfig.cfgTPCcluster) @@ -557,8 +579,6 @@ struct Kstar892LightIon { return false; if (std::abs(candidate.dcaZ()) > selectionConfig.cfgCutDCAz) return false; - if (candidate.tpcCrossedRowsOverFindableCls() < selectionConfig.cfgRCRFC) - return false; if (candidate.itsNCls() < selectionConfig.cfgITScluster) return false; if (candidate.tpcNClsFound() < selectionConfig.cfgTPCcluster) @@ -594,16 +614,33 @@ struct Kstar892LightIon { return true; } + template + bool isFakeTrack(const T& track, int PID) + { + const auto pglobal = track.p(); + const auto ptpc = track.tpcInnerParam(); + if (PID == PIDParticle::kPion) { + if (std::abs(pglobal - ptpc) > selectionConfig.cfgFakeTrackCutPi) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (std::abs(pglobal - ptpc) > selectionConfig.cfgFakeTrackCutKa) { + return true; + } + } + return false; + } + template bool selectionPID(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { if (selectionConfig.onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } } else if (selectionConfig.onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { @@ -614,7 +651,7 @@ struct Kstar892LightIon { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedPi * selectionConfig.nsigmaCutCombinedPi) && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedPi * selectionConfig.nsigmaCutCombinedPi) && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { @@ -623,11 +660,11 @@ struct Kstar892LightIon { } } else if (PID == PIDParticle::kKaon) { if (selectionConfig.onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } } else if (selectionConfig.onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { @@ -638,7 +675,7 @@ struct Kstar892LightIon { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa) && candidate.beta() > selectionConfig.cfgBetaCutTOF) { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa) && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { @@ -656,7 +693,7 @@ struct Kstar892LightIon { if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { return true; } - if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi) { + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && !candidate.hasTOF()) { @@ -666,7 +703,7 @@ struct Kstar892LightIon { if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } - if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa) { + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > selectionConfig.cfgTOFBetaCut) { return true; } if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && !candidate.hasTOF()) { @@ -771,6 +808,21 @@ struct Kstar892LightIon { return false; } + template + bool selectionMIDPtDepComp(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (candidate.pt() >= pionPIDpTlow && candidate.pt() < pionPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < std::abs(candidate.tpcNSigmaKa())) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() >= kaonPIDpTlow && candidate.pt() < kaonPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < std::abs(candidate.tpcNSigmaPi())) { + return true; + } + } + return false; + } + //*********Varibles declaration*************** float centrality{-1.0}, theta2; ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, mother, motherRot; @@ -882,7 +934,6 @@ struct Kstar892LightIon { } if (cQAplots) { - hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); if (track1.sign() < 0) { @@ -890,18 +941,26 @@ struct Kstar892LightIon { hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Neg_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); } else if (track1.sign() > 0) { hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); } hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_pt"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_pt"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - } - if (cQAevents) { hOthers.fill(HIST("hDcaxy_cent_pt"), track1.dcaXY(), centrality, track1.pt()); hOthers.fill(HIST("hDcaz_cent_pt"), track1.dcaZ(), centrality, track1.pt()); } @@ -928,9 +987,14 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(track1, 0) || selectionMIDPtDepComp(track2, 1))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(track1, 1) || isFakeTrack(track2, 0))) + continue; + if (cQAplots) { hOthers.fill(HIST("hEta_after"), track1.eta()); - hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("hDcaxyPi"), track2.dcaXY()); hOthers.fill(HIST("hDcaxyKa"), track1.dcaXY()); hOthers.fill(HIST("hDcazPi"), track2.dcaZ()); @@ -939,21 +1003,42 @@ struct Kstar892LightIon { if (track1.sign() < 0) { hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); } else if (track1.sign() > 0) { hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); } if (track2.sign() < 0) { hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } else if (track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_pt"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_pt"), track2.tpcNSigmaPi(), track2.tofNSigmaPi(), track2.pt()); + + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); + } + hOthers.fill(HIST("hTPCpDiffKa"), track1.p() - track1.tpcInnerParam(), track1.pt()); + hOthers.fill(HIST("hTPCpDiffPi"), track2.p() - track2.tpcInnerParam(), track2.pt()); } daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); @@ -966,9 +1051,10 @@ struct Kstar892LightIon { if (mother.M() >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow continue; } */ - - hOthers.fill(HIST("hKstar_rap_pt"), mother.Rapidity(), mother.Pt()); - hOthers.fill(HIST("hKstar_eta_pt"), mother.Eta(), mother.Pt()); + if (cQAplots) { + hOthers.fill(HIST("hKstar_rap_pt"), mother.Rapidity(), mother.Pt()); + hOthers.fill(HIST("hKstar_eta_pt"), mother.Eta(), mother.Pt()); + } isMix = false; fillInvMass(daughter1, daughter2, mother, centrality, isMix, track1, track2); @@ -1026,7 +1112,6 @@ struct Kstar892LightIon { continue; if (cQAplots) { - hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); if (track1.sign() < 0) { @@ -1034,18 +1119,26 @@ struct Kstar892LightIon { hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Neg_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); } else { hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); } hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_pt"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_pt"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - } - if (cQAevents) { hOthers.fill(HIST("hDcaxy_cent_pt"), track1.dcaXY(), centrality, track1.pt()); hOthers.fill(HIST("hDcaz_cent_pt"), track1.dcaZ(), centrality, track1.pt()); } @@ -1066,9 +1159,14 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(track1, 0) || selectionMIDPtDepComp(track2, 1))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(track1, 1) || isFakeTrack(track2, 0))) + continue; + if (cQAplots) { hOthers.fill(HIST("hEta_after"), track1.eta()); - hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("hDcaxyPi"), track2.dcaXY()); hOthers.fill(HIST("hDcaxyKa"), track1.dcaXY()); hOthers.fill(HIST("hDcazPi"), track2.dcaZ()); @@ -1077,21 +1175,42 @@ struct Kstar892LightIon { if (track1.sign() < 0) { hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); } else if (track1.sign() > 0) { hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); } if (track2.sign() < 0) { hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } else if (track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_pt"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_pt"), track2.tpcNSigmaPi(), track2.tofNSigmaPi(), track2.pt()); + + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); + } + hOthers.fill(HIST("hTPCpDiffKa"), track1.p() - track1.tpcInnerParam(), track1.pt()); + hOthers.fill(HIST("hTPCpDiffPi"), track2.p() - track2.tpcInnerParam(), track2.pt()); } daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); @@ -1103,10 +1222,10 @@ struct Kstar892LightIon { if (mother.M() >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow continue; } */ - - hOthers.fill(HIST("hKstar_rap_pt"), mother.Rapidity(), mother.Pt()); - hOthers.fill(HIST("hKstar_eta_pt"), mother.Eta(), mother.Pt()); - + if (cQAplots) { + hOthers.fill(HIST("hKstar_rap_pt"), mother.Rapidity(), mother.Pt()); + hOthers.fill(HIST("hKstar_eta_pt"), mother.Eta(), mother.Pt()); + } isMix = false; fillInvMass(daughter1, daughter2, mother, centrality, isMix, track1, track2); } @@ -1168,6 +1287,12 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(t1, 0) || selectionMIDpTdep(t2, 1))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(t1, 0) || selectionMIDPtDepComp(t2, 1))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(t1, 1) || isFakeTrack(t2, 0))) + continue; + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massPi); mother = daughter1 + daughter2; @@ -1245,6 +1370,12 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(t1, 0) || selectionMIDpTdep(t2, 1))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(t1, 0) || selectionMIDPtDepComp(t2, 1))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(t1, 1) || isFakeTrack(t2, 0))) + continue; + if (!t1.has_mcParticle() || !t2.has_mcParticle()) { continue; // skip if no MC particle associated } @@ -1448,7 +1579,7 @@ struct Kstar892LightIon { continue; } - if (cQAevents) { + if (cQAplots) { hOthers.fill(HIST("hDcaxy_cent_pt"), track1.dcaXY(), centrality, track1.pt()); hOthers.fill(HIST("hDcaz_cent_pt"), track1.dcaZ(), centrality, track1.pt()); } @@ -1470,18 +1601,30 @@ struct Kstar892LightIon { if (mctrack2.pdgCode() == PDG_t::kPiPlus) { // pion hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("Before/hTPCnsigPi_Pos_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Pos_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } if (mctrack2.pdgCode() == PDG_t::kKPlus) { // kaon hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_pt"), track2.tpcNSigmaKa(), centrality, track2.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_pt"), track2.tofNSigmaKa(), centrality, track2.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Pos_mult_p"), track2.tpcNSigmaKa(), centrality, track2.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Pos_mult_p"), track2.tofNSigmaKa(), centrality, track2.p()); } if (mctrack2.pdgCode() == PDG_t::kPiMinus) { // negative track pion hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("Before/hTPCnsigPi_Neg_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("Before/hTOFnsigPi_Neg_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } if (mctrack2.pdgCode() == PDG_t::kKMinus) { // negative track kaon hPID.fill(HIST("Before/hTPCnsigKa_Neg_mult_pt"), track2.tpcNSigmaKa(), centrality, track2.pt()); hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_pt"), track2.tofNSigmaKa(), centrality, track2.pt()); + + hPID.fill(HIST("Before/hTPCnsigKa_Neg_mult_p"), track2.tpcNSigmaKa(), centrality, track2.p()); + hPID.fill(HIST("Before/hTOFnsigKa_Neg_mult_p"), track2.tofNSigmaKa(), centrality, track2.p()); } if (std::abs(mctrack1.pdgCode()) == PDG_t::kKPlus && std::abs(mctrack2.pdgCode()) == PDG_t::kPiPlus) { hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_pt"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); @@ -1530,18 +1673,43 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 1) || selectionMIDpTdep(track2, 0))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(track1, 1) || selectionMIDPtDepComp(track2, 0))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(track1, 0) || isFakeTrack(track2, 1))) + continue; + if (cQAplots) { if (track1.sign() < 0 && track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_pt"), track2.tpcNSigmaKa(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_pt"), track2.tofNSigmaKa(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_p"), track2.tpcNSigmaKa(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_p"), track2.tofNSigmaKa(), centrality, track2.p()); } else { hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_pt"), track1.tofNSigmaPi(), centrality, track1.pt()); hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_pt"), track2.tpcNSigmaKa(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_pt"), track2.tofNSigmaKa(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_p"), track1.tpcNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_p"), track1.tofNSigmaPi(), centrality, track1.p()); + hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_p"), track2.tpcNSigmaKa(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_p"), track2.tofNSigmaKa(), centrality, track2.p()); } + + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track2.beta()); + } + hOthers.fill(HIST("hTPCpDiffPi"), track1.p() - track1.tpcInnerParam(), track1.pt()); + hOthers.fill(HIST("hTPCpDiffKa"), track2.p() - track2.tpcInnerParam(), track2.pt()); } } else if (track1PDG == PDG_t::kKPlus) { @@ -1559,18 +1727,43 @@ struct Kstar892LightIon { if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) continue; + if (selectionConfig.isApplypTdepMIDComp && (selectionMIDPtDepComp(track1, 0) || selectionMIDPtDepComp(track2, 1))) + continue; + + if (selectionConfig.isApplyFakeTrack && (isFakeTrack(track1, 1) || isFakeTrack(track2, 0))) + continue; + if (cQAplots) { if (track1.sign() < 0 && track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Neg_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTPCnsigPi_Pos_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Pos_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); } else { hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_pt"), track1.tofNSigmaKa(), centrality, track1.pt()); hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_pt"), track2.tpcNSigmaPi(), centrality, track2.pt()); hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_pt"), track2.tofNSigmaPi(), centrality, track2.pt()); + + hPID.fill(HIST("After/hTPCnsigKa_Pos_mult_p"), track1.tpcNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTOFnsigKa_Pos_mult_p"), track1.tofNSigmaKa(), centrality, track1.p()); + hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_p"), track2.tpcNSigmaPi(), centrality, track2.p()); + hPID.fill(HIST("After/hTOFnsigPi_Neg_mult_p"), track2.tofNSigmaPi(), centrality, track2.p()); + } + + if (track1.hasTOF()) { + hOthers.fill(HIST("hTOFBetaKa"), track1.beta()); + } + if (track2.hasTOF()) { + hOthers.fill(HIST("hTOFBetaPi"), track2.beta()); } + hOthers.fill(HIST("hTPCpDiffKa"), track1.p() - track1.tpcInnerParam(), track1.pt()); + hOthers.fill(HIST("hTPCpDiffPi"), track2.p() - track2.tpcInnerParam(), track2.pt()); } } @@ -1877,7 +2070,15 @@ struct Kstar892LightIon { auto misIDMother = p1Fake + p2True; if (misIDMother.Rapidity() > selectionConfig.motherRapidityMin && misIDMother.Rapidity() < selectionConfig.motherRapidityMax) { - hMC.fill(HIST("RecMisID/hMassMisID"), misIDMother.Pt(), centrality, misIDMother.M()); + hMC.fill(HIST("RecMisID/hMassMisIDPiPi"), misIDMother.Pt(), centrality, misIDMother.M()); + } + + ROOT::Math::PxPyPzMVector p1True(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2Fake(track2.px(), track2.py(), track2.pz(), massKa); + + misIDMother = p1True + p2Fake; + if (misIDMother.Rapidity() > selectionConfig.motherRapidityMin && misIDMother.Rapidity() < selectionConfig.motherRapidityMax) { + hMC.fill(HIST("RecMisID/hMassMisIDPiPi"), misIDMother.Pt(), centrality, misIDMother.M()); } } @@ -1888,7 +2089,15 @@ struct Kstar892LightIon { auto misIDMother = p1Fake + p2True; if (misIDMother.Rapidity() > selectionConfig.motherRapidityMin && misIDMother.Rapidity() < selectionConfig.motherRapidityMax) { - hMC.fill(HIST("RecMisID/hMassMisID"), misIDMother.Pt(), centrality, misIDMother.M()); + hMC.fill(HIST("RecMisID/hMassMisIDKK"), misIDMother.Pt(), centrality, misIDMother.M()); + } + + ROOT::Math::PxPyPzMVector p1True(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Fake(track2.px(), track2.py(), track2.pz(), massPi); + + misIDMother = p1True + p2Fake; + if (misIDMother.Rapidity() > selectionConfig.motherRapidityMin && misIDMother.Rapidity() < selectionConfig.motherRapidityMax) { + hMC.fill(HIST("RecMisID/hMassMisIDKK"), misIDMother.Pt(), centrality, misIDMother.M()); } } } @@ -2310,90 +2519,6 @@ struct Kstar892LightIon { hMC.fill(HIST("MCCheck/NchMC_AllGen"), nChMCEta08); } PROCESS_SWITCH(Kstar892LightIon, processMCCheck, "Cross-check MC analysis", false); - - void processSEMassMID(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) - { - if (!selectionEvent(collision, true)) { // fill data event cut histogram - return; - } - - centrality = -1; - - if (selectCentEstimator == kFT0M) { - centrality = collision.centFT0M(); - } else if (selectCentEstimator == kFT0A) { - centrality = collision.centFT0A(); - } else if (selectCentEstimator == kFT0C) { - centrality = collision.centFT0C(); - } else if (selectCentEstimator == kFV0A) { - centrality = collision.centFV0A(); - } else { - centrality = collision.centFT0M(); // default - } - - /* else if (selectCentEstimator == 4) { - centrality = collision.centMFT(); - } */ - /* else if (selectCentEstimator == 5) { - centrality = collision.centNGlobal(); - } */ - /* else if (selectCentEstimator == 6) { - centrality = collision.centNTPV(); - } */ - - if (cQAevents) { - hEventSelection.fill(HIST("hVertexZ"), collision.posZ()); - hEventSelection.fill(HIST("hCentrality"), centrality); - } - - for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { - if (!selectionTrack(track1) || !selectionTrack(track2)) { - continue; - } - - if (track1.globalIndex() == track2.globalIndex()) - continue; - - if (!selectionPair(track1, track2)) { - continue; - } - - // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion - if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track1, 1)) // Track 1 is checked with Kaon - continue; - if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track2, 0)) // Track 2 is checked with Pion - continue; - - if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track1, 1)) // Track 1 is checked with Kaon - continue; - if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track2, 0)) // Track 2 is checked with Pion - continue; - - if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track1, 1)) // Track 1 is checked with Kaon - continue; - if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track2, 0)) // Track 2 is checked with Pion - continue; - - /* if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) - continue; - - if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) - continue; */ - - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); - mother = daughter1 + daughter2; // Kstar meson - - if (mother.M() < selectionConfig.invMassMaxMID && mother.M() > selectionConfig.invMassMinMID) { - if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) - continue; - } - - isMix = false; - fillInvMass(daughter1, daughter2, mother, centrality, isMix, track1, track2); - } - } - PROCESS_SWITCH(Kstar892LightIon, processSEMassMID, "Process Same event", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 9bc896308644c68b05ec71cd704b068dce3657fb Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Thu, 28 May 2026 10:25:30 +0200 Subject: [PATCH 315/449] [PWGHF] treeCreatorLcToPKPi: check the size of HfMlLcToPKPi (#16425) --- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 51112ffe161..2ff5913aa99 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -478,6 +478,21 @@ struct HfTreeCreatorLcToPKPi { } } + /// \brief function to check when applyMl == true if the HfMlLcToPKPi size is equal to that of the table with candidates + /// \param candidates Lc->pKpi candidate table + /// \param candidateMlScores ML scores table + template + void checkHfMlLcToPKPiSize(CandType const& candidates, aod::HfMlLcToPKPi const& candidateMlScores) + { + if (applyMl) { + const auto candidatesSize = candidates.size(); + const auto candidateMlScoresSize = candidateMlScores.size(); + if (candidatesSize != candidateMlScoresSize) { + LOG(fatal) << "Tables with candidates and ML scores have different sizes (" << candidatesSize << " vs " << candidateMlScoresSize << ") while applyMl == true. Check if applyMl is enabled in the candidateSelectorLc"; + } + } + } + /// \brief function to fill event properties /// \param collisions Collision table template @@ -918,6 +933,7 @@ struct HfTreeCreatorLcToPKPi { soa::Join const& particles, soa::Join const&, aod::BCs const&) { + checkHfMlLcToPKPiSize(candidates, candidateMlScores); constexpr bool IsMc = true; @@ -1105,6 +1121,7 @@ struct HfTreeCreatorLcToPKPi { aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const&, aod::BCs const&) { + checkHfMlLcToPKPiSize(candidates, candidateMlScores); constexpr bool IsMc = false; From 81336372104cf510f631a719dec143fc8fc5c120 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Thu, 28 May 2026 16:51:49 +0800 Subject: [PATCH 316/449] [PWGCF] jEPFlowAnalysis.cxx: calculate q-vector over M, add QA histograms (#16428) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 101 +++++++++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index cd6f6a44190..a0e47675ea2 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \author Maxim Virta (maxim.virta@cern.ch) +/// \author Maxim Virta (maxim.virta@cern.ch), junlee kim (junlee.kim@cern.ch) /// \brief flow measurement with q-vectors /// \file jEPFlowAnalysis.cxx /// \since Jul 2024 @@ -20,12 +20,15 @@ #include "Common/Core/EventPlaneHelper.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" #include #include #include +#include +#include #include #include #include @@ -39,6 +42,7 @@ #include #include +#include #include #include #include @@ -56,7 +60,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace std; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyTracks = soa::Join; using MyCollisionsMC = soa::Join; using MyTracksMC = soa::Join; @@ -67,6 +71,8 @@ struct JEPFlowAnalysis { HistogramRegistry epFlowHistograms{"EPFlow", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; EventPlaneHelper helperEP; + o2::ft0::Geometry ft0geom; + o2::fv0::Geometry* fv0geom = nullptr; FlowJHistManager histManager; bool debug = kFALSE; Service ccdb; @@ -94,6 +100,9 @@ struct JEPFlowAnalysis { Configurable cfgEffCor{"cfgEffCor", false, "flag for efficiency correction"}; Configurable cfgEffCorDir{"cfgEffCorDir", "Users/n/nmallick/Run3OO/Eff/LHC25h3b_FT0C", "path for efficiency correction"}; + Configurable cfgGainEq{"cfgGainEq", false, "flag for gain equalization"}; + Configurable cfgGainEqPath{"cfgGainEqPath", "Users/j/junlee/Qvector/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgTrkSelFlag{"cfgTrkSelFlag", true, "flag for track selection"}; Configurable cfgSystStudy{"cfgSystStudy", false, "flag for syst study"}; Configurable cfgITSNCls{"cfgITSNCls", 5, "minimum number of its clusters"}; @@ -126,6 +135,8 @@ struct JEPFlowAnalysis { ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {200, -5.0, 5.0}, ""}; ConfigurableAxis cfgAxisQ2{"cfgAxisQ2", {100, 0, 10}, ""}; + ConfigurableAxis cfgAxisAmp{"cfgAxisAmp", {100, 0, 1e5}, ""}; + ConfigurableAxis cfgAxisAmpR{"cfgAxisAmpR", {VARIABLE_WIDTH, 0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0}, ""}; ConfigurableAxis cfgAxisCentMC{"cfgAxisCentMC", {5, 0, 100}, ""}; ConfigurableAxis cfgAxisVtxZMC{"cfgAxisVtxZMC", {20, -10, 10}, ""}; @@ -148,12 +159,16 @@ struct JEPFlowAnalysis { float minQvecAmp = 1e-5; float minChg = 0.1; float q2Mag; + float highestPt; std::vector shiftprofile{}; std::string fullCCDBShiftCorrPath; THn* effMap = nullptr; + std::vector ft0RelGainConst{}; + std::vector fv0RelGainConst{}; + bool q2sel(float q2, bool isHigh) { auto it = std::upper_bound(cfgMultq2SelBin->begin(), cfgMultq2SelBin->end(), cent); @@ -230,6 +245,27 @@ struct JEPFlowAnalysis { return true; } + template + float calcFT0CRawQVecMag(const Col& coll, int nMode) + { + float ampFT0C = 0.f; + + if (!coll.has_foundFT0()) { + return false; + } + + auto ft0 = coll.foundFT0(); + TComplex qVecFT0C(0., 0.); + + for (std::size_t iChC = 0; iChC < ft0.channelC().size(); ++iChC) { + int ft0CChId = ft0.channelC()[iChC] + 96; + float ampl = ft0.amplitudeC()[iChC] / (cfgGainEq ? ft0RelGainConst[ft0CChId] : 1.); + helperEP.SumQvectors(0, ft0CChId, ampl, nMode, qVecFT0C, ampFT0C, ft0geom, fv0geom); + } + + return qVecFT0C.Rho(); + } + template uint8_t trackSel(const Trk& track) { @@ -346,10 +382,15 @@ struct JEPFlowAnalysis { } } + highestPt = 0.0; for (const auto& track : tracks) { if (cfgTrkSelFlag && trackSel(track)) continue; + if (highestPt < track.pt()) { + highestPt = track.pt(); + } + if (cfgEffCor) { weight = getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); } @@ -371,6 +412,13 @@ struct JEPFlowAnalysis { } } } + if (i == 0) { // second harmonic only + auto qOvecM = calcFT0CRawQVecMag(coll, i + 2); + + epFlowHistograms.fill(HIST("hQoverM"), cent, highestPt, qOvecM); + epFlowHistograms.fill(HIST("hQoverM2M"), cent, coll.qvecAmp()[detId], qOvecM); + epFlowHistograms.fill(HIST("hQoverM2Q2"), cent, q2Mag, qOvecM); + } } } @@ -393,6 +441,8 @@ struct JEPFlowAnalysis { ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + fv0geom = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); + detId = getdetId(cfgDetName); refAId = getdetId(cfgRefAName); refBId = getdetId(cfgRefBName); @@ -407,6 +457,8 @@ struct JEPFlowAnalysis { AxisSpec axisCos{cfgAxisCos, "cos"}; AxisSpec axisQvec{cfgAxisQvec, "Qvec"}; AxisSpec axisQ2{cfgAxisQ2, "Q2"}; + AxisSpec axisAmp{cfgAxisAmp, "M"}; + AxisSpec axisAmpR{cfgAxisAmpR, "QoverM"}; AxisSpec axisCentMC{cfgAxisCentMC, "cent"}; AxisSpec axisVtxZMC{cfgAxisVtxZMC, "vtxz"}; @@ -423,6 +475,9 @@ struct JEPFlowAnalysis { epFlowHistograms.add("EpResRefARefB", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("hQ2", "", {HistType::kTH3F, {axisMod, axisCent, axisQ2}}); + epFlowHistograms.add("hQoverM", "", {HistType::kTH3F, {axisCent, axisPt, axisAmpR}}); + epFlowHistograms.add("hQoverM2M", "", {HistType::kTH3F, {axisCent, axisAmp, axisAmpR}}); + epFlowHistograms.add("hQoverM2Q2", "", {HistType::kTH3F, {axisCent, axisQ2, axisAmpR}}); epFlowHistograms.add("vncos", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisCos}}); epFlowHistograms.add("vnsin", "", {HistType::kTHnSparseF, {axisMod, axisCent, axisPt, axisCos}}); @@ -457,7 +512,7 @@ struct JEPFlowAnalysis { epFlowHistograms.add("MC/hPartRec", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); } - void processDefault(MyCollisions::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) + void processDefault(MyCollisions::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&, aod::FT0s const&) { if (cfgAddEvtSel) { if (!eventSel(coll)) @@ -473,6 +528,46 @@ struct JEPFlowAnalysis { } } + if (cfgGainEq) { + auto bc = coll.bc_as(); + currentRunNumber = bc.runNumber(); + auto timestamp = bc.timestamp(); + + std::string fullPath; + if (currentRunNumber != lastRunNumber) { + ft0RelGainConst.clear(); + fv0RelGainConst.clear(); + ft0RelGainConst = {}; + fv0RelGainConst = {}; + + fullPath = cfgGainEqPath; + fullPath += "/FT0"; + const int nPixelsFT0 = 208; + const auto objft0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); + if (!objft0Gain) { + for (auto i{0u}; i < nPixelsFT0; i++) { + ft0RelGainConst.push_back(1.); + } + } else { + ft0RelGainConst = *(objft0Gain); + } + + fullPath = cfgGainEqPath; + fullPath += "/FV0"; + const int nChannelsFV0 = 48; + const auto objfv0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); + if (!objfv0Gain) { + for (auto i{0u}; i < nChannelsFV0; i++) { + fv0RelGainConst.push_back(1.); + } + } else { + fv0RelGainConst = *(objfv0Gain); + } + + lastRunNumber = currentRunNumber; + } + } + cent = coll.cent(); epFlowHistograms.fill(HIST("hCentrality"), cent); epFlowHistograms.fill(HIST("hVertex"), coll.posZ()); From 62d8100ae638c263a9d875583d0de34271f21fca Mon Sep 17 00:00:00 2001 From: Andrea Giovanni Riffero Date: Thu, 28 May 2026 11:02:25 +0200 Subject: [PATCH 317/449] [PWGUD] Add ptSpectraInclusiveUpc.cxx (#16386) Co-authored-by: ALICE Action Bot --- PWGUD/Tasks/CMakeLists.txt | 5 + PWGUD/Tasks/ptSpectraInclusiveUpc.cxx | 423 ++++++++++++++++++++++++++ 2 files changed, 428 insertions(+) create mode 100644 PWGUD/Tasks/ptSpectraInclusiveUpc.cxx diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index b30af171280..6dbb62a449b 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -293,3 +293,8 @@ o2physics_add_dpl_workflow(fitbit-mapping SOURCES upcTestFITBitMapping.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pt-spectra-inclusive-upc + SOURCES ptSpectraInclusiveUpc.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx b/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx new file mode 100644 index 00000000000..8ddaff46569 --- /dev/null +++ b/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx @@ -0,0 +1,423 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file ptSpectraInclusiveUpc.cxx +/// \executable o2-analysis-ud-pt-spectra-inclusive-upc +/// \brief Task for the of pT spectra of pions, kaons and protons in inclusive UPC events. +/// Used to obtain the templates for the DCA_xy fits for the primary fractions +/// +/// \author Andrea Giovanni Riffero andrea.giovanni.riffero@cern.ch + +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct PtSpectraInclusiveUpc { + + Service pdg; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histos"}; + Configurable nBinsDCAxy{"nBinsDCAxy", 100, "N bins in DCA_{xy} histos"}; + Configurable applyKineCutsInGen{"applyKineCutsInGen", false, "Apply kinematic cuts in the generated level"}; + + Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + // define abbreviations + using CCs = soa::Join; + using CC = CCs::iterator; + using TCs = soa::Join; + using TC = TCs::iterator; + + const double etaMax = 0.9; + const double yMax = 0.9; + const double ptMin = 0.1; + const int nFindableMin = 70; + const double sigmaMax = 3.; + const double dcaZlimit = 2.; + + void init(InitContext const&) + { + + // axes + const AxisSpec axisPt{nBinsPt, 0, 5, "#it{p}_{T} GeV/#it{c}"}; + const AxisSpec axisEventCounter{2, 0.5, 2.5, "Event type"}; + const AxisSpec axisDCAxy{nBinsDCAxy, -0.6, 0.6, "DCA_{xy} cm"}; + + // histograms + histos.add("ptGeneratedPion", "ptGeneratedPion", kTH1F, {axisPt}); + histos.add("ptGeneratedKaon", "ptGeneratedKaon", kTH1F, {axisPt}); + histos.add("ptGeneratedProton", "ptGeneratedProton", kTH1F, {axisPt}); + + histos.add("ptReconstructedTPCPion", "ptReconstructedTPCPion", kTH1F, {axisPt}); + histos.add("ptReconstructedTPCKaon", "ptReconstructedTPCKaon", kTH1F, {axisPt}); + histos.add("ptReconstructedTPCProton", "ptReconstructedTPCProton", kTH1F, {axisPt}); + + histos.add("ptReconstructedTOFPion", "ptReconstructedTOFPion", kTH1F, {axisPt}); + histos.add("ptReconstructedTOFKaon", "ptReconstructedTOFKaon", kTH1F, {axisPt}); + histos.add("ptReconstructedTOFProton", "ptReconstructedTOFProton", kTH1F, {axisPt}); + + histos.add("ptDataTPCPion", "ptDataTPCPion", kTH1F, {axisPt}); + histos.add("ptDataTPCKaon", "ptDataTPCKaon", kTH1F, {axisPt}); + histos.add("ptDataTPCProton", "ptDataTPCProton", kTH1F, {axisPt}); + + histos.add("ptDataTOFPion", "ptDataTOFPion", kTH1F, {axisPt}); + histos.add("ptDataTOFKaon", "ptDataTOFKaon", kTH1F, {axisPt}); + histos.add("ptDataTOFProton", "ptDataTOFProton", kTH1F, {axisPt}); + + histos.add("myEventCounter", "myEventCounter", kTH1F, {axisEventCounter}); + histos.add("DCAxy_primary_pions", "DCAxy_primary_pions", kTH1F, {axisDCAxy}); + histos.add("DCAxy_secondary_pions", "DCAxy_secondary_pions", kTH1F, {axisDCAxy}); + histos.add("DCAxy_primary_kaons", "DCAxy_primary_kaons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_secondary_kaons", "DCAxy_secondary_kaons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_primary_protons", "DCAxy_primary_protons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_secondary_protons", "DCAxy_secondary_protons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_material_protons", "DCAxy_material_protons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_data_pions", "DCAxy_data_pions", kTH1F, {axisDCAxy}); + histos.add("DCAxy_data_kaons", "DCAxy_data_kaons", kTH1F, {axisDCAxy}); + histos.add("DCAxy_data_protons", "DCAxy_data_protons", kTH1F, {axisDCAxy}); + } + + void processSim(aod::UDMcCollision const&, aod::UDMcParticles const& mcParticles) + { + + std::array trackMomentum; + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + + trackMomentum[0] = mcParticle.px(); + trackMomentum[1] = mcParticle.py(); + trackMomentum[2] = mcParticle.pz(); + + if (applyKineCutsInGen) { + if (std::fabs(RecoDecay::eta(trackMomentum)) > etaMax) + continue; + + if (std::fabs(RecoDecay::y(trackMomentum, pdg->Mass(mcParticle.pdgCode()))) > yMax) + continue; + + if (RecoDecay::pt(trackMomentum) < ptMin) + continue; + } + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("ptGeneratedPion"), RecoDecay::pt(trackMomentum)); + } + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) { + histos.fill(HIST("ptGeneratedKaon"), RecoDecay::pt(trackMomentum)); + } + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) { + histos.fill(HIST("ptGeneratedProton"), RecoDecay::pt(trackMomentum)); + } + + histos.fill(HIST("myEventCounter"), 1); // gen event + } + } + + void processReco(CC const&, TCs const& tracks, aod::UDMcParticles const&) + { + + double dcaXyLimit = 0; + + auto nSigmaPi = -999.; + auto nSigmaKa = -999.; + auto nSigmaPr = -999.; + + std::array trackMomentum; + + for (const auto& track : tracks) { + if (!track.isPVContributor()) { + continue; + } + + if (track.tpcNClsFindable() < nFindableMin) { + continue; + } + + if (track.pt() < ptMin) { + continue; + } + + if (!(std::abs(track.dcaZ()) < dcaZlimit)) { + continue; + } + + dcaXyLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (!(std::abs(track.dcaXY()) < dcaXyLimit)) { + continue; + } + + trackMomentum[0] = track.px(); + trackMomentum[1] = track.py(); + trackMomentum[2] = track.pz(); + + if (!track.has_udMcParticle()) { + continue; + } + auto mcParticle = track.udMcParticle(); + + bool hasTpc = false; + // TPC tracks + if (track.hasTPC()) { + hasTpc = true; + nSigmaPi = track.tpcNSigmaPi(); + nSigmaKa = track.tpcNSigmaKa(); + nSigmaPr = track.tpcNSigmaPr(); + + if (std::abs(nSigmaPi) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassPionCharged)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTPCPion"), track.pt()); + histos.fill(HIST("DCAxy_primary_pions"), track.dcaXY()); + } else { + histos.fill(HIST("DCAxy_secondary_pions"), track.dcaXY()); + } + } + if (std::abs(nSigmaKa) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassKaonCharged)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTPCKaon"), track.pt()); + histos.fill(HIST("DCAxy_primary_kaons"), track.dcaXY()); + } else { + histos.fill(HIST("DCAxy_secondary_kaons"), track.dcaXY()); + } + } + + if (std::abs(nSigmaPr) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassProton)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTPCProton"), track.pt()); + histos.fill(HIST("DCAxy_primary_protons"), track.dcaXY()); + } else { + if (mcParticle.getProcess() == kPDecay) { + histos.fill(HIST("DCAxy_secondary_protons"), track.dcaXY()); + } else { + histos.fill(HIST("DCAxy_material_protons"), track.dcaXY()); + } + } + } + } + + // TPC tracks + if (track.hasTOF()) { + nSigmaPi = track.tofNSigmaPi(); + nSigmaKa = track.tofNSigmaKa(); + nSigmaPr = track.tofNSigmaPr(); + + if (std::abs(nSigmaPi) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassPionCharged)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTOFPion"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_primary_pions"), track.dcaXY()); + } else { + if (!hasTpc) + histos.fill(HIST("DCAxy_secondary_pions"), track.dcaXY()); + } + } + if (std::abs(nSigmaKa) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassKaonCharged)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTOFKaon"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_primary_kaons"), track.dcaXY()); + } else { + if (!hasTpc) + histos.fill(HIST("DCAxy_secondary_kaons"), track.dcaXY()); + } + } + + if (std::abs(nSigmaPr) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassProton)) > yMax) { + continue; + } + + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedTOFProton"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_primary_protons"), track.dcaXY()); + } else { + if (!hasTpc) { + if (mcParticle.getProcess() == kPDecay) { + histos.fill(HIST("DCAxy_secondary_protons"), track.dcaXY()); + } else { + histos.fill(HIST("DCAxy_material_protons"), track.dcaXY()); + } + } + } + } + } + } + } + + void processData(CC const&, TCs const& tracks) + { + + double dcaXyLimit = 0; + + auto nSigmaPi = -999.; + auto nSigmaKa = -999.; + auto nSigmaPr = -999.; + + std::array trackMomentum; + + for (const auto& track : tracks) { + if (!track.isPVContributor()) { + continue; + } + + if (track.tpcNClsFindable() < nFindableMin) { + continue; + } + + if (track.pt() < ptMin) { + continue; + } + + if (!(std::abs(track.dcaZ()) < dcaZlimit)) { + continue; + } + + dcaXyLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (!(std::abs(track.dcaXY()) < dcaXyLimit)) { + continue; + } + + trackMomentum[0] = track.px(); + trackMomentum[1] = track.py(); + trackMomentum[2] = track.pz(); + + bool hasTpc = false; + // TPC tracks + if (track.hasTPC()) { + hasTpc = true; + nSigmaPi = track.tpcNSigmaPi(); + nSigmaKa = track.tpcNSigmaKa(); + nSigmaPr = track.tpcNSigmaPr(); + + if (std::abs(nSigmaPi) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassPionCharged)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTPCPion"), track.pt()); + histos.fill(HIST("DCAxy_data_pions"), track.dcaXY()); + } + + if (std::abs(nSigmaKa) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassKaonCharged)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTPCKaon"), track.pt()); + histos.fill(HIST("DCAxy_data_kaons"), track.dcaXY()); + } + + if (std::abs(nSigmaPr) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassProton)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTPCProton"), track.pt()); + histos.fill(HIST("DCAxy_data_protons"), track.dcaXY()); + } + } + + // TPC tracks + if (track.hasTOF()) { + nSigmaPi = track.tofNSigmaPi(); + nSigmaKa = track.tofNSigmaKa(); + nSigmaPr = track.tofNSigmaPr(); + + if (std::abs(nSigmaPi) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassPionCharged)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTOFPion"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_data_pions"), track.dcaXY()); + } + if (std::abs(nSigmaKa) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassKaonCharged)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTOFKaon"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_data_kaons"), track.dcaXY()); + } + + if (std::abs(nSigmaPr) < sigmaMax) { + if (std::abs(RecoDecay::y(trackMomentum, o2::constants::physics::MassProton)) > yMax) { + continue; + } + histos.fill(HIST("ptDataTOFProton"), track.pt()); + if (!hasTpc) + histos.fill(HIST("DCAxy_data_protons"), track.dcaXY()); + } + } + } + } + + PROCESS_SWITCH(PtSpectraInclusiveUpc, processSim, "processSim", false); + + PROCESS_SWITCH(PtSpectraInclusiveUpc, processReco, "processReco", true); + + PROCESS_SWITCH(PtSpectraInclusiveUpc, processData, "processData", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From b28d6eae37471cd7a3b9463cf1947c46239bed83 Mon Sep 17 00:00:00 2001 From: MRazza <118839113+MRazza879@users.noreply.github.com> Date: Thu, 28 May 2026 13:19:25 +0200 Subject: [PATCH 318/449] [PWGHF] Add task h2fromlb (#16372) Co-authored-by: Marta Razza --- PWGHF/D2H/Tasks/CMakeLists.txt | 5 + PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx | 326 +++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 96296bf2c6b..a4e036cd80c 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -168,3 +168,8 @@ o2physics_add_dpl_workflow(task-hidden-charm SOURCES taskHiddenCharm.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-deuteron-from-lb + SOURCES taskDeuteronFromLb.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx b/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx new file mode 100644 index 00000000000..1a1f25d5372 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx @@ -0,0 +1,326 @@ +// 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 A filter task for non prompt deuterons from beauty-hadron decays +/// \author Marta Razza marta.razza@cern.ch +/// \author Francesca Ercolessi francesca.ercolessi@cern.ch +/// \since May 25, 2026 + +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfTaskDeuteronFromLb { + + Zorro zorro; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable applySkimming{"applySkimming", false, "Skimmed dataset processing"}; + Configurable cfgSkimming{"cfgSkimming", "fH2fromLb", "Configurable for skimming"}; + Configurable sel8{"sel8", true, "sel8 event selection"}; + Configurable separateAntideuterons{"separateAntideuterons", true, "Fill FromLb histos for primary deuterons whose mother is Lb, Primary histos for all others"}; + Configurable cfgEta{"cfgEta", 0.8f, "Track eta selection"}; + Configurable cfgTPCNclsFound{"cfgTPCNclsFound", 100, "Minimum TPC clusters found"}; + Configurable cfgTPCChi2Ncl{"cfgTPCChi2Ncl", 4.0f, "Maximum TPC chi2 per N clusters"}; + Configurable cfgITSChi2Ncl{"cfgITSChi2Ncl", 36.0f, "Maximum ITS chi2 per N clusters"}; + Configurable cfgITScls{"cfgITScls", 2, "Minimum ITS clusters"}; + Configurable cfgMaxPt{"cfgMaxPt", 5.0f, "Maximum pT cut"}; + Configurable cfgMinPt{"cfgMinPt", 0.5f, "Minimum pT cut"}; + Configurable cfgTPCNsigma{"cfgTPCNsigma", 4.0f, "TPC n sigma for deuteron PID"}; + Configurable cfgTofNsigmaMin{"cfgTofNsigmaMin", 3.0f, "TOF n sigma min for deuteron PID"}; + Configurable cfgTofNsigmaMax{"cfgTofNsigmaMax", 4.0f, "TOF n sigma max for deuteron PID"}; + Configurable ptThresholdPid{"ptThresholdPid", 1.0f, "pT threshold to switch between 4 and 3 sigmas for TOF PID"}; + Configurable rapidityCut{"rapidityCut", 0.5f, "Rapidity cut"}; + // PDG codes + Configurable pdgCodeMother{"pdgCodeMother", -5122, "PDG code of the mother particle (default: anti-Lambda_b)"}; + Configurable pdgCodeDaughter{"pdgCodeDaughter", -1000010020, "PDG code of the daughter particle (default: anti-deuteron)"}; + + int mRunNumber = 0; + float d_bz = 0.f; + int mCurrentRun = -1; + + framework::Service ccdb; + + using CollisionCandidates = o2::soa::Join; + using MCTrackCandidates = o2::soa::Join; + using MCCollisionCandidates = o2::soa::Join; + using TrackCandidates = o2::soa::Join; + + Preslice trackIndicesPerCollision = o2::aod::track_association::collisionId; + + HistogramRegistry QAHistos{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + OutputObj zorroSummary{"zorroSummary"}; + OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Event filtered;; Number of events", 4, 0., 4.)}; + + void init(framework::InitContext&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + + if (applySkimming) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + + ConfigurableAxis ptAxis{"ptAxis", {100, 0., 10.f}, "p_{T} GeV/c"}; + ConfigurableAxis nSigmaAxis{"nSigmaAxis", {200, -10.f, 10.f}, "nSigma"}; + ConfigurableAxis dcaXyAxis{"dcaXyAxis", {1000, -0.2f, 0.2f}, "DCA xy (cm)"}; + ConfigurableAxis dcaZAxis{"dcaZAxis", {1000, -0.2f, 0.2f}, "DCA z (cm)"}; + + QAHistos.add("hVtxZ", "Z-Vertex distribution after selection;Z (cm)", HistType::kTH1F, {{100, -50, 50}}); + QAHistos.add("ptGeneratedLb", "ptGeneratedLb", HistType::kTH1F, {ptAxis}); + QAHistos.add("ptAntiDeuteronPrimary", "ptAntiDeuteronPrimaryReco", HistType::kTH1F, {ptAxis}); + QAHistos.add("ptAntiDeuteronFromLb", "ptAntiDeuteronFromLbReco", HistType::kTH1F, {ptAxis}); + QAHistos.add("hDCAxy-Primary", "DCAxy-Primary", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); + QAHistos.add("hDCAxy-FromLb", "DCAxy-FromLb", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); + QAHistos.add("hDCAxyVsPt", "DCAxy #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaXyAxis}}); + QAHistos.add("hDCAzVsPt", "DCAz #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaZAxis}}); + QAHistos.add("hnSigmaTPCVsPt", "n#sigma TPC vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TPC", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); + QAHistos.add("hnSigmaTOFVsPt", "n#sigma TOF vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TOF", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); + QAHistos.add("ptAntiDeuteron", "ptAntiDeuteron", {HistType::kTH1F, {ptAxis}}); + QAHistos.add("etaAntideuteron", "etaAntideuteron", {HistType::kTH1F, {{100, -1.0f, 1.0f, "eta #bar{d}"}}}); + + hProcessedEvents->GetXaxis()->SetBinLabel(1, "Events processed"); + hProcessedEvents->GetXaxis()->SetBinLabel(2, "ZORRO"); + hProcessedEvents->GetXaxis()->SetBinLabel(3, "sel8"); + hProcessedEvents->GetXaxis()->SetBinLabel(4, "z-vertex"); + } + + void initCCDB(o2::aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + d_bz = 0.f; + + if (applySkimming) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfgSkimming.value); + zorro.populateHistRegistry(registry, bc.runNumber()); + } + } + + template + bool passedSingleTrackSelection(const T1& track) + { + if (std::abs(track.eta()) > cfgEta) + return false; + if (!track.hasITS()) + return false; + if (!track.hasTPC()) + return false; + if (!track.hasTOF()) + return false; + if (track.tpcNClsFound() < cfgTPCNclsFound) + return false; + if (track.tpcChi2NCl() > cfgTPCChi2Ncl) + return false; + if (track.itsChi2NCl() > cfgITSChi2Ncl) + return false; + if (track.itsNCls() < cfgITScls) + return false; + if (track.pt() > cfgMaxPt) + return false; + if (track.pt() < cfgMinPt) + return false; + if (track.sign() > 0) + return false; + + return true; + } + + void processData(CollisionCandidates const& collisions, + o2::aod::TrackAssoc const& trackIndices, + TrackCandidates const& tracks, + o2::aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + if (mCurrentRun != collision.bc_as().runNumber()) { + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", collision.bc_as().timestamp()); + o2::base::Propagator::initFieldFromGRP(grpo); + mCurrentRun = collision.bc_as().runNumber(); + } + + const auto& bc = collision.bc_as(); + initCCDB(bc); + hProcessedEvents->Fill(0.5); + if (applySkimming) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + hProcessedEvents->Fill(1.5); + if (sel8 && !collision.sel8()) { + continue; + } + hProcessedEvents->Fill(2.5); + if (std::abs(collision.posZ()) > cutzvertex) { + continue; + } + hProcessedEvents->Fill(3.5); + QAHistos.fill(HIST("hVtxZ"), collision.posZ()); + + const auto& trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + + for (const auto& trackId : trackIdsThisCollision) { + const auto& track = tracks.rawIteratorAt(trackId.trackId()); + std::array dca{track.dcaXY(), track.dcaZ()}; + + if (track.collisionId() != collision.globalIndex()) { + auto trackPar = getTrackParCov(track); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackPar, 2.f, noMatCorr, &dca); + } + + if (!passedSingleTrackSelection(track)) { + continue; + } + + const bool isTPCDe = std::abs(track.tpcNSigmaDe()) < cfgTPCNsigma; + const bool isTOFDe_min = std::abs(track.tofNSigmaDe()) > cfgTofNsigmaMin; + const bool isTOFDe_max = std::abs(track.tofNSigmaDe()) < cfgTofNsigmaMax; + + if (track.pt() < ptThresholdPid) { + if (isTPCDe && isTOFDe_max) { + QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + } + } else { + if (isTPCDe && isTOFDe_min && isTOFDe_max) { + QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + } + } + } + } + } + PROCESS_SWITCH(HfTaskDeuteronFromLb, processData, "processData", false); + + void processMC(MCCollisionCandidates::iterator const&, MCTrackCandidates const& tracks, o2::aod::McParticles const&) + { + for (const auto& track : tracks) { + if (!passedSingleTrackSelection(track)) { + continue; + } + + if (!track.has_mcParticle()) { + continue; + } + + auto mcParticle = track.mcParticle(); + if (mcParticle.pdgCode() == pdgCodeDaughter) { + if (std::abs(mcParticle.y()) > rapidityCut) { + continue; + } + if (mcParticle.isPhysicalPrimary()) { + bool isFromLb = false; + if (separateAntideuterons) { + for (const auto& mom : mcParticle.mothers_as()) { + if (mom.pdgCode() == pdgCodeMother) { + isFromLb = true; + break; + } + } + } + if (isFromLb) { + QAHistos.fill(HIST("hDCAxy-FromLb"), track.dcaXY()); + QAHistos.fill(HIST("ptAntiDeuteronFromLb"), track.pt()); + } else { + QAHistos.fill(HIST("hDCAxy-Primary"), track.dcaXY()); + QAHistos.fill(HIST("ptAntiDeuteronPrimary"), track.pt()); + } + } + } + } + } + PROCESS_SWITCH(HfTaskDeuteronFromLb, processMC, "processMC", true); + + void processGen(o2::aod::McCollision const&, o2::aod::McParticles const& mcParticles) + { + hProcessedEvents->Fill(0.5); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.pdgCode() == pdgCodeMother) { + if (std::abs(mcParticle.y()) <= rapidityCut) { + QAHistos.fill(HIST("ptGeneratedLb"), mcParticle.pt()); + } + } + + if (mcParticle.pdgCode() == pdgCodeDaughter) { + if (std::abs(mcParticle.y()) > rapidityCut) + continue; + + bool isFromLb = false; + if (mcParticle.has_mothers()) { + for (const auto& mom : mcParticle.mothers_as()) { + if (mom.pdgCode() == pdgCodeMother) { + isFromLb = true; + break; + } + } + } + + if (isFromLb) { + QAHistos.fill(HIST("ptAntiDeuteronFromLb"), mcParticle.pt()); + } else if (mcParticle.isPhysicalPrimary()) { + QAHistos.fill(HIST("ptAntiDeuteronPrimary"), mcParticle.pt()); + } + } + } + } + PROCESS_SWITCH(HfTaskDeuteronFromLb, processGen, "processGen", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 4f9c453fc0bfdddfe17693f4e6d0d015a07bac95 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Thu, 28 May 2026 14:23:34 +0200 Subject: [PATCH 319/449] [PWGDQ] Fix bin index retrieval for efficiency histogram (#16431) --- PWGDQ/Core/VarManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 1d5bd30e476..f9c0105dbd5 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -414,7 +414,7 @@ void VarManager::FillEfficiency(float* values) } TH3F* efficiencyHist = reinterpret_cast(fgEfficiencyHist); // Get the bin indices for the efficiency histogram - int binPt = efficiencyHist->GetXaxis()->FindBin(values[kPairPt]); + int binPt = efficiencyHist->GetXaxis()->FindBin(values[kPt]); binPt = (binPt == 0 ? 1 : binPt); binPt = (binPt > efficiencyHist->GetXaxis()->GetNbins() ? efficiencyHist->GetXaxis()->GetNbins() : binPt); int binCent = efficiencyHist->GetYaxis()->FindBin(values[kCentFT0C]); From 7d24a13b7803b6665d5e1ac3d789b300628c594d Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Thu, 28 May 2026 14:44:00 +0200 Subject: [PATCH 320/449] [PWGDQ] fix reduced MCH track index in output table (#16429) --- PWGDQ/Tasks/qaMatching.cxx | 41 +++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index b886909a3ea..4a8689fc0bc 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -93,7 +93,6 @@ DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(MatchLabel, matchLabel, int8_t); -DECLARE_SOA_COLUMN(TrackId, trackId, int64_t); DECLARE_SOA_COLUMN(MatchType, matchType, int8_t); DECLARE_SOA_COLUMN(MatchChi2, matchChi2, float); DECLARE_SOA_COLUMN(MatchScore, matchScore, float); @@ -133,7 +132,6 @@ namespace o2::aod DECLARE_SOA_TABLE(QaMatchingMCHTrack, "AOD", "QAMCHTRK", o2::soa::Index<>, qamatching::ReducedEventId, - qamatching::TrackId, qamatching::TrackType, qamatching::P, qamatching::Pt, @@ -147,11 +145,20 @@ DECLARE_SOA_TABLE(QaMatchingMCHTrack, "AOD", "QAMCHTRK", qamatching::PxAtVtx, qamatching::PyAtVtx, qamatching::PzAtVtx); +} // namespace o2::aod + +namespace qamatching +{ +DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(ReducedTrack, reducedTrack, int32_t, o2::aod::QaMatchingMCHTrack, "QAMCHTRKs", ""); +} // namespace qamatching + +namespace o2::aod +{ DECLARE_SOA_TABLE(QaMatchingCandidates, "AOD", "QAMCAND", o2::soa::Index<>, qamatching::ReducedEventId, + qamatching::ReducedTrackId, qamatching::MatchLabel, - qamatching::TrackId, qamatching::P, qamatching::Pt, qamatching::Eta, qamatching::Phi, qamatching::MatchType, qamatching::MatchChi2, qamatching::MatchScore, qamatching::MatchRanking, qamatching::XAtVtx, @@ -162,6 +169,11 @@ DECLARE_SOA_TABLE(QaMatchingCandidates, "AOD", "QAMCAND", qamatching::PzAtVtx); } // namespace o2::aod +namespace qamatching +{ +DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(Candidate, candidate, int32_t, o2::aod::QaMatchingCandidates, "QAMCANDs", ""); +} // namespace qamatching + using MyEvents = soa::Join; using MyMuons = soa::Join; using MyMuonsMC = soa::Join; @@ -458,6 +470,8 @@ struct QaMatching { std::vector mftTracks; // vector of MCH(-MID) track indexes std::vector mchTracks; + // mapping between original and reduced MCH track indexes + std::map reducedMchTrackIds; // matching candidates MatchingCandidates matchingCandidates; // vector of MFT-MCH track index pairs belonging to the same MC muon particle @@ -1986,6 +2000,7 @@ struct QaMatching { if (collisionIds.empty()) return; + int64_t reducedMchTrackId = 0; for (size_t cid = 0; cid < collisionIds.size(); cid++) { const auto& collision = collisions.rawIteratorAt(collisionIds[cid]); int64_t collisionIndex = collision.globalIndex(); @@ -2015,6 +2030,8 @@ struct QaMatching { // standalone MCH or MCH-MID tracks int64_t mchTrackIndex = muonTrack.globalIndex(); collisionInfo.mchTracks.push_back(mchTrackIndex); + collisionInfo.reducedMchTrackIds[mchTrackIndex] = reducedMchTrackId; + reducedMchTrackId += 1; } else { // global muon tracks (MFT-MCH or MFT-MCH-MID) int64_t muonTrackIndex = muonTrack.globalIndex(); @@ -2916,7 +2933,7 @@ struct QaMatching { //------------------------------- // Chi2-based matching from production - fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); } else { @@ -2970,7 +2987,7 @@ struct QaMatching { double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; - fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); } else { @@ -2988,7 +3005,7 @@ struct QaMatching { double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; - fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId); + fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); } else { @@ -3006,7 +3023,8 @@ struct QaMatching { TMUON const& muonTracks, const MatchingCandidates& matchingCandidates, int8_t matchLabel, - int32_t reducedEventId) + int32_t reducedEventId, + std::map reducedMchTrackIds) { for (const auto& [mchIndex, candidates] : matchingCandidates) { if (candidates.empty()) { @@ -3018,13 +3036,19 @@ struct QaMatching { continue; } + auto reducedMchTrackIdIt = reducedMchTrackIds.find(mchIndex); + if (reducedMchTrackIdIt == reducedMchTrackIds.end()) { + continue; + } + int64_t reducedMchTrackId = reducedMchTrackIdIt->second; + for (const auto& candidate : candidates) { const auto& candidateTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); auto candidateTrackAtVertex = VarManager::PropagateMuon(candidateTrack, collision, VarManager::kToVertex); qaMatchingCandidates( reducedEventId, + reducedMchTrackId, matchLabel, - mchIndex, static_cast(candidateTrack.p()), static_cast(candidateTrack.pt()), static_cast(candidateTrack.eta()), @@ -3095,7 +3119,6 @@ struct QaMatching { } qaMatchingMCHTrack( reducedEventId, - mchIndex, static_cast(mchTrack.trackType()), static_cast(mchTrack.p()), static_cast(mchTrack.pt()), From 74c90a5e61367d9a3d5256082a13fb7f33187af2 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 28 May 2026 18:28:12 +0200 Subject: [PATCH 321/449] [PWGEM/Dilepton] add option to apply PF in single electron QC task (#16438) --- PWGEM/Dilepton/Core/SingleTrackQC.h | 2 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 015ed26ec32..32b1d5fec41 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -67,7 +67,7 @@ using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyElectrons = o2::soa::Join; +using MyElectrons = o2::soa::Join; using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 8c823c9a1b3..18c35af06ab 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -70,7 +70,7 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = o2::soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyMCElectrons = o2::soa::Join; +using MyMCElectrons = o2::soa::Join; using MyMCElectron = MyMCElectrons::iterator; using FilteredMyMCElectrons = o2::soa::Filtered; From 9e3239b796724643429e8ef9ab59fcd3c6260e1d Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Thu, 28 May 2026 18:28:51 +0200 Subject: [PATCH 322/449] [PWGHF] Add the number of tracks into the charm-bulk thnsparse in `taskPtFlucCharmHadrons.cxx` (#16434) --- PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx index 4b1b6362692..0f53b2ab63e 100644 --- a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx @@ -186,7 +186,7 @@ struct HfTaskPtFlucCharmHadrons { // charm-bulk correlations (optional) if (saveCharmBulkCorrelations) { - registry.add("hCharmBulkCorrelations", "Charm-bulk correlations", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo, aCandEta, aMPtTrkA, aMPtTrkB, aPtCandProduct}, true); + registry.add("hCharmBulkCorrelations", "Charm-bulk correlations", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, aMlOne, aMlTwo, aCandEta, aMPtTrkA, aMPtTrkB, aPtCandProduct, aNTrkA, aNTrkB}, true); registry.add("hMeanPtTrkAllColls", "Mean pT of charged hadrons for all collisions", HistType::kTHnSparseF, {aCent, aMPtTrkA, aMPtTrkB, aPtTrkProduct, aNTrkA, aNTrkB}, true); } @@ -250,7 +250,7 @@ struct HfTaskPtFlucCharmHadrons { /// remove candidate daughters from the mean pT of tracks in A and B (if they are in the respective subevent) template - float removeDaughtersFromMeanPt(const CandT& cand, float rawMeanPt, int n, const std::vector& trkIDs) + std::pair removeDaughtersFromMeanPt(const CandT& cand, float rawMeanPt, int n, const std::vector& trkIDs) { int removedCount = 0; float removedSumPt = 0.f; @@ -270,9 +270,9 @@ struct HfTaskPtFlucCharmHadrons { } if (removedCount > 0) { double totalSum = static_cast(rawMeanPt) * n; - return static_cast((totalSum - removedSumPt) / (n - removedCount)); + return {static_cast((totalSum - removedSumPt) / (n - removedCount)), n - removedCount}; } - return rawMeanPt; + return {rawMeanPt, n}; } // --------------------------------------------------------------------------- @@ -420,12 +420,14 @@ struct HfTaskPtFlucCharmHadrons { float candPtProduct{0.f}; float meanPtA{0.f}; float meanPtB{0.f}; + int nATrk{nA}; + int nBTrk{nB}; if (eta > etaAMin.value && eta < etaAMax.value) { - meanPtB = removeDaughtersFromMeanPt(cand, RawMeanPtB, nB, trkIDB); + std::tie(meanPtB, nBTrk) = removeDaughtersFromMeanPt(cand, RawMeanPtB, nB, trkIDB); meanPtA = RawMeanPtA; // no need to remove daughters from A if candidate is in A candPtProduct = pt * meanPtB; } else if (eta > etaBMin.value && eta < etaBMax.value) { - meanPtA = removeDaughtersFromMeanPt(cand, RawMeanPtA, nA, trkIDA); + std::tie(meanPtA, nATrk) = removeDaughtersFromMeanPt(cand, RawMeanPtA, nA, trkIDA); meanPtB = RawMeanPtB; // no need to remove daughters from B if candidate is in B candPtProduct = pt * meanPtA; } @@ -434,7 +436,7 @@ struct HfTaskPtFlucCharmHadrons { auto [invMass, sign] = getCandMassAndSign(cand); // fill charm-bulk correlation thnsparse - registry.fill(HIST("hCharmBulkCorrelations"), invMass, cent, pt, sign, ml1, ml2, eta, meanPtA, meanPtB, candPtProduct); + registry.fill(HIST("hCharmBulkCorrelations"), invMass, cent, pt, sign, ml1, ml2, eta, meanPtA, meanPtB, candPtProduct, nATrk, nBTrk); } } else { int nDcandTotA = 0; From 5c0fe997f0744c88baafa20230872df6f5c26ca0 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Thu, 28 May 2026 18:31:39 +0200 Subject: [PATCH 323/449] [PWGLF] Add extra histo for charged track pt (#16437) --- PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx index 6070921bbe1..10a72a46eaf 100644 --- a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -664,6 +664,7 @@ struct FlattenictyPikp { registryData.add("Tracks/postSel/hPt", "", kTH1F, {ptAxis}); registryData.add("Tracks/postSel/hPhi", "", kTH1F, {phiAxis}); registryData.add("Tracks/postSel/hEta", "", kTH1F, {etaAxis}); + registryData.add("Tracks/postSel/hTpcInnerParamVsP", ";Global track p (GeV/#it{c});Track p at inner wall of the TPC (GeV/#it{c});", kTH2F, {pAxis, pAxis}); registryData.add("Tracks/postSel/hDCAXYvsPt", "", kTH2F, {ptAxis, dcaXYAxis}); registryData.add("Tracks/postSel/hDCAZvsPt", "", kTH2F, {ptAxis, dcaZAxis}); // tpc @@ -721,6 +722,8 @@ struct FlattenictyPikp { registryData.addClone("Tracks/V0qa/pi/La/", "Tracks/V0qa/pr/La/"); registryData.addClone("Tracks/V0qa/pi/ALa/", "Tracks/V0qa/pr/ALa/"); + // charged pT + registryData.add({"Tracks/all/hFlatVsPt", "; #eta; mult; flat; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, ptAxis}}}); // dEdx PID registryData.add({"Tracks/all/hdEdx", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); // Clean samples @@ -1080,11 +1083,14 @@ struct FlattenictyPikp { // PID TPC dEdx if (cfgFillChrgType) { if (track.sign() * track.p() > Cnull) { + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kPos]) + HIST("hFlatVsPt"), track.eta(), mult, flat, track.p(), track.pt()); registryData.fill(HIST(Cprefix) + HIST(Ccharge[kPos]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } else { + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kNeg]) + HIST("hFlatVsPt"), track.eta(), mult, flat, track.p(), track.pt()); registryData.fill(HIST(Cprefix) + HIST(Ccharge[kNeg]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } } else { + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kAll]) + HIST("hFlatVsPt"), track.eta(), mult, flat, track.p(), track.pt()); registryData.fill(HIST(Cprefix) + HIST(Ccharge[kAll]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } @@ -1657,6 +1663,7 @@ struct FlattenictyPikp { registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPt"), track.pt()); registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPhi"), track.phi()); registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hEta"), track.eta()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTpcInnerParamVsP"), track.tpcInnerParam(), track.p()); registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAXYvsPt"), track.pt(), track.dcaXY()); registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAZvsPt"), track.pt(), track.dcaZ()); From 02278cd73e424e9842a487e0a0de53bb9a815ac4 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Fri, 29 May 2026 13:05:25 +0800 Subject: [PATCH 324/449] [PWGCF] flowDirectedFlowTask.cxx: adding q1 axis th the resolution (#16441) --- PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx index 253174ef5bb..530e528badc 100644 --- a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx +++ b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx @@ -163,8 +163,8 @@ struct flowDirectedFlowTask { histos.add("hQxCvscent", "Qx C vs centrality", kTH2F, {{centAxis}, {qAxis}}); histos.add("hQyCvscent", "Qy C vs centrality", kTH2F, {{centAxis}, {qAxis}}); - histos.add("hpResCosAC", "cos(#Psi_{A}-#Psi_{C}) vs centrality", kTH2F, {{centAxis}, {resAxis}}); - histos.add("hpResDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH2F, {{centAxis}, {resAxis}}); + histos.add("hpResCosAC", "cos(#Psi_{A}-#Psi_{C}) vs centrality", kTH3F, {{centAxis}, {resAxis}, {q1Axis}}); + histos.add("hpResDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH3F, {{centAxis}, {resAxis}, {q1Axis}}); histos.add("hpQxAQxC", "QxA QxC", kTH2F, {{centAxis}, {resAxis}}); histos.add("hpQyAQyC", "QyA QyC", kTH2F, {{centAxis}, {resAxis}}); histos.add("hpQxAQyC", "QxA QyC", kTH2F, {{centAxis}, {resAxis}}); @@ -524,8 +524,8 @@ struct flowDirectedFlowTask { float dotAC = qxA * qxC + qyA * qyC; float resDot = dotAC / (magA * magC); - histos.fill(HIST("hpResCosAC"), centrality, std::cos(psiA - psiC)); - histos.fill(HIST("hpResDotAC"), centrality, resDot); + histos.fill(HIST("hpResCosAC"), centrality, std::cos(psiA - psiC), q1); + histos.fill(HIST("hpResDotAC"), centrality, resDot, q1); histos.fill(HIST("hpQxAQxC"), centrality, qxA * qxC); histos.fill(HIST("hpQyAQyC"), centrality, qyA * qyC); histos.fill(HIST("hpQxAQyC"), centrality, qxA * qyC); From da3c9cac8cfdcdc5aeeaf8e3f316102a182e3df4 Mon Sep 17 00:00:00 2001 From: Pei-Ying Kuan <128475937+pykuan@users.noreply.github.com> Date: Fri, 29 May 2026 07:50:12 +0200 Subject: [PATCH 325/449] [PWGCF] add some event cuts, particle cuts and histograms (#16426) Co-authored-by: Pei-Ying Kuan --- .../Tasks/multiparticleCumulants.cxx | 534 +++++++++++++++--- 1 file changed, 440 insertions(+), 94 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx index d99dc18aa21..0b5ceafdd47 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticleCumulants.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -63,6 +65,9 @@ using TrackSim = aod::McParticles::iterator; using namespace std; // *) Define enums: +enum EnRlMc { eRl = 0, + eMc }; + enum EnRecSim { eRec = 0, eSim, eRecAndSim }; @@ -80,6 +85,7 @@ enum EnEventHistograms { eVertexX, eVertexY, eVertexZ, + eNumContrib, eEventHistograms_N }; @@ -89,7 +95,7 @@ const char* eventHistNames[eEventHistograms_N] = { "VertexX", "VertexY", "VertexZ", -}; + "NumContrib"}; enum EnParticleHistograms { ePt, @@ -103,6 +109,7 @@ const char* particleHistNames[eParticleHistograms_N] = { enum EnQAHistograms { eQACent, + eQAMultNumContrib, eQAHistograms_N }; @@ -115,8 +122,9 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType::OutputObjSource}; - // *) CCDB: - Service ccdb; // support for offline callibration data base, not needed for the time being... + // *) Service: + Service ccdb; // support for offline callibration data base + Service pdg; // *) Define configurables: Configurable cfDryRun{"cfDryRun", false, "book all histos and run without filling and calculating anything"}; // example for built-in type (float, string, etc.) @@ -125,21 +133,48 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam Configurable cfQASwitch{"cfQASwitch", true, "quality assurance switch"}; Configurable cfWeightSwitch{"cfWeightSwitch", true, "weight switch"}; - Configurable> cfVertexZ{"cfVertexZ", {-10., 10.}, "vertex z position range: {min, max}[cm], with convention: min <= Vz < max"}; - Configurable cfVertexZSwitch{"cfVertexZSwitch", true, "vertex z cut switch"}; - Configurable> cfPt{"cfPt", {0.2, 5.0}, "Pt range: {min, max}[GeV], with convention: min <= Pt < max"}; - Configurable cfPtSwitch{"cfPtSwitch", true, "Pt cut switch"}; - - Configurable cfFileWithWeights{"cfFileWithWeights", "/scratch3/go52dab/O2tutorial/tutorial3-5/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; + Configurable cfPrintSwitch{"cfPrintSwitch", true, "printing result switch"}; + + // *) Event cut switches + Configurable cfVertexZCutSwitch{"cfVertexZCutSwitch", true, "vertex z cut switch"}; + Configurable cfSel8CutSwitch{"cfSel8CutSwitch", true, "Sel8 cut switch"}; + Configurable cfCentCutSwitch{"cfCentCutSwitch", true, "centrality cut switch"}; + Configurable cfNumContribCutSwitch{"cfNumContribCutSwitch", true, "NContribution cut switch"}; + + // *) Particle cut switches + Configurable cfPtCutSwitch{"cfPtCutSwitch", true, "Pt cut switch"}; + Configurable cfEtaCutSwitch{"cfEtaCutSwitch", true, "Eta cut switch"}; + Configurable cfSignCutSwitch{"cfSignCutSwitch", true, "Charge cut switch"}; + Configurable cfTpcNClsFoundCutSwitch{"cfTpcNClsFoundCutSwitch", true, ""}; + Configurable cfDCAXYCutSwitch{"cfDCAXYCutSwitch", true, ""}; + Configurable cfDCAZCutSwitch{"cfDCAZCutSwitch", true, ""}; + + // *) Event cut + Configurable> cfVertexZCut{"cfVertexZCut", {-10., 10.}, "vertex z position range: {min, max}[cm]"}; + Configurable> cfCentCut{"cfCentCut", {10., 20.}, "centrality range: {min, max}[%]"}; + Configurable> cfNumContribCut{"cfNumContribCut", {0, 3000.}, "NContribution range: {min, max}"}; + + // *) Particle cut + Configurable> cfPtCut{"cfPtCut", {0.2, 5.0}, "Pt range: {min, max}[GeV], with convention: min <= Pt < max"}; + Configurable> cfEtaCut{"cfEtaCut", {-0.8, 0.8}, "Eta range: {min, max}, with convention: min <= Eta < max"}; + Configurable> cfSignCut{"cfSignCut", {1, 0, 1}, "sign of charge, 1 to keep and 0 to discard, {negative, neutral, positive}"}; + Configurable> cfTpcNClsFoundCut{"cfTpcNClsFoundCut", {70., 160.}, "range of found TPC clusters for this track geometry: {min, max}"}; + Configurable> cfDCAXYCut{"cfDCAXYCut", {-3.2, 3.2}, "range of distance-of-closest-approach (DCA) of the extrapolated track to the primary position in XY-direction: {min, max}[cm]"}; + Configurable> cfDCAZCut{"cfDCAZCut", {-2.4, 2.4}, "range of distance-of-closest-approach (DCA) of the extrapolated track to the primary position in Z-direction: {min, max}[cm]"}; + + // *) + Configurable cfFileWithWeights{"cfFileWithWeights", "/scratch3/go52dab/O2tutorial/tutorial3-6/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; Configurable cfRunNumber{"cfRunNumber", "000123456", "run number"}; + // *) Bins Configurable> cfPtBins{"cfPtBins", {1000, 0., 100.}, "nPtBins, ptMin, ptMax"}; Configurable> cfPhiBins{"cfPhiBins", {1000, 0., o2::constants::math::TwoPI}, "nPhiBins, phiMin, phiMax"}; Configurable> cfCentBins{"cfCentBins", {100, 0., 100.}, "nCenBins, cenMin, cenMax"}; - Configurable> cfMultBins{"cfMultBins", {100, 0., 1000.}, "nMultBins, MultMin, MultMax"}; + Configurable> cfMultBins{"cfMultBins", {100, 0., 5000.}, "nMultBins, MultMin, MultMax"}; Configurable> cfVerXBins{"cfVerXBins", {100, -0.05, 0.05}, "nVerXBins, VerXMin, VerXMax"}; Configurable> cfVerYBins{"cfVerYBins", {100, -0.05, 0.05}, "nVerYBins, VerYMin, VerYMax"}; Configurable> cfVerZBins{"cfVerZBins", {100, -50., 50.}, "nVerZBins, VerZMin, VerZMax"}; + Configurable> cfNumContribBins{"cfNumContribBins", {100, 0., 5000.}, "nNumContribBins, NumContribMin, NumContribMax"}; // *) Define and initialize all data members to be called in the main process* functions: // **) Task configuration: @@ -148,11 +183,43 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam bool fDryRun = kFALSE; // book all histos and run without filling and calculating anything std::string fCentEstm = "FT0M"; std::string fMultEstm = "FT0A"; - std::vector fVertexZ = {-10., 10.}; - bool fVertexZSwitch = true; - std::vector fPt = {0.2, 5.0}; - bool fPtSwitch = true; - std::string fFileWithWeights = "/scratch3/go52dab/O2tutorial/tutorial3-5/weights.root"; + + bool fPrintSwitch = true; + + bool fVertexZCutSwitch = true; + bool fSel8CutSwitch = true; + bool fCentCutSwitch = true; + bool fNumContribCutSwitch = true; + + bool fPtCutSwitch = true; + bool fEtaCutSwitch = true; + bool fSignCutSwitch = true; + bool fTpcNClsFoundCutSwitch = true; + bool fDCAXYCutSwitch = true; + bool fDCAZCutSwitch = true; + + std::vector fVertexZCut = {-10., 10.}; + std::vector fCentCut = {10., 20.}; + std::vector fNumContribCut = {0, 3000.}; + + std::vector fPtCut = {0.2, 5.0}; + std::vector fEtaCut = {-0.8, 0.8}; + std::vector fSignCut = {1, 0, 1}; + std::vector fTpcNClsFoundCut = {70., 160.}; + std::vector fDCAXYCut = {-3.2, 3.2}; + std::vector fDCAZCut = {-2.4, 2.4}; + + std::vector fPtBins = {0., 100.}; + std::vector fPhiBins = {0., o2::constants::math::TwoPI}; + + std::vector fCentBins = {0., 100.}; + std::vector fMultBins = {0, 5000}; + std::vector fVerXBins = {-0.05, 0.05}; + std::vector fVerYBins = {-0.05, 0.05}; + std::vector fVerZBins = {-50., 50.}; + std::vector fNumContribBins = {0, 5000}; + + std::string fFileWithWeights = "/scratch3/go52dab/O2tutorial/tutorial3-6/weights.root"; std::string fRunNumber = "000123456"; } tc; // you have to prepend "tc." for all objects name in this group later in the code @@ -171,7 +238,7 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam struct QAHistograms { bool fQASwitch = kTRUE; TList* fQAHistogramsList = NULL; - TH2F* fQAHistograms[eQAHistograms_N][2] = {{NULL}}; //[type][cut] + TH2F* fQAHistograms[eQAHistograms_N][2] = {{NULL}}; //[type][before/after cut] } qa; struct WeightHistograms { @@ -185,18 +252,109 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam float fCentrality = 0.; float fCentralitySim = 0.; float fImpactParameter = 0.; + float fNumContrib = 0.; } ebye; - template - bool EventCuts(T1 const& collision) + template + bool ctEventCuts(T1 const& collision) { - return (collision.posZ() < tc.fVertexZ[1] && collision.posZ() > tc.fVertexZ[0]); + bool pass = true; + + bool bVertexZCut = true; + bool bSel8Cut = true; + bool bCentCut = true; + bool bNumContribCut = true; + + // *) For real event and MC event + bVertexZCut = collision.posZ() < tc.fVertexZCut[1] && collision.posZ() > tc.fVertexZCut[0]; + + // *) For real event only + if constexpr (rm == eRl) { + bSel8Cut = collision.sel8(); + bCentCut = ebye.fCentrality < tc.fCentCut[1] && ebye.fCentrality > tc.fCentCut[0]; + bNumContribCut = ebye.fNumContrib < tc.fNumContribCut[1] && ebye.fNumContrib > tc.fNumContribCut[0]; + } + + // *) For MC event only + if constexpr (rm == eMc) { + bCentCut = ebye.fCentralitySim < tc.fCentCut[1] && ebye.fCentralitySim > tc.fCentCut[0]; + } + + if (tc.fVertexZCutSwitch) { + pass = pass && bVertexZCut; + } + if (tc.fSel8CutSwitch) { + pass = pass && bSel8Cut; + } + if (tc.fCentCutSwitch) { + pass = pass && bCentCut; + } + if (tc.fNumContribCutSwitch) { + pass = pass && bNumContribCut; + } + + return pass; } - template - bool ParticleCuts(T1 const& track) + template + bool ctParticleCuts(T1 const& track) { - return (track.pt() < tc.fPt[1] && track.pt() > tc.fPt[0]); + bool pass = true; + + bool bPtCut = true; + bool bEtaCut = true; + bool bSignCut = true; + bool bTpcNClsFoundCut = true; + bool bDCAXYCut = true; + bool bDCAZCut = true; + + // *) For real event and MC event + bPtCut = track.pt() < tc.fPtCut[1] && track.pt() > tc.fPtCut[0]; + bEtaCut = track.eta() < tc.fEtaCut[1] && track.eta() > tc.fEtaCut[0]; + + // *) For real event only + if constexpr (rm == eRl) { + bSignCut = (track.sign() == -1 && tc.fSignCut[0]) || (track.sign() == 0 && tc.fSignCut[1]) || (track.sign() == 1 && tc.fSignCut[2]); + bTpcNClsFoundCut = track.tpcNClsFound() < tc.fTpcNClsFoundCut[1] && track.tpcNClsFound() > tc.fTpcNClsFoundCut[0]; + bDCAXYCut = track.dcaXY() < tc.fDCAXYCut[1] && track.dcaXY() > tc.fDCAXYCut[0]; + bDCAZCut = track.dcaZ() < tc.fDCAZCut[1] && track.dcaZ() > tc.fDCAZCut[0]; + } + + // *) For mc event only + if constexpr (rm == eMc) { + // TDatabasePDG *db= TDatabasePDG::Instance(); + TParticlePDG* particle = pdg->GetParticle(track.pdgCode()); + + if (!particle) { + // LOGF(warning, "PDG code %d not found", track.pdgCode()); + bSignCut = false; + } else { + // LOGF(info, "PDG code %d found", track.pdgCode()); + float charge = particle->Charge(); + bSignCut = (charge < 0 && tc.fSignCut[0]) || (charge == 0 && tc.fSignCut[1]) || (charge > 0 && tc.fSignCut[2]); + } + } + + if (tc.fPtCutSwitch) { + pass = pass && bPtCut; + } + if (tc.fEtaCutSwitch) { + pass = pass && bEtaCut; + } + if (tc.fSignCutSwitch) { + pass = pass && bSignCut; + } + if (tc.fTpcNClsFoundCutSwitch) { + pass = pass && bTpcNClsFoundCut; + } + if (tc.fDCAXYCutSwitch) { + pass = pass && bDCAXYCut; + } + if (tc.fDCAZCutSwitch) { + pass = pass && bDCAZCut; + } + + return pass; } TObject* getObjectFromList(TList* list, const char* objectName) @@ -258,7 +416,7 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam TString filePathStr(filePath); - if (filePathStr(0, 17) == "/alice/data/CCDB/" || filePathStr(0, 15) == "/alice/cern.ch/") { + if (filePathStr(0, 7) == "/alice/") { bFileIsInAliEn = true; } else if (filePathStr(0, 20) == "/alice-ccdb.cern.ch/") { bFileIsInCCDB = true; @@ -383,8 +541,10 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam return; } - // Print current run number: - LOGF(info, "Run number: %d", collision.bc().runNumber()); + if (tc.fPrintSwitch) { + // Print current run number: + LOGF(info, "Run number: %d", collision.bc().runNumber()); + } float rlCollisionCent = 0.; if (tc.fCentEstm == "FT0M") @@ -396,15 +556,6 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam else if (tc.fCentEstm == "FT0C") rlCollisionCent = collision.centFT0C(); - // Print centrality estimated with "FT0M" estimator: - LOGF(info, "Centrality: %f", rlCollisionCent); - ebye.fCentrality = rlCollisionCent; - - // Print vertex position: - LOGF(info, "Vertex X position: %f", collision.posX()); - LOGF(info, "Vertex Y position: %f", collision.posY()); - LOGF(info, "Vertex Z position: %f", collision.posZ()); - float rlCollisionMult = 0.; if (tc.fMultEstm == "FT0A") rlCollisionMult = collision.multFT0A(); @@ -419,9 +570,27 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam else if (tc.fMultEstm == "NTracksPV") rlCollisionMult = collision.multNTracksPV(); - // Print multiplicity: - LOGF(info, "Multiplicity: %f", (float)rlCollisionMult); + float rlCollisionNumContrib = 0.; + rlCollisionNumContrib = static_cast(collision.numContrib()); + + if (tc.fPrintSwitch) { + // Print centrality estimated with "FT0M" estimator: + LOGF(info, "Centrality: %f", rlCollisionCent); + + // Print multiplicity: + LOGF(info, "Multiplicity: %f", static_cast(rlCollisionMult)); + + // Print vertex position: + LOGF(info, "Vertex X position: %f", collision.posX()); + LOGF(info, "Vertex Y position: %f", collision.posY()); + LOGF(info, "Vertex Z position: %f", collision.posZ()); + + // Print NContributors + LOGF(info, "NContributors: %f", static_cast(rlCollisionNumContrib)); + } + ebye.fCentrality = rlCollisionCent; ebye.fReferenceMultiplicity = rlCollisionMult; + ebye.fNumContrib = rlCollisionNumContrib; if constexpr (rs == eRec || rs == eRecAndSim) { ev.fEventHistograms[eCent][eRec][0]->Fill(rlCollisionCent); @@ -429,19 +598,23 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam ev.fEventHistograms[eVertexX][eRec][0]->Fill(collision.posX()); ev.fEventHistograms[eVertexY][eRec][0]->Fill(collision.posY()); ev.fEventHistograms[eVertexZ][eRec][0]->Fill(collision.posZ()); + ev.fEventHistograms[eNumContrib][eRec][0]->Fill(rlCollisionNumContrib); - if (tc.fVertexZSwitch && EventCuts(collision)) { + if (ctEventCuts(collision)) { ev.fEventHistograms[eCent][eRec][1]->Fill(rlCollisionCent); ev.fEventHistograms[eMult][eRec][1]->Fill(rlCollisionMult); ev.fEventHistograms[eVertexX][eRec][1]->Fill(collision.posX()); ev.fEventHistograms[eVertexY][eRec][1]->Fill(collision.posY()); ev.fEventHistograms[eVertexZ][eRec][1]->Fill(collision.posZ()); + ev.fEventHistograms[eNumContrib][eRec][1]->Fill(rlCollisionNumContrib); } if constexpr (rs == eRecAndSim) { if (!collision.has_mcCollision()) { - LOGF(warning, " No MC collision for this collision, skip..."); + if (tc.fPrintSwitch) { + LOGF(warning, " No MC collision for this collision, skip..."); + } return; } @@ -456,12 +629,17 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam ebye.fCentralitySim = mcCollisionCent; ebye.fImpactParameter = b; + if (tc.fPrintSwitch) { + LOGF(info, "mc impact param (fm): %f", mccollision.impactParameter()); + LOGF(info, "mc centrality: %f", mcCollisionCent); + } + ev.fEventHistograms[eCent][eSim][0]->Fill(mcCollisionCent); ev.fEventHistograms[eVertexX][eSim][0]->Fill(mccollision.posX()); ev.fEventHistograms[eVertexY][eSim][0]->Fill(mccollision.posY()); ev.fEventHistograms[eVertexZ][eSim][0]->Fill(mccollision.posZ()); - if (tc.fVertexZSwitch && EventCuts(mccollision)) { + if (ctEventCuts(mccollision)) { ev.fEventHistograms[eCent][eSim][1]->Fill(mcCollisionCent); ev.fEventHistograms[eVertexX][eSim][1]->Fill(mccollision.posX()); ev.fEventHistograms[eVertexY][eSim][1]->Fill(mccollision.posY()); @@ -470,6 +648,11 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam if (qa.fQASwitch) { qa.fQAHistograms[eQACent][0]->Fill(rlCollisionCent, mcCollisionCent); + qa.fQAHistograms[eQAMultNumContrib][0]->Fill(rlCollisionMult, rlCollisionNumContrib); + if (ctEventCuts(collision) && ctEventCuts(mccollision)) { + qa.fQAHistograms[eQACent][1]->Fill(rlCollisionCent, mcCollisionCent); + qa.fQAHistograms[eQAMultNumContrib][1]->Fill(rlCollisionMult, rlCollisionNumContrib); + } } } } @@ -486,7 +669,7 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam pc.fParticleHistograms[ePt][eRec][0]->Fill(track.pt()); pc.fParticleHistograms[ePhi][eRec][0]->Fill(track.phi()); - if (tc.fPtSwitch && ParticleCuts(track)) { + if (ctParticleCuts(track)) { pc.fParticleHistograms[ePt][eRec][1]->Fill(track.pt()); pc.fParticleHistograms[ePhi][eRec][1]->Fill(track.phi()); } @@ -497,13 +680,15 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam // See https://aliceo2group.github.io/analysis-framework/docs/datamodel/ao2dTables.html#montecarlo if constexpr (rs == eRecAndSim) { if (!track.has_mcParticle()) { - LOGF(warning, " No MC particle for this track, skip..."); + if (tc.fPrintSwitch) { + LOGF(warning, " No MC particle for this track, skip..."); + } return; } auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle pc.fParticleHistograms[ePt][eSim][0]->Fill(mcparticle.pt()); pc.fParticleHistograms[ePhi][eSim][0]->Fill(mcparticle.phi()); - if (tc.fPtSwitch && ParticleCuts(mcparticle)) { + if (ctParticleCuts(mcparticle)) { pc.fParticleHistograms[ePt][eSim][1]->Fill(mcparticle.pt()); pc.fParticleHistograms[ePhi][eSim][1]->Fill(mcparticle.phi()); } @@ -518,8 +703,19 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam template void BookParticleHistograms(T1 const& lPcBins, ParticleHistograms& pc) { - - std::vector lPtBins = lPcBins[histType].value; // define local array and initialize it from an array set in the configurables + // *) structure: + // hists without cut + // - name + // - new hists + // └ rec + // └ sim + // hists with cut + // - name + // - new hists + // └ rec + // └ sim + + std::vector lPtBins = lPcBins[histType]; // define local array and initialize it from an array set in the configurables int nBinsPt = static_cast(lPtBins[0]); float minPt = lPtBins[1]; float maxPt = lPtBins[2]; @@ -529,58 +725,180 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam std::string nameRecNocutfull = particleHistNames[histType] + std::string(" distribution for reconstructed particles"); std::string nameSimNocutfull = particleHistNames[histType] + std::string(" distribution for simulated particles"); - pc.fParticleHistograms[histType][eRec][0] = new TH1F(nameRecNocut.c_str(), nameRecNocutfull.c_str(), nBinsPt, minPt, maxPt); - pc.fParticleHistograms[histType][eRec][0]->GetXaxis()->SetTitle(particleHistNames[histType]); - pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eRec][0]); - pc.fParticleHistograms[histType][eSim][0] = new TH1F(nameSimNocut.c_str(), nameSimNocutfull.c_str(), nBinsPt, minPt, maxPt); - pc.fParticleHistograms[histType][eSim][0]->GetXaxis()->SetTitle(particleHistNames[histType]); - pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eSim][0]); + if (doprocessRec || doprocessRecSim) { + pc.fParticleHistograms[histType][eRec][0] = new TH1F(nameRecNocut.c_str(), nameRecNocutfull.c_str(), nBinsPt, minPt, maxPt); + pc.fParticleHistograms[histType][eRec][0]->GetXaxis()->SetTitle(particleHistNames[histType]); + pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eRec][0]); + } + + if (doprocessSim || doprocessRecSim) { + pc.fParticleHistograms[histType][eSim][0] = new TH1F(nameSimNocut.c_str(), nameSimNocutfull.c_str(), nBinsPt, minPt, maxPt); + pc.fParticleHistograms[histType][eSim][0]->GetXaxis()->SetTitle(particleHistNames[histType]); + pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eSim][0]); + } std::string nameRecCut = std::string("fHist") + particleHistNames[histType] + std::string("[eRec][after cut]"); std::string nameSimCut = std::string("fHist") + particleHistNames[histType] + std::string("[eSim][after cut]"); std::string nameRecCutfull = particleHistNames[histType] + std::string(" distribution for reconstructed particles"); std::string nameSimCutfull = particleHistNames[histType] + std::string(" distribution for simulated particles"); - pc.fParticleHistograms[histType][eRec][1] = new TH1F(nameRecCut.c_str(), nameRecCutfull.c_str(), nBinsPt, minPt, maxPt); - pc.fParticleHistograms[histType][eRec][1]->GetXaxis()->SetTitle(particleHistNames[histType]); - pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eRec][1]); - pc.fParticleHistograms[histType][eSim][1] = new TH1F(nameSimCut.c_str(), nameSimCutfull.c_str(), nBinsPt, minPt, maxPt); - pc.fParticleHistograms[histType][eSim][1]->GetXaxis()->SetTitle(particleHistNames[histType]); - pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eSim][1]); + if (doprocessRec || doprocessRecSim) { + pc.fParticleHistograms[histType][eRec][1] = new TH1F(nameRecCut.c_str(), nameRecCutfull.c_str(), nBinsPt, minPt, maxPt); + pc.fParticleHistograms[histType][eRec][1]->GetXaxis()->SetTitle(particleHistNames[histType]); + pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eRec][1]); + } + + if (doprocessSim || doprocessRecSim) { + pc.fParticleHistograms[histType][eSim][1] = new TH1F(nameSimCut.c_str(), nameSimCutfull.c_str(), nBinsPt, minPt, maxPt); + pc.fParticleHistograms[histType][eSim][1]->GetXaxis()->SetTitle(particleHistNames[histType]); + pc.fParticleHistogramsList->Add(pc.fParticleHistograms[histType][eSim][1]); + } } template void BookEventHistograms(T1 const& lEvBins, EventHistograms& ev) { - - std::vector lCentBins = lEvBins[histType].value; // define local array and initialize it from an array set in the configurables + // *) structure: + // hists without cut + // - name + // └ centrality + estimator + // └ multiplicity + estimator + // └ others + // - new hists + // └ rec + // └ sim (without multiplicity and nContrib) + // hists with cut + // - name + // └ centrality + estimator + // └ multiplicity + estimator + // └ others + // - new hists + // └ rec + // └ sim (without multiplicity and nContrib) + + std::vector lCentBins = lEvBins[histType]; // define local array and initialize it from an array set in the configurables int nBinsCent = static_cast(lCentBins[0]); float minCent = lCentBins[1]; float maxCent = lCentBins[2]; std::string nameRecNocut = std::string("fHist") + eventHistNames[histType] + std::string("[eRec][before cut]"); std::string nameSimNocut = std::string("fHist") + eventHistNames[histType] + std::string("[eSim][before cut]"); - std::string nameRecNocutfull = eventHistNames[histType] + std::string(" distribution for reconstructed events"); - std::string nameSimNocutfull = eventHistNames[histType] + std::string(" distribution for simulated events"); + std::string nameRecNocutfull; + std::string nameSimNocutfull; + + if constexpr (histType == eCent) { + std::string nameRecNocutfull = tc.fCentEstm + eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimNocutfull = tc.fCentEstm + eventHistNames[histType] + std::string(" distribution for simulated events"); + } else if constexpr (histType == eMult) { + std::string nameRecNocutfull = tc.fMultEstm + eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimNocutfull = tc.fMultEstm + eventHistNames[histType] + std::string(" distribution for simulated events"); + } else { + std::string nameRecNocutfull = eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimNocutfull = eventHistNames[histType] + std::string(" distribution for simulated events"); + } + + if (doprocessRec || doprocessRecSim) { + ev.fEventHistograms[histType][eRec][0] = new TH1F(nameRecNocut.c_str(), nameRecNocutfull.c_str(), nBinsCent, minCent, maxCent); + ev.fEventHistograms[histType][eRec][0]->GetXaxis()->SetTitle(eventHistNames[histType]); + ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eRec][0]); + } - ev.fEventHistograms[histType][eRec][0] = new TH1F(nameRecNocut.c_str(), nameRecNocutfull.c_str(), nBinsCent, minCent, maxCent); - ev.fEventHistograms[histType][eRec][0]->GetXaxis()->SetTitle(eventHistNames[histType]); - ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eRec][0]); - ev.fEventHistograms[histType][eSim][0] = new TH1F(nameSimNocut.c_str(), nameSimNocutfull.c_str(), nBinsCent, minCent, maxCent); - ev.fEventHistograms[histType][eSim][0]->GetXaxis()->SetTitle(eventHistNames[histType]); - ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eSim][0]); + if (doprocessSim || doprocessRecSim) { + if constexpr (histType != eNumContrib && histType != eMult) { + ev.fEventHistograms[histType][eSim][0] = new TH1F(nameSimNocut.c_str(), nameSimNocutfull.c_str(), nBinsCent, minCent, maxCent); + ev.fEventHistograms[histType][eSim][0]->GetXaxis()->SetTitle(eventHistNames[histType]); + ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eSim][0]); + } // No nContrib and multiplicity for processSim + } std::string nameRecCut = std::string("fHist") + eventHistNames[histType] + std::string("[eRec][after cut]"); std::string nameSimCut = std::string("fHist") + eventHistNames[histType] + std::string("[eSim][after cut]"); - std::string nameRecCutfull = eventHistNames[histType] + std::string(" distribution for reconstructed events"); - std::string nameSimCutfull = eventHistNames[histType] + std::string(" distribution for simulated events"); - - ev.fEventHistograms[histType][eRec][1] = new TH1F(nameRecCut.c_str(), nameRecCutfull.c_str(), nBinsCent, minCent, maxCent); - ev.fEventHistograms[histType][eRec][1]->GetXaxis()->SetTitle(eventHistNames[histType]); - ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eRec][1]); - ev.fEventHistograms[histType][eSim][1] = new TH1F(nameSimCut.c_str(), nameSimCutfull.c_str(), nBinsCent, minCent, maxCent); - ev.fEventHistograms[histType][eSim][1]->GetXaxis()->SetTitle(eventHistNames[histType]); - ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eSim][1]); + std::string nameRecCutfull; + std::string nameSimCutfull; + + if constexpr (histType == eCent) { + std::string nameRecCutfull = tc.fCentEstm + eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimCutfull = tc.fCentEstm + eventHistNames[histType] + std::string(" distribution for simulated events"); + } else if constexpr (histType == eMult) { + std::string nameRecCutfull = tc.fMultEstm + eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimCutfull = tc.fMultEstm + eventHistNames[histType] + std::string(" distribution for simulated events"); + } else { + std::string nameRecCutfull = eventHistNames[histType] + std::string(" distribution for reconstructed events"); + std::string nameSimCutfull = eventHistNames[histType] + std::string(" distribution for simulated events"); + } + + if (doprocessRec || doprocessRecSim) { + ev.fEventHistograms[histType][eRec][1] = new TH1F(nameRecCut.c_str(), nameRecCutfull.c_str(), nBinsCent, minCent, maxCent); + ev.fEventHistograms[histType][eRec][1]->GetXaxis()->SetTitle(eventHistNames[histType]); + ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eRec][1]); + } + + if (doprocessSim || doprocessRecSim) { + if constexpr (histType != eNumContrib && histType != eMult) { + ev.fEventHistograms[histType][eSim][1] = new TH1F(nameSimCut.c_str(), nameSimCutfull.c_str(), nBinsCent, minCent, maxCent); + ev.fEventHistograms[histType][eSim][1]->GetXaxis()->SetTitle(eventHistNames[histType]); + ev.fEventHistogramsList->Add(ev.fEventHistograms[histType][eSim][1]); + } + } + } + + template + void BookQAHistograms(T1 const& lQABins, QAHistograms& qa) + { + // *) structure: + // hists without cut + // └ simulated centrality vs. reconstructed centrality + // └ nContrib vs. multiplicity + // └ others + // hists with cut + // └ simulated centrality vs. reconstructed centrality + // └ nContrib vs. multiplicity + // └ others + + std::vector lCentBins = lQABins[histType]; + int nBinsCent = static_cast(lCentBins[0]); + float minCent = lCentBins[1]; + float maxCent = lCentBins[2]; + + std::string nameNocut = std::string("fHist") + eventHistNames[histType] + std::string("[before cut]"); + std::string nameNocutfull; + if constexpr (histType == eCent) { + std::string nameNocutfull = std::string("Quality assurance of ") + tc.fCentEstm + eventHistNames[histType]; + } else if constexpr (histType == eNumContrib) { + std::string nameNocutfull = std::string("Quality assurance of ") + tc.fMultEstm + eventHistNames[histType] + std::string(" vs. NContributors"); + } else { + std::string nameNocutfull = std::string("Quality assurance of ") + eventHistNames[histType]; + } + + qa.fQAHistograms[histType][0] = new TH2F(nameNocut.c_str(), nameNocutfull.c_str(), nBinsCent, minCent, maxCent, nBinsCent, minCent, maxCent); + if constexpr (histType == eNumContrib) { + qa.fQAHistograms[histType][0]->GetYaxis()->SetTitle("NContributors"); + qa.fQAHistograms[histType][0]->GetXaxis()->SetTitle("Reference multiplicity"); + } else { + qa.fQAHistograms[histType][0]->GetYaxis()->SetTitle(Form("Simulated %s", eventHistNames[histType])); + qa.fQAHistograms[histType][0]->GetXaxis()->SetTitle(Form("Reconstructed %s", eventHistNames[histType])); + } + qa.fQAHistogramsList->Add(qa.fQAHistograms[histType][0]); + + std::string nameCut = std::string("fHist") + eventHistNames[histType] + std::string("[after cut]"); + std::string nameCutfull; + if constexpr (histType == eCent) { + std::string nameCutfull = std::string("Quality assurance of ") + tc.fCentEstm + eventHistNames[histType]; + } else if constexpr (histType == eNumContrib) { + std::string nameCutfull = std::string("Quality assurance of ") + tc.fMultEstm + eventHistNames[histType]; + } else { + std::string nameCutfull = std::string("Quality assurance of ") + eventHistNames[histType]; + } + + qa.fQAHistograms[histType][1] = new TH2F(nameCut.c_str(), nameCutfull.c_str(), nBinsCent, minCent, maxCent, nBinsCent, minCent, maxCent); + if constexpr (histType == eNumContrib) { + qa.fQAHistograms[histType][1]->GetYaxis()->SetTitle("NContributors"); + qa.fQAHistograms[histType][1]->GetXaxis()->SetTitle("Reference multiplicity"); + } else { + qa.fQAHistograms[histType][1]->GetYaxis()->SetTitle(Form("Simulated %s", eventHistNames[histType])); + qa.fQAHistograms[histType][1]->GetXaxis()->SetTitle(Form("Reconstructed %s", eventHistNames[histType])); + } + qa.fQAHistogramsList->Add(qa.fQAHistograms[histType][1]); } // *) Initialize and book all objects: @@ -598,10 +916,41 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam tc.fDryRun = cfDryRun; tc.fCentEstm = cfCentEstm; tc.fMultEstm = cfMultEstm; - tc.fVertexZ = cfVertexZ; - tc.fVertexZSwitch = cfVertexZSwitch; - tc.fPt = cfPt; - tc.fPtSwitch = cfPtSwitch; + + tc.fVertexZCutSwitch = cfVertexZCutSwitch; + tc.fSel8CutSwitch = cfSel8CutSwitch; + tc.fCentCutSwitch = cfCentCutSwitch; + tc.fNumContribCutSwitch = cfNumContribCutSwitch; + + tc.fPtCutSwitch = cfPtCutSwitch; + tc.fEtaCutSwitch = cfEtaCutSwitch; + tc.fSignCutSwitch = cfSignCutSwitch; + tc.fTpcNClsFoundCutSwitch = cfTpcNClsFoundCutSwitch; + tc.fDCAXYCutSwitch = cfDCAXYCutSwitch; + tc.fDCAZCutSwitch = cfDCAZCutSwitch; + + tc.fVertexZCut = cfVertexZCut; + tc.fCentCut = cfCentCut; + tc.fNumContribCut = cfNumContribCut; + + tc.fPtCut = cfPtCut; + tc.fEtaCut = cfEtaCut; + tc.fSignCut = cfSignCut; + tc.fTpcNClsFoundCut = cfTpcNClsFoundCut; + tc.fDCAXYCut = cfDCAXYCut; + tc.fDCAZCut = cfDCAZCut; + + tc.fPtBins = cfPtBins; + tc.fPhiBins = cfPhiBins; + + tc.fCentBins = cfCentBins; + tc.fMultBins = cfMultBins; + tc.fVerXBins = cfVerXBins; + tc.fVerYBins = cfVerYBins; + tc.fVerZBins = cfVerZBins; + tc.fNumContribBins = cfNumContribBins; + + tc.fPrintSwitch = cfPrintSwitch; tc.fFileWithWeights = cfFileWithWeights; tc.fRunNumber = cfRunNumber; @@ -634,8 +983,9 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam wt.fWeightHistogramsList->SetOwner(kTRUE); fBaseList->Add(wt.fWeightHistogramsList); - std::vector>> lPcBins = {cfPtBins, cfPhiBins}; - std::vector>> lEvBins = {cfCentBins, cfMultBins, cfVerXBins, cfVerYBins, cfVerZBins}; + std::vector> lPcBins = {tc.fPtBins, tc.fPhiBins}; + std::vector> lEvBins = {tc.fCentBins, tc.fMultBins, tc.fVerXBins, tc.fVerYBins, tc.fVerZBins, tc.fNumContribBins}; + std::vector> lQABins = {tc.fCentBins, tc.fMultBins, tc.fNumContribBins}; BookParticleHistograms(lPcBins, pc); BookParticleHistograms(lPcBins, pc); @@ -644,19 +994,15 @@ struct MultiparticleCumulants { // this name is used in lower-case format to nam BookEventHistograms(lEvBins, ev); BookEventHistograms(lEvBins, ev); BookEventHistograms(lEvBins, ev); - - std::vector lCentBins = cfCentBins.value; - int nBinsCent = static_cast(lCentBins[0]); - float minCent = lCentBins[1]; - float maxCent = lCentBins[2]; - qa.fQAHistograms[eQACent][0] = new TH2F("fHistQACen", "Quality assurance of centrality", nBinsCent, minCent, maxCent, nBinsCent, minCent, maxCent); - qa.fQAHistograms[eQACent][0]->GetYaxis()->SetTitle("Simulated centrality"); - qa.fQAHistograms[eQACent][0]->GetXaxis()->SetTitle("Reconstructed centrality"); - qa.fQAHistogramsList->Add(qa.fQAHistograms[eQACent][0]); - - wt.fWeightHistograms = getHistogramsWithWeights(tc.fFileWithWeights.c_str(), tc.fRunNumber.c_str()); - for (auto* hist : wt.fWeightHistograms) { - wt.fWeightHistogramsList->Add(hist); + BookEventHistograms(lEvBins, ev); + BookQAHistograms(lQABins, qa); + BookQAHistograms(lQABins, qa); + + if (wt.fWeightSwitch) { + wt.fWeightHistograms = getHistogramsWithWeights(tc.fFileWithWeights.c_str(), tc.fRunNumber.c_str()); + for (auto* hist : wt.fWeightHistograms) { + wt.fWeightHistogramsList->Add(hist); + } } } // end of void init(InitContext&) { From e708e98e160e5bfedc3783f12896a2fe78eabdf0 Mon Sep 17 00:00:00 2001 From: Jinhyun Park <125851562+jinhyunni@users.noreply.github.com> Date: Fri, 29 May 2026 17:06:42 +0900 Subject: [PATCH 326/449] [PWGHF] Fill in empty PDG value for KFParticle of V0 and CharmBaryon (#16439) Co-authored-by: Jinhyun Park --- PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx index 04dacbfc128..fff93b7f5fe 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx @@ -997,6 +997,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { kfV0 = kfV0MassConstrained; } kfV0.TransportToDecayVertex(); + kfV0.SetPDG(pdgIdOfV0); //~~~~~~~Construct cascade with KF~~~~~~~ const KFParticle* cascDaughters[2] = {&kfBach, &kfV0}; @@ -1023,6 +1024,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { if (kfCasc.GetNDF() <= 0 || kfCasc.GetChi2() <= 0) { continue; } + kfCasc.SetPDG(pdgIdOfCascade); // perform cascade building on casc_rej - only for Omega if constexpr (decayChannel != hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { @@ -1035,6 +1037,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { } kfCascRej.GetMass(massCascRej, sigMassCascRej); + kfCascRej.SetPDG(pdgIdOfCascade); } // Set mass constraint to cascade @@ -1073,6 +1076,7 @@ struct HfCandidateCreatorXic0Omegac0Qa { hCandCounter->Fill(VertexFit); hInvMassCharmBaryon->Fill(massCharmBaryon); } + kfCharmBaryon.SetPDG(pdgIdOfCharmBaryon); // Set production vertex // PV From c6e6b54a45b1c2bf8dd7bd9c5b1729ae4f72a305 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 29 May 2026 10:07:33 +0200 Subject: [PATCH 327/449] [PWGDQ] use momentum scaling method in reduced candidates table filling (#16445) --- PWGDQ/Tasks/qaMatching.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 4a8689fc0bc..d4259de78e3 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -2933,7 +2933,7 @@ struct QaMatching { //------------------------------- // Chi2-based matching from production - fillQaMatchingAodTablesForCollision(collision, muonTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); + fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); } else { @@ -2987,7 +2987,7 @@ struct QaMatching { double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; - fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); + fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); } else { @@ -3005,7 +3005,7 @@ struct QaMatching { double matchingScoreCut = matchingScoreCuts.at(label); matchingMethodCounter += 1; - fillQaMatchingAodTablesForCollision(collision, muonTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); + fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); } else { @@ -3018,9 +3018,10 @@ struct QaMatching { fillDimuonPlotsMc(collisionInfo, collisions, muonTracks, mftTracks); } - template + template void fillQaMatchingAodTablesForCollision(TCOLLISION const& collision, TMUON const& muonTracks, + TMFT const& mftTracks, const MatchingCandidates& matchingCandidates, int8_t matchLabel, int32_t reducedEventId, @@ -3044,7 +3045,9 @@ struct QaMatching { for (const auto& candidate : candidates) { const auto& candidateTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); - auto candidateTrackAtVertex = VarManager::PropagateMuon(candidateTrack, collision, VarManager::kToVertex); + const auto& mftTrack = mftTracks.rawIteratorAt(candidate.mftTrackId); + // propagate global forward track to vertex using momentum rescaling method + auto candidateTrackAtVertex = propagateToVertexMft(mftTrack, mchTrack, collision); qaMatchingCandidates( reducedEventId, reducedMchTrackId, From 5ea3fae9101fe178af34927b8ea841297b0e1b51 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 29 May 2026 10:17:21 +0200 Subject: [PATCH 328/449] [PWGDQ] Provide an upper limit for the size of the tables (#16356) --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 32 +++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 40450cdb4a8..985eab4bcc4 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1794,19 +1794,23 @@ struct AnalysisSameEventPairing { uint32_t dileptonMcDecision = static_cast(0); // placeholder, copy of the dqEfficiency.cxx one int sign1 = 0; int sign2 = 0; - dielectronList.reserve(1); - dimuonList.reserve(1); - dielectronsExtraList.reserve(1); - dielectronInfoList.reserve(1); - dimuonsExtraList.reserve(1); - dileptonInfoList.reserve(1); - dileptonFlowList.reserve(1); + // Reserve capacity for the output tables to avoid repeated reallocations + // inside the Arrow builders. Unused capacity is virtual address space + // only — pages are not faulted in until written. + auto nAssocs = assocs.size(); + dielectronList.reserve(nAssocs); + dimuonList.reserve(nAssocs); + dielectronsExtraList.reserve(nAssocs); + dielectronInfoList.reserve(nAssocs); + dimuonsExtraList.reserve(nAssocs); + dileptonInfoList.reserve(nAssocs); + dileptonFlowList.reserve(nAssocs); if (fConfigOptions.flatTables.value) { - dielectronAllList.reserve(1); - dimuonAllList.reserve(1); + dielectronAllList.reserve(nAssocs); + dimuonAllList.reserve(nAssocs); } if (fConfigOptions.polarTables.value) { - dileptonPolarList.reserve(1); + dileptonPolarList.reserve(nAssocs); } fAmbiguousPairs.clear(); constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); @@ -2388,7 +2392,7 @@ struct AnalysisSameEventPairing { const auto& histNames = fTrackMuonHistNames; int nPairCuts = (fPairCuts.size() > 0) ? fPairCuts.size() : 1; - electronmuonList.reserve(1); + electronmuonList.reserve(assocs1.size()); uint32_t twoTrackFilter = 0; int sign1 = 0; @@ -3085,7 +3089,7 @@ struct AnalysisAsymmetricPairing { // Template function to run same event pairing with asymmetric pairs (e.g. kaon-pion) template - void runAsymmetricPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& /*assocs*/, TTracks const& /*tracks*/) + void runAsymmetricPairing(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& /*tracks*/) { fPairCount.clear(); @@ -3098,8 +3102,8 @@ struct AnalysisAsymmetricPairing { int sign1 = 0; int sign2 = 0; - ditrackList.reserve(1); - ditrackExtraList.reserve(1); + ditrackList.reserve(assocs.size()); + ditrackExtraList.reserve(assocs.size()); constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::TrackCov) > 0 || (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelCov) > 0); From a20512e2c19a5270b734fcfe1d389f0d7e319bcc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 29 May 2026 10:30:52 +0200 Subject: [PATCH 329/449] [PWGDQ] Remove string creation from inner loop (#16384) --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 985eab4bcc4..ecd68a04327 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -2111,9 +2111,9 @@ struct AnalysisSameEventPairing { } } if constexpr (TPairType == VarManager::kDecayToEE) { - fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); if (isAmbiExtra) { - fHistMan->FillHistClass(Form("PairsBarrelSEPM_ambiguousextra_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); } } } else { @@ -2133,9 +2133,9 @@ struct AnalysisSameEventPairing { } } if constexpr (TPairType == VarManager::kDecayToEE) { - fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); if (isAmbiExtra) { - fHistMan->FillHistClass(Form("PairsBarrelSEPP_ambiguousextra_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][4].Data(), VarManager::fgValues); } } } else { @@ -2154,9 +2154,9 @@ struct AnalysisSameEventPairing { } } if constexpr (TPairType == VarManager::kDecayToEE) { - fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); if (isAmbiExtra) { - fHistMan->FillHistClass(Form("PairsBarrelSEMM_ambiguousextra_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); } } } From 4cbf839a207067c13455a73ec3e0e08771aa9ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 29 May 2026 10:34:28 +0200 Subject: [PATCH 330/449] [PWGDQ] Fix includes (#16411) --- PWGDQ/Core/MuonMatchingMlResponse.h | 9 +++++---- PWGDQ/Tasks/DalitzSelection.cxx | 2 ++ PWGDQ/Tasks/qaMatching.cxx | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Core/MuonMatchingMlResponse.h b/PWGDQ/Core/MuonMatchingMlResponse.h index 90e0da301e4..71a16ad9920 100644 --- a/PWGDQ/Core/MuonMatchingMlResponse.h +++ b/PWGDQ/Core/MuonMatchingMlResponse.h @@ -20,6 +20,8 @@ #include +#include +#include #include #include #include @@ -28,10 +30,9 @@ // Fill the map of available input features // the key is the feature's name (std::string) // the value is the corresponding value in EnumInputFeatures -#define FILL_MAP_MFTMUON_MATCH(FEATURE) \ - { \ - #FEATURE, static_cast(InputFeaturesMFTMuonMatch::FEATURE) \ - } +#define FILL_MAP_MFTMUON_MATCH(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesMFTMuonMatch::FEATURE)} // Check if the index of mCachedIndices (index associated to a FEATURE) // matches the entry in EnumInputFeatures associated to this FEATURE diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index 26162822fd7..e44e1cac782 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -24,10 +24,12 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include #include diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index d4259de78e3..2870357c5e4 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -58,10 +58,12 @@ #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include +#include #include #include #include #include +#include #include #include From aa7b3991854fa4df985de1d3d1ba749995fe2ca4 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 29 May 2026 10:54:22 +0200 Subject: [PATCH 331/449] [Common] add dipole shift correction to muon QA task (#16440) --- Common/Tasks/qaMuon.cxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index 370c61f7afe..dd1a9c6d76d 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -223,6 +223,7 @@ struct muonQa { Configurable fChamberResolutionX{"cfgChamberResolutionX", 0.4, "Chamber resolution along X configuration for refit"}; // 0.4cm pp, 0.2cm PbPb Configurable fChamberResolutionY{"cfgChamberResolutionY", 0.4, "Chamber resolution along Y configuration for refit"}; // 0.4cm pp, 0.2cm PbPb Configurable fSigmaCutImprove{"cfgSigmaCutImprove", 6., "Sigma cut for track improvement"}; + Configurable fDipoleZcorr{"cfgDipoleZcorr", 0.0f, "Correction to the dipole z position"}; } configRealign; /// Variables to event mixing criteria @@ -1651,6 +1652,11 @@ struct muonQa { fgValues.errorClusters.emplace_back(eCls); fgValues.DEIDs.emplace_back(cluster.deId()); + // subtract the dipole shift correction from the cluster z position + if (configRealign.fDipoleZcorr != 0) { + clusterMCH->z -= configRealign.fDipoleZcorr; + } + // Add transformed cluster into temporary variable convertedTrack.createParamAtCluster(*clusterMCH); } @@ -1663,6 +1669,12 @@ struct muonQa { LOGF(fatal, "Muon track %d has no associated clusters.", muon.globalIndex()); } + // add back the dipole shift correction to the track z + if (configRealign.fDipoleZcorr != 0) { + auto& trackParam = *(convertedTrack.begin()); + trackParam.setZ(trackParam.getZ() + configRealign.fDipoleZcorr); + } + for (auto it = convertedTrack.begin(); it != convertedTrack.end(); it++) { std::vector pos = {static_cast(it->getNonBendingCoor()), static_cast(it->getBendingCoor()), static_cast(it->getZ())}; fgValues.posClusters.emplace_back(pos); From f95b96197093a9fdf3f2f872edfa803e71611e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 29 May 2026 11:01:49 +0200 Subject: [PATCH 332/449] [PWGLF] Fix includes (#16415) --- PWGLF/DataModel/ZDCCalTables.h | 1 + .../Nuspex/coalescenceTreeProducer.cxx | 32 +++++++++------ .../Nuspex/deuteronInTriggeredEvents.cxx | 40 +++++++++++++------ PWGLF/TableProducer/QC/flowQC.cxx | 1 - .../Strangeness/sigmaHadCorr.cxx | 1 + .../GlobalEventProperties/ptmultCorr.cxx | 10 ----- .../Tasks/GlobalEventProperties/studyPnch.cxx | 3 +- PWGLF/Tasks/Nuspex/multiplicityPt.cxx | 1 + PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 1 - .../Strangeness/phiStrangeCorrelation.cxx | 2 +- .../Strangeness/strangenessInJetsIons.cxx | 1 + 11 files changed, 53 insertions(+), 40 deletions(-) diff --git a/PWGLF/DataModel/ZDCCalTables.h b/PWGLF/DataModel/ZDCCalTables.h index 097fb57e16c..0d11fe4b1ca 100644 --- a/PWGLF/DataModel/ZDCCalTables.h +++ b/PWGLF/DataModel/ZDCCalTables.h @@ -20,6 +20,7 @@ #include #include +#include namespace o2::aod { diff --git a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx index 18a3d6bdd64..e58a906a391 100644 --- a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx +++ b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx @@ -28,23 +28,31 @@ /// /// \author Alberto Calivà -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/Logger.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include // IWYU pragma: keep (do not replace with Math/Vector3Dfwd.h) +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include #include -#include #include +#include +#include #include using namespace o2; diff --git a/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx index 0f309b028d0..412fbb44adc 100644 --- a/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx +++ b/PWGLF/TableProducer/Nuspex/deuteronInTriggeredEvents.cxx @@ -35,48 +35,62 @@ #include "PWGJE/Core/JetUtilities.h" #include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/EventPlaneHelper.h" #include "Common/Core/PID/PIDTOF.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.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 +#include +#include +#include #include #include // for PDG codes #include #include -#include #include #include +#include #include +#include + +#include +#include #include +#include #include +#include +#include #include +#include #include #include diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index ec7e06c276f..8210ac95666 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -42,7 +42,6 @@ #include #include -#include #include #include #include diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index db2f50c8e29..dc7df2f567a 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx index 5cab01248e8..4e8abe41a4c 100644 --- a/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/ptmultCorr.cxx @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -38,23 +37,14 @@ #include #include -#include -#include -#include #include -#include -#include -#include #include -#include #include #include -#include #include #include #include -#include #include #include diff --git a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx index 8bf72d54a5a..20a27dce05a 100644 --- a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx @@ -15,8 +15,6 @@ /// \author Abhi Modak (abhi.modak@cern.ch), Lucas José (lucas.jose.franco.da.silva@cern.ch) /// \since September 10, 2025 -#include "PWGLF/DataModel/LFStrangenessTables.h" - #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" @@ -37,6 +35,7 @@ #include #include +#include #include #include diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx index 28531bd0446..70c1a2fd46b 100644 --- a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index cf85c93cc17..e0352773f6b 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -50,7 +50,6 @@ #include #include #include -#include #include diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 36726e80d5d..14c2b3c3ad4 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -39,9 +39,9 @@ #include #include -#include #include #include +#include #include #include diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index e39ceb4020b..b129823c74d 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include From a1da60836d4e8c3aa371c1ac248fa6e27d6d9c18 Mon Sep 17 00:00:00 2001 From: lcernusa Date: Fri, 29 May 2026 11:23:01 +0200 Subject: [PATCH 333/449] [PWGCF] MC truth-truth and truth-recon update (#16442) --- .../Tasks/flowDecorrelation.cxx | 82 +- .../Tasks/longRangeDihadronCor.cxx | 1156 +++++++++++++++-- 2 files changed, 1067 insertions(+), 171 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index 04b2a51a18a..d1ff0dc929a 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -1784,7 +1784,13 @@ struct FlowDecorrelation { } } - if (cfgSelCollByNch && (mcParticles.size() < cfgGeneralCuts.cfgCutMultMin || mcParticles.size() >= cfgGeneralCuts.cfgCutMultMax)) { + int tpcMult = 0; + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgSelCollByNch && (tpcMult < cfgGeneralCuts.cfgCutMultMin || tpcMult >= cfgGeneralCuts.cfgCutMultMax)) { return; } if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgGeneralCuts.cfgCutCentMin || cent >= cfgGeneralCuts.cfgCutCentMax)) { @@ -1794,7 +1800,7 @@ struct FlowDecorrelation { registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin if (!cfgCentTableUnavailable) registry.fill(HIST("MCTrue/MCCentrality"), cent); - registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); for (const auto& mcParticle : mcParticles) { if (mcParticle.isPhysicalPrimary()) { @@ -1804,12 +1810,12 @@ struct FlowDecorrelation { } } if (cfgMcTrue.cfgUseCFStepAll) { - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + same->fillEvent(tpcMult, CorrelationContainer::kCFStepAll); fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0C); } registry.fill(HIST("MCTrue/MCeventcount"), 2.5); - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + same->fillEvent(tpcMult, CorrelationContainer::kCFStepTrackedOnlyPrim); fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0C); } PROCESS_SWITCH(FlowDecorrelation, processMcSameTpcFt0c, "Process MC same event", false); @@ -1818,8 +1824,12 @@ struct FlowDecorrelation { { auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); - auto mult = associatedTracks.size(); - return mult; + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; }; using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; @@ -1831,22 +1841,20 @@ struct FlowDecorrelation { for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - if (cfgSelCollByNch && (tracks1.size() < cfgGeneralCuts.cfgCutMultMin || tracks1.size() >= cfgGeneralCuts.cfgCutMultMax)) - continue; - - if (cfgSelCollByNch && (tracks2.size() < cfgGeneralCuts.cfgCutMultMin || tracks2.size() >= cfgGeneralCuts.cfgCutMultMax)) - continue; - - auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); - - float cent = -1; + auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + auto groupedCollisions2 = collisions.sliceBy(collisionPerMCCollision, collision2.globalIndex()); + float cent1 = -1; + float cent2 = -1; if (!cfgCentTableUnavailable) { - for (const auto& collision : groupedCollisions) { - cent = getCentrality(collision); + for (const auto& collision : groupedCollisions1) { + cent1 = getCentrality(collision); + } + for (const auto& collision : groupedCollisions2) { + cent2 = getCentrality(collision); } } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgGeneralCuts.cfgCutCentMin || cent >= cfgGeneralCuts.cfgCutCentMax)) + if (!cfgSelCollByNch && !cfgCentTableUnavailable && ((cent1 < cfgGeneralCuts.cfgCutCentMin || cent1 >= cfgGeneralCuts.cfgCutCentMax) || (cent2 < cfgGeneralCuts.cfgCutCentMin || cent2 >= cfgGeneralCuts.cfgCutCentMax))) continue; registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin @@ -1874,7 +1882,13 @@ struct FlowDecorrelation { } } - if (cfgSelCollByNch && (mcParticles.size() < cfgGeneralCuts.cfgCutMultMin || mcParticles.size() >= cfgGeneralCuts.cfgCutMultMax)) { + int tpcMult = 0; + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgSelCollByNch && (tpcMult < cfgGeneralCuts.cfgCutMultMin || tpcMult >= cfgGeneralCuts.cfgCutMultMax)) { return; } if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgGeneralCuts.cfgCutCentMin || cent >= cfgGeneralCuts.cfgCutCentMax)) { @@ -1884,7 +1898,7 @@ struct FlowDecorrelation { registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin if (!cfgCentTableUnavailable) registry.fill(HIST("MCTrue/MCCentrality"), cent); - registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); for (const auto& mcParticle : mcParticles) { if (mcParticle.isPhysicalPrimary()) { @@ -1894,12 +1908,12 @@ struct FlowDecorrelation { } } if (cfgMcTrue.cfgUseCFStepAll) { - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + same->fillEvent(tpcMult, CorrelationContainer::kCFStepAll); fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0A); } registry.fill(HIST("MCTrue/MCeventcount"), 2.5); - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + same->fillEvent(tpcMult, CorrelationContainer::kCFStepTrackedOnlyPrim); fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0A); } PROCESS_SWITCH(FlowDecorrelation, processMcSameTpcFt0a, "Process MC same event", false); @@ -1908,8 +1922,12 @@ struct FlowDecorrelation { { auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); - auto mult = associatedTracks.size(); - return mult; + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; }; using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; @@ -1927,16 +1945,20 @@ struct FlowDecorrelation { if (cfgSelCollByNch && (tracks2.size() < cfgGeneralCuts.cfgCutMultMin || tracks2.size() >= cfgGeneralCuts.cfgCutMultMax)) continue; - auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); - - float cent = -1; + auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + auto groupedCollisions2 = collisions.sliceBy(collisionPerMCCollision, collision2.globalIndex()); + float cent1 = -1; + float cent2 = -1; if (!cfgCentTableUnavailable) { - for (const auto& collision : groupedCollisions) { - cent = getCentrality(collision); + for (const auto& collision : groupedCollisions1) { + cent1 = getCentrality(collision); + } + for (const auto& collision : groupedCollisions2) { + cent2 = getCentrality(collision); } } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgGeneralCuts.cfgCutCentMin || cent >= cfgGeneralCuts.cfgCutCentMax)) + if (!cfgSelCollByNch && !cfgCentTableUnavailable && ((cent1 < cfgGeneralCuts.cfgCutCentMin || cent1 >= cfgGeneralCuts.cfgCutCentMax) || (cent2 < cfgGeneralCuts.cfgCutCentMin || cent2 >= cfgGeneralCuts.cfgCutCentMax))) continue; registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx index e688c05684d..513ed42dbd8 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx @@ -84,45 +84,52 @@ static constexpr float LongArrayFloat[3][6] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3} struct LongRangeDihadronCor { Service ccdb; o2::aod::ITSResponse itsResponse; - - O2_DEFINE_CONFIGURABLE(cfgCutVtxZ, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta cut") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") - O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") - O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") - O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") - O2_DEFINE_CONFIGURABLE(cfgCutMultMin, int, 0, "Minimum multiplicity for collision") - O2_DEFINE_CONFIGURABLE(cfgCutMultMax, int, 10, "Maximum multiplicity for collision") - O2_DEFINE_CONFIGURABLE(cfgCutCentMin, float, 60.0f, "Minimum centrality for collision") - O2_DEFINE_CONFIGURABLE(cfgCutCentMax, float, 80.0f, "Maximum centrality for collision") - O2_DEFINE_CONFIGURABLE(cfgMixEventNumMin, int, 5, "Minimum number of events to mix") - O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") - O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") - O2_DEFINE_CONFIGURABLE(cfgCentTableUnavailable, bool, false, "if a dataset does not provide centrality information") - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoITSROFrameBorder, bool, false, "reject events at ITS ROF border") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoTimeFrameBorder, bool, false, "reject events at TF border") - O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference, use this cut at low multiplicities with caution") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") - O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") - O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, false, "cut time intervals with dead ITS staves (layers 0-3 only, for pp)") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") - O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") - O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") - O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") - O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") - O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") - O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") - O2_DEFINE_CONFIGURABLE(cfgDrawEtaPhiDis, bool, false, "draw eta-phi distribution for detectors in used") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgCutVtxZ, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") + O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 7.0f, "max DCA to vertex xy") + O2_DEFINE_CONFIGURABLE(cfgCutMultMin, int, 0, "Minimum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgCutMultMax, int, 10, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgCutCentMin, float, 60.0f, "Minimum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgCutCentMax, float, 80.0f, "Maximum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") + O2_DEFINE_CONFIGURABLE(cfgMixEventNumMin, int, 5, "Minimum number of events to mix") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgCentTableUnavailable, bool, false, "if a dataset does not provide centrality information") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoITSROFrameBorder, bool, false, "reject events at ITS ROF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoTimeFrameBorder, bool, false, "reject events at TF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference, use this cut at low multiplicities with caution") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, false, "cut time intervals with dead ITS staves (layers 0-3 only, for pp)") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgDrawEtaPhiDis, bool, false, "draw eta-phi distribution for detectors in used"); + O2_DEFINE_CONFIGURABLE(cfgEtaTpcCut, float, 0.8f, "Eta cut of TPC MC particles") + O2_DEFINE_CONFIGURABLE(cfgMinEtaFt0Cut, float, 0.0f, "Min eta cut of FT0 MC particles") + O2_DEFINE_CONFIGURABLE(cfgMaxEtaFt0Cut, float, 0.0f, "Max eta cut of FT0 MC particles") + O2_DEFINE_CONFIGURABLE(cfgUseFt0Structure, bool, true, "Use the true structure of FT0 in MC-true") + O2_DEFINE_CONFIGURABLE(cfgUseCFStepAll, bool, true, "Use CFStepAll in addition to primry"); + } cfgGeneral; struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -195,7 +202,7 @@ struct LongRangeDihadronCor { ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity / centrality axis for mixed event histograms"}; - ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; + ConfigurableAxis axisSample{"axisSample", {cfgGeneral.cfgSampleSize, 0, cfgGeneral.cfgSampleSize}, "sample axis for histograms"}; ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; @@ -209,11 +216,24 @@ struct LongRangeDihadronCor { AxisSpec axisFit{cfgaxisFITamp, "fit amplitude"}; AxisSpec axisChID = {220, 0, 220}; // make the filters and cuts. - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVtxZ); - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == static_cast(true))) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgGeneral.cfgCutVtxZ); + Filter trackFilter = (nabs(aod::track::eta) < cfgGeneral.cfgCutEta) && (aod::track::pt > cfgGeneral.cfgCutPtMin) && (aod::track::pt < cfgGeneral.cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == static_cast(true))) && (aod::track::tpcChi2NCl < cfgGeneral.cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgGeneral.cfgCutDCAz); using FilteredCollisions = soa::Filtered>; using FilteredTracks = soa::Filtered>; + Filter particleFilter = (nabs(aod::mcparticle::eta) < cfgGeneral.cfgEtaTpcCut || ((aod::mcparticle::eta > cfgGeneral.cfgMinEtaFt0Cut) && (aod::mcparticle::eta < cfgGeneral.cfgMaxEtaFt0Cut))) && (aod::mcparticle::pt > cfgGeneral.cfgCutPtMin) && (aod::mcparticle::pt < cfgGeneral.cfgCutPtMax); + using FilteredMcParticles = soa::Filtered; + + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgGeneral.cfgCutVtxZ; + using FilteredMcCollisions = soa::Filtered; + + using SmallGroupMcCollisions = soa::SmallGroups>; + + PresliceUnsorted collisionPerMCCollision = aod::mccollisionlabel::mcCollisionId; + Preslice perCollision = aod::track::collisionId; + Preslice perColMc = o2::aod::mcparticle::mcCollisionId; + // FT0 geometry o2::ft0::Geometry ft0Det; static constexpr uint64_t Ft0IndexA = 96; @@ -301,18 +321,39 @@ struct LongRangeDihadronCor { std::array tofNsigmaCut; std::array itsNsigmaCut; std::array tpcNsigmaCut; + + struct Ft0cCConstants { + double zFt0cDistance = -83.44; + double maxWidth = 12.; + double minWidthX = 18.25; + double minWidhtY = 18.175; + double insideWidthX = 6.825; + double insideWidthY = 6.675; + }; + struct Ft0aCConstants { + double zFt0aDistance = 338.43; + double offSetX = 0.588; + double offSetY = 1.468; + double blockFar = 14.875; + double blockClose = 2.65; + double rectOffSet = 1.325; + }; + Ft0cCConstants Ft0cLocations{}; + Ft0aCConstants Ft0aLocations{}; + int lastRunNumber = -1; std::vector runNumbers; std::map> histAmpCorrectPerRun; // map of TH3 histograms for all runs void init(InitContext&) { - if (cfgCentTableUnavailable && !cfgSelCollByNch) { + if (cfgGeneral.cfgCentTableUnavailable && !cfgGeneral.cfgSelCollByNch) { LOGF(fatal, "Centrality table is unavailable, cannot select collisions by centrality"); } const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; const AxisSpec axisEta{40, -1., 1., "#eta"}; const AxisSpec axisEtaFull{90, -4., 5., "#eta"}; + const AxisSpec axisCentrality{20, 0., 100., "cent"}; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -344,7 +385,7 @@ struct LongRangeDihadronCor { itsNsigmaCut[kProtonLow] = cfgPIDConfig.nSigmas->getData()[kITS][kProtonLow]; // Event Counter - if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) && cfgUseAdditionalEventCut) { + if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSemiMcSameTpcFt0c || doprocessSemiMcSameTpcFt0a) && cfgGeneral.cfgUseAdditionalEventCut) { registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); @@ -358,10 +399,33 @@ struct LongRangeDihadronCor { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "occupancy"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "MultCorrelation"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgGeneral.cfgEvSelV0AT0ACut"); + } + if (doprocessMcSameTpcFt0c || doprocessMcSameTpcFt0a || doprocessSemiMcSameTpcFt0c || doprocessSemiMcSameTpcFt0a) { + registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{5, 0, 5, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(2, "same all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(3, "same reco"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(4, "mixed all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(5, "mixed reco"); + registry.add("MCTrue/MCCentrality", "cent", {HistType::kTH1D, {axisCentrality}}); + registry.add("MCTrue/MCNch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("MCTrue/MCzVtx", "MCzVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("MCTrue/MCPhi", "MCPhi", {HistType::kTH1D, {axisPhi}}); + registry.add("MCTrue/MCEta", "MCEta", {HistType::kTH1D, {axisEtaFull}}); + registry.add("MCTrue/MCEtaTrueShape", "MCEta", {HistType::kTH1D, {axisEtaFull}}); + registry.add("MCTrue/MCpT", "MCpT", {HistType::kTH1D, {axisPtEfficiency}}); + registry.add("MCTrue/MCTrig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtEfficiency}}}); + if (doprocessMcSameTpcFt0c || doprocessSemiMcSameTpcFt0c) { + registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); + } + if (doprocessMcSameTpcFt0a || doprocessSemiMcSameTpcFt0a) { + registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution + registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); + } } - if (cfgEvSelMultCorrelation) { + if (cfgGeneral.cfgEvSelMultCorrelation) { cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; @@ -392,9 +456,9 @@ struct LongRangeDihadronCor { cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } - std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); + std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgGeneral.cfgCentEstimator); // Make histograms to check the distributions after cuts - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) { + if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSemiMcSameTpcFt0c || doprocessSemiMcSameTpcFt0a) { registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); @@ -409,18 +473,18 @@ struct LongRangeDihadronCor { registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); - if (cfgDrawEtaPhiDis) { + if (cfgGeneral.cfgDrawEtaPhiDis) { registry.add("EtaPhi", "", {HistType::kTH2F, {axisEtaFull, axisPhi}}); } } - if (doprocessSameTpcFt0a) { + if (doprocessSameTpcFt0a || doprocessSemiMcSameTpcFt0a) { registry.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); registry.add("Assoc_amp_same_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); registry.add("Assoc_amp_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } - if (doprocessSameTpcFt0c) { + if (doprocessSameTpcFt0c || doprocessSemiMcSameTpcFt0c) { registry.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); registry.add("Assoc_amp_same_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); @@ -461,11 +525,11 @@ struct LongRangeDihadronCor { {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaFt0aFt0c, "#Delta#eta"}}; - if (doprocessSameTpcFt0a) { + if (doprocessSameTpcFt0a || doprocessMcSameTpcFt0a || doprocessSemiMcSameTpcFt0a) { sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); mixedTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); } - if (doprocessSameTpcFt0c) { + if (doprocessSameTpcFt0c || doprocessMcSameTpcFt0c || doprocessSemiMcSameTpcFt0c) { sameTpcFt0c.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); mixedTpcFt0c.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); } @@ -474,7 +538,7 @@ struct LongRangeDihadronCor { mixedFt0aFt0c.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); } - if (cfgCumulantConfig.gfwOutput && doprocessSameTpcFt0a && doprocessSameTpcFt0c) { + if (cfgCumulantConfig.gfwOutput && (doprocessSameTpcFt0a && doprocessSameTpcFt0c)) { LOGF(fatal, "If you enable gfwOutput, you can only enable processSameTpcFt0a or processSameTpcFt0c, NOT both."); } if (cfgCumulantConfig.gfwOutput) { @@ -587,7 +651,7 @@ struct LongRangeDihadronCor { float getCentrality(TCollision const& collision) { float cent; - switch (cfgCentEstimator) { + switch (cfgGeneral.cfgCentEstimator) { case kCentFT0C: cent = collision.centFT0C(); break; @@ -609,7 +673,7 @@ struct LongRangeDihadronCor { template bool trackSelected(TTrack track) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgGeneral.cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgGeneral.cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgGeneral.cfgCutITSclu)); } template @@ -703,24 +767,24 @@ struct LongRangeDihadronCor { if (correctionsLoaded) { return; } - if (cfgEfficiency.value.empty() == false) { - if (cfgLocalEfficiency > 0) { - TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); + if (cfgGeneral.cfgEfficiency.value.empty() == false) { + if (cfgGeneral.cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgGeneral.cfgEfficiency.value.c_str(), "READ"); mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); } else { - mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + mEfficiency = ccdb->getForTimeStamp(cfgGeneral.cfgEfficiency, timestamp); } if (mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgGeneral.cfgEfficiency.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgGeneral.cfgEfficiency.value.c_str(), (void*)mEfficiency); } - if (cfgCentralityWeight.value.empty() == false) { - mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); + if (cfgGeneral.cfgCentralityWeight.value.empty() == false) { + mCentralityWeight = ccdb->getForTimeStamp(cfgGeneral.cfgCentralityWeight, timestamp); if (mCentralityWeight == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCentralityWeight.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgGeneral.cfgCentralityWeight.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgGeneral.cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); } if (cfgCumulantConfig.gfwOutput && cfgCumulantConfig.gfwAcceptance.value.empty() == false) { mAcceptance = ccdb->getForTimeStamp(cfgCumulantConfig.gfwAcceptance, timestamp); @@ -909,12 +973,12 @@ struct LongRangeDihadronCor { void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { if (system == SameEvent) { - if (!cfgCentTableUnavailable) + if (!cfgGeneral.cfgCentTableUnavailable) registry.fill(HIST("Centrality_used"), cent); registry.fill(HIST("Nch_used"), tracks1.size()); } - int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + int fSampleIndex = gRandom->Uniform(0, cfgGeneral.cfgSampleSize); float triggerWeight = 1.0f; // loop over all tracks @@ -932,7 +996,7 @@ struct LongRangeDihadronCor { } else if (corType == kFT0A) { registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); } - if (cfgDrawEtaPhiDis && corType == kFT0A) { + if (cfgGeneral.cfgDrawEtaPhiDis && corType == kFT0A) { registry.fill(HIST("EtaPhi"), track1.eta(), track1.phi(), eventWeight * triggerWeight); } } @@ -962,7 +1026,7 @@ struct LongRangeDihadronCor { auto phi = getPhiFT0(chanelid, corType); auto eta = getEtaFT0(chanelid, corType); - if (cfgDrawEtaPhiDis && system == SameEvent) { + if (cfgGeneral.cfgDrawEtaPhiDis && system == SameEvent) { registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); if (mirrorChannel) registry.fill(HIST("EtaPhi"), eta, 4 * PIHalf - phi, ampl * eventWeight); @@ -1006,7 +1070,7 @@ struct LongRangeDihadronCor { template void fillCorrelationsFT0AFT0C(TFT0s const& ft0Col1, TFT0s const& ft0Col2, float posZ, int system, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { - int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + int fSampleIndex = gRandom->Uniform(0, cfgGeneral.cfgSampleSize); float triggerWeight = 1.0f; std::size_t channelASize = ft0Col1.channelA().size(); @@ -1067,80 +1131,253 @@ struct LongRangeDihadronCor { } } + template + void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, float eventWeight, int corType) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + int fSampleIndex = gRandom->Uniform(0, cfgGeneral.cfgSampleSize); + double tpcEtaAcceptance = 0.8001; + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all FT0 tracks + for (auto const& track1 : tracks1) { + + if (corType == kFT0C && !cfgGeneral.cfgUseFt0Structure) { + if (std::abs(track1.eta()) < tpcEtaAcceptance) + continue; + } + if (corType == kFT0C && cfgGeneral.cfgUseFt0Structure && !ft0cCollisionCourse(track1.eta(), track1.phi(), posZ)) { + continue; + } + if (corType == kFT0A && !cfgGeneral.cfgUseFt0Structure) { + if (std::abs(track1.eta()) < tpcEtaAcceptance) + continue; + } + if (corType == kFT0A && cfgGeneral.cfgUseFt0Structure && !ft0aCollisionCourse(track1.eta(), track1.phi(), posZ)) { + continue; + } + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track1.isPhysicalPrimary()) + continue; + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && system == SameEvent) + registry.fill(HIST("MCTrue/MCEtaTrueShape"), track1.eta()); + + if (system == SameEvent && (doprocessMcSameTpcFt0c || doprocessMcSameTpcFt0a)) + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + + // loop over all TPC tracks + for (auto const& track2 : tracks2) { + + if (std::abs(track2.eta()) > tpcEtaAcceptance) + continue; + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track2.isPhysicalPrimary()) + continue; + + if (track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + + float deltaPhi = RecoDecay::constrainAngle(track2.phi() - track1.phi(), -PIHalf); + float deltaEta = track2.eta() - track1.eta(); + + // fill the right sparse and histograms + if (system == SameEvent) { + if (corType == kFT0C) { + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track2.pt(), track1.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + if (corType == kFT0A) { + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track2.pt(), track1.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0C) { + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track2.pt(), track1.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + if (corType == kFT0A) { + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track2.pt(), track1.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } + } + } + } + + template + void fillSemiMcCorrelations(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (system == SameEvent) { + if (!cfgGeneral.cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + } + + int fSampleIndex = gRandom->Uniform(0, cfgGeneral.cfgSampleSize); + double tpcEtaAcceptance = 0.8001; + + float triggerWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + + if (std::abs(track1.eta()) > tpcEtaAcceptance) + continue; + if (!track1.isPhysicalPrimary()) + continue; + + if (system == SameEvent) { + if (corType == kFT0C) { + registry.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + } else if (corType == kFT0A) { + registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + } + } + + std::size_t channelSize = 0; + if (corType == kFT0C) { + channelSize = ft0.channelC().size(); + } else if (corType == kFT0A) { + channelSize = ft0.channelA().size(); + } else { + LOGF(fatal, "Cor Index %d out of range", corType); + } + + if (channelSize == 0) + continue; + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int chanelid = 0; + float ampl = 0.; + getChannel(ft0, iCh, chanelid, ampl, corType, system); + if (corType == kFT0C) { + if ((cfgFwdConfig.cfgRejectFT0CInside && (chanelid >= kFT0CInnerRingMin && chanelid <= kFT0CInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0COutside && (chanelid >= kFT0COuterRingMin && chanelid <= kFT0COuterRingMax))) + continue; + } else if (corType == kFT0A) { + if ((cfgFwdConfig.cfgRejectFT0AInside && (chanelid >= kFT0AInnerRingMin && chanelid <= kFT0AInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0AOutside && (chanelid >= kFT0AOuterRingMin && chanelid <= kFT0AOuterRingMax))) + continue; + } + bool mirrorChannel = false; + if ((corType == kFT0A && cfgFwdConfig.cfgMirrorFT0ADeadChannels) || (corType == kFT0C && cfgFwdConfig.cfgMirrorFT0CDeadChannels)) + mirrorChannel = isMirrorId(chanelid, corType); + + auto phi = getPhiFT0(chanelid, corType); + auto eta = getEtaFT0(chanelid, corType); + if (cfgGeneral.cfgDrawEtaPhiDis && system == SameEvent) { + registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); + if (mirrorChannel) + registry.fill(HIST("EtaPhi"), eta, 4 * PIHalf - phi, ampl * eventWeight); + } + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); + float deltaEta = track1.eta() - eta; + // fill the right sparse and histograms + if (system == SameEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); + } else if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); + } else if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); + } + } + } + } + } + template bool eventSelected(TCollision collision, const int multTrk, const float centrality, const bool fillCounter) { registry.fill(HIST("hEventCountSpecific"), 0.5); - if (cfgEvSelkNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (cfgGeneral.cfgEvSelkNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof return 0; } - if (fillCounter && cfgEvSelkNoSameBunchPileup) + if (fillCounter && cfgGeneral.cfgEvSelkNoSameBunchPileup) registry.fill(HIST("hEventCountSpecific"), 1.5); - if (cfgEvSelkNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (cfgGeneral.cfgEvSelkNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { return 0; } - if (fillCounter && cfgEvSelkNoITSROFrameBorder) + if (fillCounter && cfgGeneral.cfgEvSelkNoITSROFrameBorder) registry.fill(HIST("hEventCountSpecific"), 2.5); - if (cfgEvSelkNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (cfgGeneral.cfgEvSelkNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { return 0; } - if (fillCounter && cfgEvSelkNoTimeFrameBorder) + if (fillCounter && cfgGeneral.cfgEvSelkNoTimeFrameBorder) registry.fill(HIST("hEventCountSpecific"), 3.5); - if (cfgEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (cfgGeneral.cfgEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference // use this cut at low multiplicities with caution return 0; } - if (fillCounter && cfgEvSelkIsGoodZvtxFT0vsPV) + if (fillCounter && cfgGeneral.cfgEvSelkIsGoodZvtxFT0vsPV) registry.fill(HIST("hEventCountSpecific"), 4.5); - if (cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (cfgGeneral.cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // no collisions in specified time range return 0; } - if (fillCounter && cfgEvSelkNoCollInTimeRangeStandard) + if (fillCounter && cfgGeneral.cfgEvSelkNoCollInTimeRangeStandard) registry.fill(HIST("hEventCountSpecific"), 5.5); - if (cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (cfgGeneral.cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { // from Jan 9 2025 AOT meeting // cut time intervals with dead ITS staves return 0; } - if (fillCounter && cfgEvSelkIsGoodITSLayersAll) + if (fillCounter && cfgGeneral.cfgEvSelkIsGoodITSLayersAll) registry.fill(HIST("hEventCountSpecific"), 6.5); - if (cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (cfgGeneral.cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { // for pp: cut time intervals with dead ITS staves on layers 0-3 only return 0; } - if (fillCounter && cfgEvSelkIsGoodITSLayer0123) + if (fillCounter && cfgGeneral.cfgEvSelkIsGoodITSLayer0123) registry.fill(HIST("hEventCountSpecific"), 7.5); - if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (cfgGeneral.cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold return 0; } - if (fillCounter && cfgEvSelkNoCollInRofStandard) + if (fillCounter && cfgGeneral.cfgEvSelkNoCollInRofStandard) registry.fill(HIST("hEventCountSpecific"), 8.5); - if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (cfgGeneral.cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold return 0; } - if (fillCounter && cfgEvSelkNoHighMultCollInPrevRof) + if (fillCounter && cfgGeneral.cfgEvSelkNoHighMultCollInPrevRof) registry.fill(HIST("hEventCountSpecific"), 9.5); auto occupancy = collision.trackOccupancyInTimeRange(); - if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) + if (cfgGeneral.cfgEvSelOccupancy && (occupancy < cfgGeneral.cfgCutOccupancyLow || occupancy > cfgGeneral.cfgCutOccupancyHigh)) return 0; - if (fillCounter && cfgEvSelOccupancy) + if (fillCounter && cfgGeneral.cfgEvSelOccupancy) registry.fill(HIST("hEventCountSpecific"), 10.5); auto multNTracksPV = collision.multNTracksPV(); - if (cfgEvSelMultCorrelation) { - if (cfgFuncParas.cfgMultPVT0CCutEnabled && !cfgCentTableUnavailable) { + if (cfgGeneral.cfgEvSelMultCorrelation) { + if (cfgFuncParas.cfgMultPVT0CCutEnabled && !cfgGeneral.cfgCentTableUnavailable) { if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(centrality)) return 0; if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(centrality)) return 0; } - if (cfgFuncParas.cfgMultT0CCutEnabled && !cfgCentTableUnavailable) { + if (cfgFuncParas.cfgMultT0CCutEnabled && !cfgGeneral.cfgCentTableUnavailable) { if (multTrk < cfgFuncParas.fMultT0CCutLow->Eval(centrality)) return 0; if (multTrk > cfgFuncParas.fMultT0CCutHigh->Eval(centrality)) @@ -1159,19 +1396,100 @@ struct LongRangeDihadronCor { return 0; } } - if (fillCounter && cfgEvSelMultCorrelation) + if (fillCounter && cfgGeneral.cfgEvSelMultCorrelation) registry.fill(HIST("hEventCountSpecific"), 11.5); // V0A T0A 5 sigma cut float sigma = 5.0; - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) + if (cfgGeneral.cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; - if (fillCounter && cfgEvSelV0AT0ACut) + if (fillCounter && cfgGeneral.cfgEvSelV0AT0ACut) registry.fill(HIST("hEventCountSpecific"), 12.5); return 1; } + bool ft0cCollisionCourse(float eta, float phi, float vtxZ) + { + double theta = 2 * std::atan(std::exp(-eta)); + double vx = std::sin(theta) * std::cos(phi); // veloctiy component along x + double vy = std::sin(theta) * std::sin(phi); // veloctiy component along y + double vz = std::cos(theta); // veloctiy component along z + + if (vz > 0.) + return false; + + double x = vx * ((Ft0cLocations.zFt0cDistance - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + double y = vy * ((Ft0cLocations.zFt0cDistance - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + + if (std::abs(x) < Ft0cLocations.maxWidth && (std::abs(y) > Ft0cLocations.insideWidthX && std::abs(y) < Ft0cLocations.minWidthX)) + return true; + if (std::abs(y) < Ft0cLocations.maxWidth && (std::abs(x) > Ft0cLocations.insideWidthY && std::abs(x) < Ft0cLocations.minWidhtY)) + return true; + return false; + } + + bool ft0aCollisionCourse(float eta, float phi, float vtxZ) + { + double theta = 2 * std::atan(std::exp(-eta)); + double vx = std::sin(theta) * std::cos(phi); // veloctiy component along x + double vy = std::sin(theta) * std::sin(phi); // veloctiy component along y + double vz = std::cos(theta); // veloctiy component along z + + if (vz < 0.) + return false; + + double x = vx * ((Ft0aLocations.zFt0aDistance - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + double y = vy * ((Ft0aLocations.zFt0aDistance - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + + if (x < (Ft0aLocations.blockFar + Ft0aLocations.offSetX) && x > (Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y < (Ft0aLocations.blockFar + Ft0aLocations.offSetY) && y > (Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + return true; + } + } + if (x < (Ft0aLocations.blockFar + Ft0aLocations.offSetX) && x > (Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y > (-Ft0aLocations.blockFar + Ft0aLocations.offSetY) && y < (-Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + return true; + } + } + + if (x > (-Ft0aLocations.blockFar + Ft0aLocations.offSetX) && x < (-Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y < (Ft0aLocations.blockFar + Ft0aLocations.offSetY) && y > (Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + return true; + } + } + if (x > (-Ft0aLocations.blockFar + Ft0aLocations.offSetX) && x < (-Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y > (-Ft0aLocations.blockFar + Ft0aLocations.offSetY) && y < (-Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + return true; + } + } + + if (x < (Ft0aLocations.blockClose + Ft0aLocations.offSetX) && x > (-Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y > (-Ft0aLocations.blockFar + Ft0aLocations.offSetY - Ft0aLocations.rectOffSet) && y < (-Ft0aLocations.blockClose + Ft0aLocations.offSetY - Ft0aLocations.rectOffSet)) { + return true; + } + } + + if (x < (Ft0aLocations.blockClose + Ft0aLocations.offSetX) && x > (-Ft0aLocations.blockClose + Ft0aLocations.offSetX)) { + if (y < (Ft0aLocations.blockFar + Ft0aLocations.offSetY + Ft0aLocations.rectOffSet) && y > (Ft0aLocations.blockClose + Ft0aLocations.offSetY + Ft0aLocations.rectOffSet)) { + return true; + } + } + + if (y < (Ft0aLocations.blockClose + Ft0aLocations.offSetY) && y > (-Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + if (x > (-Ft0aLocations.blockFar + Ft0aLocations.offSetX - Ft0aLocations.rectOffSet) && x < (-Ft0aLocations.blockClose + Ft0aLocations.offSetX - Ft0aLocations.rectOffSet)) { + return true; + } + } + + if (y < (Ft0aLocations.blockClose + Ft0aLocations.offSetY) && y > (-Ft0aLocations.blockClose + Ft0aLocations.offSetY)) { + if (x < (Ft0aLocations.blockFar + Ft0aLocations.offSetX + Ft0aLocations.rectOffSet) && x > (Ft0aLocations.blockClose + Ft0aLocations.offSetX + Ft0aLocations.rectOffSet)) { + return true; + } + } + return false; + } + void processSameTpcFt0a(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) { if (!collision.sel8()) @@ -1179,17 +1497,17 @@ struct LongRangeDihadronCor { auto bc = collision.bc_as(); float cent = -1.; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent = getCentrality(collision); } - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) return; if (!collision.has_foundFT0()) return; loadAlignParam(bc.timestamp()); loadGain(bc); loadCorrection(bc.timestamp()); - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent); registry.fill(HIST("Centrality"), cent); registry.fill(HIST("CentralityWeighted"), cent, weightCent); @@ -1231,10 +1549,10 @@ struct LongRangeDihadronCor { } } - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + if (cfgGeneral.cfgSelCollByNch && (tracks.size() < cfgGeneral.cfgCutMultMin || tracks.size() >= cfgGeneral.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { return; } @@ -1277,33 +1595,33 @@ struct LongRangeDihadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; if (!collision1.sel8() || !collision2.sel8()) continue; - if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) continue; - if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) continue; float cent1 = -1; float cent2 = -1; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); } - if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) continue; - if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax)) continue; if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) @@ -1314,11 +1632,11 @@ struct LongRangeDihadronCor { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - if (cfgUseEventWeights) { + if (cfgGeneral.cfgUseEventWeights) { eventWeight = 1.0f / it.currentWindowNeighbours(); } float weightCent = 1.0f; - if (!cfgCentTableUnavailable) + if (!cfgGeneral.cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); @@ -1333,17 +1651,17 @@ struct LongRangeDihadronCor { auto bc = collision.bc_as(); float cent = -1.; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent = getCentrality(collision); } - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) return; if (!collision.has_foundFT0()) return; loadAlignParam(bc.timestamp()); loadGain(bc); loadCorrection(bc.timestamp()); - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent); registry.fill(HIST("Centrality"), cent); registry.fill(HIST("CentralityWeighted"), cent, weightCent); @@ -1385,10 +1703,10 @@ struct LongRangeDihadronCor { } } - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + if (cfgGeneral.cfgSelCollByNch && (tracks.size() < cfgGeneral.cfgCutMultMin || tracks.size() >= cfgGeneral.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { return; } @@ -1431,33 +1749,33 @@ struct LongRangeDihadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; if (!collision1.sel8() || !collision2.sel8()) continue; - if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) continue; - if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) continue; float cent1 = -1; float cent2 = -1; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); } - if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) continue; - if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax)) continue; if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) @@ -1468,11 +1786,11 @@ struct LongRangeDihadronCor { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - if (cfgUseEventWeights) { + if (cfgGeneral.cfgUseEventWeights) { eventWeight = 1.0f / it.currentWindowNeighbours(); } float weightCent = 1.0f; - if (!cfgCentTableUnavailable) + if (!cfgGeneral.cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); @@ -1487,10 +1805,10 @@ struct LongRangeDihadronCor { auto bc = collision.bc_as(); float cent = -1.; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent = getCentrality(collision); } - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) return; if (!collision.has_foundFT0()) return; @@ -1499,10 +1817,10 @@ struct LongRangeDihadronCor { loadCorrection(bc.timestamp()); // should have the same event to TPC-FT0A/C correlations - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + if (cfgGeneral.cfgSelCollByNch && (tracks.size() < cfgGeneral.cfgCutMultMin || tracks.size() >= cfgGeneral.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { return; } @@ -1542,30 +1860,30 @@ struct LongRangeDihadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; // should have the same event to TPC-FT0A/C correlations if (!collision1.sel8() || !collision2.sel8()) continue; - if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) continue; - if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) continue; float cent1 = -1; float cent2 = -1; - if (!cfgCentTableUnavailable) { + if (!cfgGeneral.cfgCentTableUnavailable) { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); } - if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) continue; - if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax)) continue; - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax)) continue; if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) @@ -1575,11 +1893,11 @@ struct LongRangeDihadronCor { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - if (cfgUseEventWeights) { + if (cfgGeneral.cfgUseEventWeights) { eventWeight = 1.0f / it.currentWindowNeighbours(); } float weightCent = 1.0f; - if (!cfgCentTableUnavailable) + if (!cfgGeneral.cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0Col1 = collision1.foundFT0(); const auto& ft0Col2 = collision2.foundFT0(); @@ -1587,6 +1905,562 @@ struct LongRangeDihadronCor { } } PROCESS_SWITCH(LongRangeDihadronCor, processMixedFt0aFt0c, "Process mixed events for FT0A-FT0C correlation", false); + + void processMcSameTpcFt0c(FilteredMcCollisions::iterator const& mcCollision, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + float cent = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + } + + int tpcMult = 0; + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgCumulantConfig.gfwOutput) { + cfgCumulantConfig.fGFW->Clear(); + float lRandom = cfgCumulantConfig.fRndm->Rndm(); + float independent = cent; + if (cfgCumulantConfig.gfwUseNch) + independent = static_cast(tpcMult); + + // fill TPC Q-vector + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) > cfgGeneral.cfgEtaTpcCut) + continue; + if (!track.isPhysicalPrimary()) + continue; + if (std::abs(track.eta()) > cfgGeneral.cfgEtaTpcCut) + continue; + bool withinPtPOI = (0.2 < track.pt()) && (track.pt() < 10.0); // o2-linter: disable=magic-number (within POI pT range) + bool withinPtRef = (0.2 < track.pt()) && (track.pt() < 3.0); // o2-linter: disable=magic-number (within RF pT range) + if (withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 1); + if (withinPtPOI) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 2); + if (withinPtPOI && withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 4); + } + // fill FT0 Q-vector + for (const auto& tackFT : mcParticles) { + if (std::abs(tackFT.eta()) < cfgGeneral.cfgEtaTpcCut) + continue; + + if (cfgGeneral.cfgUseFt0Structure && !ft0cCollisionCourse(tackFT.eta(), tackFT.phi(), mcCollision.posZ())) { + continue; + } + if (!tackFT.isPhysicalPrimary()) + continue; + + cfgCumulantConfig.fGFW->Fill(tackFT.eta(), 1, tackFT.phi(), 1., 1); + } + + // Filling Flow Container + for (uint l_ind = 0; l_ind < cfgCumulantConfig.corrconfigs.size(); l_ind++) { + fillFC(cfgCumulantConfig.corrconfigs.at(l_ind), independent, lRandom); + } + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) { + return; + } + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgGeneral.cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + if (cfgGeneral.cfgUseCFStepAll) { + sameTpcFt0c->fillEvent(tpcMult, CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0C); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 2.5); + sameTpcFt0c->fillEvent(tpcMult, CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0C); + } + PROCESS_SWITCH(LongRangeDihadronCor, processMcSameTpcFt0c, "Process MC same event", false); + + void processMcSameTpcFt0a(FilteredMcCollisions::iterator const& mcCollision, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + float cent = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + } + + int tpcMult = 0; + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgCumulantConfig.gfwOutput) { + cfgCumulantConfig.fGFW->Clear(); + float lRandom = cfgCumulantConfig.fRndm->Rndm(); + float independent = cent; + if (cfgCumulantConfig.gfwUseNch) + independent = static_cast(tpcMult); + + // fill TPC Q-vector + for (const auto& track : mcParticles) { + if (std::abs(track.eta()) > cfgGeneral.cfgEtaTpcCut) + continue; + if (!track.isPhysicalPrimary()) + continue; + if (std::abs(track.eta()) > cfgGeneral.cfgEtaTpcCut) + continue; + bool withinPtPOI = (0.2 < track.pt()) && (track.pt() < 10.0); // o2-linter: disable=magic-number (within POI pT range) + bool withinPtRef = (0.2 < track.pt()) && (track.pt() < 3.0); // o2-linter: disable=magic-number (within RF pT range) + if (withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 1); + if (withinPtPOI) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 2); + if (withinPtPOI && withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), 1., 4); + } + // fill FT0 Q-vector + for (const auto& tackFT : mcParticles) { + if (std::abs(tackFT.eta()) < cfgGeneral.cfgEtaTpcCut) + continue; + + if (cfgGeneral.cfgUseFt0Structure && !ft0aCollisionCourse(tackFT.eta(), tackFT.phi(), mcCollision.posZ())) { + continue; + } + if (!tackFT.isPhysicalPrimary()) + continue; + + cfgCumulantConfig.fGFW->Fill(tackFT.eta(), 1, tackFT.phi(), 1., 1); + } + + // Filling Flow Container + for (uint l_ind = 0; l_ind < cfgCumulantConfig.corrconfigs.size(); l_ind++) { + fillFC(cfgCumulantConfig.corrconfigs.at(l_ind), independent, lRandom); + } + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) { + return; + } + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgGeneral.cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + if (cfgGeneral.cfgUseCFStepAll) { + sameTpcFt0a->fillEvent(tpcMult, CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0A); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 2.5); + sameTpcFt0a->fillEvent(tpcMult, CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f, kFT0A); + } + PROCESS_SWITCH(LongRangeDihadronCor, processMcSameTpcFt0a, "Process MC same event", false); + + void processMcMixedTpcFt0c(FilteredMcCollisions const& mcCollisions, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) + continue; + + if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) + continue; + + auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + auto groupedCollisions2 = collisions.sliceBy(collisionPerMCCollision, collision2.globalIndex()); + float cent1 = -1; + float cent2 = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + for (const auto& collision : groupedCollisions1) { + cent1 = getCentrality(collision); + } + for (const auto& collision : groupedCollisions2) { + cent2 = getCentrality(collision); + } + } + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && ((cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax) || (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax))) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgGeneral.cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + if (cfgGeneral.cfgUseCFStepAll) { + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight, kFT0C); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight, kFT0C); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processMcMixedTpcFt0c, "Process MC mixed events", false); + + void processMcMixedTpcFt0a(FilteredMcCollisions const& mcCollisions, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) + continue; + + if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) + continue; + + auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + auto groupedCollisions2 = collisions.sliceBy(collisionPerMCCollision, collision2.globalIndex()); + float cent1 = -1; + float cent2 = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + for (const auto& collision : groupedCollisions1) { + cent1 = getCentrality(collision); + } + for (const auto& collision : groupedCollisions2) { + cent2 = getCentrality(collision); + } + } + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && ((cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax) || (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax))) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgGeneral.cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + if (cfgGeneral.cfgUseCFStepAll) { + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight, kFT0A); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight, kFT0A); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processMcMixedTpcFt0a, "Process MC mixed events", false); + + void processSemiMcSameTpcFt0c(FilteredMcParticles const& mcParticles, FilteredCollisions const& collisions, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + auto tracks1 = mcParticles.sliceBy(perColMc, collision.globalIndex()); // TPC MC-truth + + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + + int tpcMult = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + float cent = -1.; + float weightCent = 1.0f; + if (!cfgGeneral.cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision, tpcMult, cent, true)) + return; + if (!collision.has_foundFT0()) + return; + + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + if (!cfgGeneral.cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tpcMult); + registry.fill(HIST("zVtx"), collision.posZ()); + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgGeneral.cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); + for (const auto& track1 : tracks1) { + if (track1.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), track1.phi()); + registry.fill(HIST("MCTrue/MCEta"), track1.eta()); + registry.fill(HIST("MCTrue/MCpT"), track1.pt()); + } + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) { + return; + } + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + sameTpcFt0c->fillEvent(tpcMult, CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillSemiMcCorrelations(tracks1, ft0, collision.posZ(), SameEvent, kFT0C, cent, weightCent); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processSemiMcSameTpcFt0c, "Process truth-TPC and recon-FT0C same events", false); + + void processSemiMcSameTpcFt0a(FilteredMcParticles const& mcParticles, FilteredCollisions const& collisions, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + auto tracks1 = mcParticles.sliceBy(perColMc, collision.globalIndex()); // TPC MC-truth + + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + + int tpcMult = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + float cent = -1.; + float weightCent = 1.0f; + if (!cfgGeneral.cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision, tpcMult, cent, true)) + return; + if (!collision.has_foundFT0()) + return; + + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + if (!cfgGeneral.cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tpcMult); + registry.fill(HIST("zVtx"), collision.posZ()); + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgGeneral.cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), tpcMult); + for (const auto& track1 : tracks1) { + if (track1.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), track1.phi()); + registry.fill(HIST("MCTrue/MCEta"), track1.eta()); + registry.fill(HIST("MCTrue/MCpT"), track1.pt()); + } + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) { + return; + } + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent < cfgGeneral.cfgCutCentMin || cent >= cfgGeneral.cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + sameTpcFt0a->fillEvent(tpcMult, CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillSemiMcCorrelations(tracks1, ft0, collision.posZ(), SameEvent, kFT0A, cent, weightCent); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processSemiMcSameTpcFt0a, "Process truth-TPC and recon-FT0A same events", false); + + void processSemiMcMixedTpcFt0c(FilteredMcParticles const& mcParticles, FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&mcParticles, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracksRecon1, collision2, tracksRecon2] = *it; + + auto tracksTruth1 = mcParticles.sliceBy(perColMc, collision1.globalIndex()); // TPC MC-truth + + if (!collision1.sel8() || !collision2.sel8()) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracksRecon1.size(), cent1, false)) + continue; + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracksRecon2.size(), cent2, false)) + continue; + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax)) + continue; + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; + + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgGeneral.cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + float weightCent = 1.0f; + if (!cfgGeneral.cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + const auto& ft0 = collision2.foundFT0(); + + fillSemiMcCorrelations(tracksTruth1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processSemiMcMixedTpcFt0c, "Process MC mixed events for TPC(truth)-FT0C(recon)", false); + + void processSemiMcMixedTpcFt0a(FilteredMcParticles const& mcParticles, FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&mcParticles, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); + int tpcMult = 0; + for (const auto& track : associatedTracks) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + return tpcMult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracksRecon1, collision2, tracksRecon2] = *it; + + auto tracksTruth1 = mcParticles.sliceBy(perColMc, collision1.globalIndex()); // TPC MC-truth + + if (!collision1.sel8() || !collision2.sel8()) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgGeneral.cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracksRecon1.size(), cent1, false)) + continue; + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracksRecon2.size(), cent2, false)) + continue; + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent1 < cfgGeneral.cfgCutCentMin || cent1 >= cfgGeneral.cfgCutCentMax)) + continue; + + if (!cfgGeneral.cfgSelCollByNch && !cfgGeneral.cfgCentTableUnavailable && (cent2 < cfgGeneral.cfgCutCentMin || cent2 >= cfgGeneral.cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; + + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgGeneral.cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + float weightCent = 1.0f; + if (!cfgGeneral.cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + const auto& ft0 = collision2.foundFT0(); + + fillSemiMcCorrelations(tracksTruth1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); + } + } + PROCESS_SWITCH(LongRangeDihadronCor, processSemiMcMixedTpcFt0a, "Process MC mixed events for TPC(truth)-FT0A(recon)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From bfa3f7951f3e246c1d87fd1b0a2b07960a805834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 29 May 2026 11:39:43 +0200 Subject: [PATCH 334/449] [ALICE3] Fix includes (#16407) --- ALICE3/Core/TrackUtilities.cxx | 2 ++ ALICE3/Core/TrackUtilities.h | 2 -- ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 6 +----- ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx | 1 - ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 4 ++-- ALICE3/Tasks/alice3DecayerQa.cxx | 2 ++ 6 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ALICE3/Core/TrackUtilities.cxx b/ALICE3/Core/TrackUtilities.cxx index 4239864e933..86b41e6245c 100644 --- a/ALICE3/Core/TrackUtilities.cxx +++ b/ALICE3/Core/TrackUtilities.cxx @@ -17,6 +17,8 @@ #include "TrackUtilities.h" +#include +#include #include #include diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index b80ea1b2341..0cdcc5da92b 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -24,9 +24,7 @@ #include -#include #include -#include #include namespace o2::upgrade diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index 4bf984db338..ae0d61bcd82 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -20,7 +20,6 @@ #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFMCParticle.h" -#include #include #include #include @@ -32,19 +31,16 @@ #include #include #include +#include #include #include -#include - #include #include #include #include #include -#include -#include #include #include diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index 99d9de97f22..59950f4a243 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index c7da0654e42..0ba1c3e57e0 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -23,11 +23,11 @@ /// \author Roberto Preghenella preghenella@bo.infn.it /// -#include "GeometryContainer.h" - #include "ALICE3/Core/DetLayer.h" #include "ALICE3/Core/FastTracker.h" #include "ALICE3/Core/FlatTrackSmearer.h" +#include "ALICE3/Core/GeometryContainer.h" +#include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/OTFMCParticle.h" diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index ff01b24a93b..5ae57d33f66 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -29,8 +29,10 @@ #include #include +#include #include +#include #include using namespace o2; From a2bcdcea4b5fe55eb7450d906ff828e77ee633a6 Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Fri, 29 May 2026 12:03:10 +0200 Subject: [PATCH 335/449] [PWGCF] FemtoUniverse: Add debug histogram with TPC momentum (#16436) --- ...versePairTaskTrackTrackSpherHarMultKtExtended.cxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index e69e4b68ca6..dcd67614798 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -166,6 +166,7 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { ConfigurableAxis confDeltaEtaAxis{"confDeltaEtaAxis", {100, -0.15, 0.15}, "DeltaEta"}; ConfigurableAxis confDeltaPhiStarAxis{"confDeltaPhiStarAxis", {100, -0.15, 0.15}, "DeltaPhiStar"}; + Configurable confIsDebug{"confIsDebug", true, "Fill additional histograms"}; } twotracksconfigs; using FemtoFullParticles = soa::Join; @@ -492,6 +493,11 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + if (twotracksconfigs.confIsDebug) { + qaRegistry.add("Tracks_one/hPtpcVsP", ";p GeV/c; (p_{TPC}-p)/p", kTH2F, {{800, 0, 4}, {400, -1, 1}}); + qaRegistry.add("Tracks_two/hPtpcVsP", ";p GeV/c; (p_{TPC}-p)/p", kTH2F, {{800, 0, 4}, {400, -1, 1}}); + } + mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); @@ -582,6 +588,9 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } trackHistoPartOne.fillQA(part); trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); + if (twotracksconfigs.confIsDebug) { + qaRegistry.fill(HIST("Tracks_one/hPtpcVsP"), part.p(), (part.tpcInnerParam() - part.p()) / part.p()); + } } } @@ -591,6 +600,9 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { continue; } trackHistoPartTwo.fillQA(part); + if (twotracksconfigs.confIsDebug) { + qaRegistry.fill(HIST("Tracks_two/hPtpcVsP"), part.p(), (part.tpcInnerParam() - part.p()) / part.p()); + } } } From e662b8b1439d0ee4f3d1735db416ee6c6d7fa4ea Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Fri, 29 May 2026 18:11:09 +0800 Subject: [PATCH 336/449] [PWGCF] jEPFlowAnalysis.cxx: fix bug for the ratio (#16446) --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index a0e47675ea2..983b3ef07bc 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -413,7 +413,7 @@ struct JEPFlowAnalysis { } } if (i == 0) { // second harmonic only - auto qOvecM = calcFT0CRawQVecMag(coll, i + 2); + auto qOvecM = calcFT0CRawQVecMag(coll, i + 2) / coll.qvecAmp()[detId]; epFlowHistograms.fill(HIST("hQoverM"), cent, highestPt, qOvecM); epFlowHistograms.fill(HIST("hQoverM2M"), cent, coll.qvecAmp()[detId], qOvecM); From 0195f3b812f2e41da06b7e1794e62e9877b6a81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 29 May 2026 12:55:45 +0200 Subject: [PATCH 337/449] [Common] Fix includes (#16408) --- Common/TableProducer/qVectorsTable.cxx | 1 - Common/Tasks/centralityQa.cxx | 2 ++ Common/Tasks/centralityStudypp.cxx | 3 +-- Common/Tasks/checkDataModelMC.cxx | 1 + Common/Tasks/qVectorsCorrection.cxx | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index ce5152aace6..ba8af37b094 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -45,7 +45,6 @@ #include #include -#include #include #include diff --git a/Common/Tasks/centralityQa.cxx b/Common/Tasks/centralityQa.cxx index ab7bd502377..2fc8ed715a3 100644 --- a/Common/Tasks/centralityQa.cxx +++ b/Common/Tasks/centralityQa.cxx @@ -22,6 +22,8 @@ #include #include +#include + using namespace o2; using namespace o2::framework; diff --git a/Common/Tasks/centralityStudypp.cxx b/Common/Tasks/centralityStudypp.cxx index a43f59e1973..47f1e540480 100644 --- a/Common/Tasks/centralityStudypp.cxx +++ b/Common/Tasks/centralityStudypp.cxx @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -331,7 +330,7 @@ struct centralityStudypp { float multNTracksPV = collision.multNTracksPV(); if (applyVertexZEqualization) { - float epsilon = 1e-2; // average value after which this collision will be disregarded + float epsilon = 1e-2; // average value after which this collision will be disregarded float maxVertexZ = 15.0f; // max value for any equalization attempt // same defaults as multCentTable in case of unhealthy signals diff --git a/Common/Tasks/checkDataModelMC.cxx b/Common/Tasks/checkDataModelMC.cxx index 343c577853d..799cf68a8e2 100644 --- a/Common/Tasks/checkDataModelMC.cxx +++ b/Common/Tasks/checkDataModelMC.cxx @@ -25,6 +25,7 @@ #include +#include #include #include diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx index b879cdaeb4c..e99017b1397 100644 --- a/Common/Tasks/qVectorsCorrection.cxx +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -39,6 +39,7 @@ #include +#include #include #include From 66cb166e5c98e79ed21f89bc27d017530c75fd79 Mon Sep 17 00:00:00 2001 From: GiuliaRusso02 Date: Fri, 29 May 2026 13:04:11 +0200 Subject: [PATCH 338/449] [PWGHF] Add centrality branch to Lc candidate tree (#16343) --- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 38 ++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 2ff5913aa99..6bf2d001097 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -262,7 +262,8 @@ DECLARE_SOA_TABLE(HfCandLcLites, "AOD", "HFCANDLCLITE", full::MassKPi, full::MlScoreFirstClass, full::MlScoreSecondClass, - full::MlScoreThirdClass); + full::MlScoreThirdClass, + full::CentFT0C); DECLARE_SOA_TABLE(HfCollIdLCLite, "AOD", "HFCOLLIDLCLITE", full::CollisionId); @@ -343,7 +344,8 @@ DECLARE_SOA_TABLE(HfCandLcFulls, "AOD", "HFCANDLCFULL", full::MassKPi, full::MlScoreFirstClass, full::MlScoreSecondClass, - full::MlScoreThirdClass); + full::MlScoreThirdClass, + full::CentFT0C); DECLARE_SOA_TABLE(HfCandLcFullEvs, "AOD", "HFCANDLCFULLEV", full::CollisionId, @@ -622,8 +624,8 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template - void fillLiteTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) + template + void fillLiteTable(CandType const& candidate, CollType const& collision, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMassesDCAFitter(candidate, candFlag); const float functionCt = HfHelper::ctLc(candidate); @@ -649,6 +651,11 @@ struct HfTreeCreatorLcToPKPi { assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); } + float centFT0C = -1.f; + if constexpr (UseCentrality) { + centFT0C = collision.centFT0C(); + } + rowCandidateLite( candidate.posX(), candidate.posY(), @@ -696,7 +703,8 @@ struct HfTreeCreatorLcToPKPi { functionInvMassKPi, mlScoreFirstClass, mlScoreSecondClass, - mlScoreThirdClass); + mlScoreThirdClass, + centFT0C); if (fillCollIdTable) { /// save also candidate collision indices @@ -708,8 +716,8 @@ struct HfTreeCreatorLcToPKPi { /// \param candidate candidate instance /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used - template - void fillFullTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) + template + void fillFullTable(CandType const& candidate, CollType const& collision, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMassesDCAFitter(candidate, candFlag); const float functionCt = HfHelper::ctLc(candidate); @@ -736,6 +744,11 @@ struct HfTreeCreatorLcToPKPi { assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); } + float centFT0C = -1.f; + if constexpr (UseCentrality) { + centFT0C = collision.centFT0C(); + } + rowCandidateFull( candidate.collisionId(), candidate.posX(), @@ -812,7 +825,8 @@ struct HfTreeCreatorLcToPKPi { functionInvMassKPi, mlScoreFirstClass, mlScoreSecondClass, - mlScoreThirdClass); + mlScoreThirdClass, + centFT0C); } /// \brief function to fill lite table @@ -960,9 +974,9 @@ struct HfTreeCreatorLcToPKPi { const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; if (passSelection && notSkippedBkg && (keepAll || (keepSignalMc && isMcCandidateSignal) || (keepBkgMc && !isMcCandidateSignal) || (keepCorrBkgMC && isCorrBkg))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, collision, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, collision, candidateMlScore, candFlag); } if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -1143,9 +1157,9 @@ struct HfTreeCreatorLcToPKPi { const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); if (functionSelection >= selectionFlagLc && (candidate.pt() > downSampleBkgPtMax || (pseudoRndm < downSampleBkgFactor && candidate.pt() < downSampleBkgPtMax))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candidateMlScore, candFlag); + fillLiteTable(candidate, collision, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candidateMlScore, candFlag); + fillFullTable(candidate, collision, candidateMlScore, candFlag); } if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { From ea6ba4c5b87cf99d20620c62327dfcc9a0582b3a Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 29 May 2026 13:36:08 +0200 Subject: [PATCH 339/449] [PWGDQ] extend matching features plots (#16447) --- PWGDQ/Tasks/qaMatching.cxx | 119 ++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 2870357c5e4..44e003bfa85 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -681,27 +681,30 @@ struct QaMatching { MatchFeaturesHistos(std::string path, HistogramRegistry* registry, int numCandidates) { - AxisSpec indexAxis = {numCandidates + 1, 0, static_cast(numCandidates + 1), "ranking index"}; + AxisSpec indexAxis = {numCandidates, 0, static_cast(numCandidates), "ranking index"}; AxisSpec scoreAxis = {100, 0, 1, "match score"}; int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; - AxisSpec dxAxis = {100, -10, 10, "#Deltax (cm)"}; - AxisSpec dyAxis = {100, -10, 10, "#Deltay (cm)"}; - AxisSpec dpAxis = {100, -10, 10, "#Deltap (GeV/c)"}; - AxisSpec dptAxis = {100, -1, 1, "#Deltap_{T} (GeV/c)"}; - AxisSpec dphiAxis = {100, -1, 1, "#Delta#phi (rad)"}; - AxisSpec dtanlAxis = {100, -10, 10, "#Deltatanl"}; - AxisSpec detaAxis = {100, -1, 1, "#Delta#eta"}; + AxisSpec taggedAxis = {2, 0, 2.0, "is tagged"}; + AxisSpec scoreGapAxis = {100, 0, 1.0, "match score gap"}; + AxisSpec logpAxis = {16, -1, 3, "log_{10}(p)"}; + AxisSpec dxAxis = {100, -20, 20, "#Deltax (cm)"}; + AxisSpec dyAxis = {100, -20, 20, "#Deltay (cm)"}; + AxisSpec dpAxis = {100, -50, 50, "#Deltap (GeV/c)"}; + AxisSpec dptAxis = {100, -5, 5, "#Deltap_{T} (GeV/c)"}; + AxisSpec dphiAxis = {100, -2, 2, "#Delta#phi (rad)"}; + AxisSpec dtanlAxis = {100, -20, 20, "#Deltatanl"}; + AxisSpec detaAxis = {100, -2, 2, "#Delta#eta"}; AxisSpec rabsAxis = {100, 0, 100, "R_{abs}"}; - hDeltaP = registry->add((path + "/deltaP").c_str(), "MFT-MCH #Deltap", {HistType::kTHnSparseF, {dpAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaPt = registry->add((path + "/deltaPt").c_str(), "MFT-MCH #Deltap_{T}", {HistType::kTHnSparseF, {dptAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaX = registry->add((path + "/deltaX").c_str(), "MFT-MCH #Deltax", {HistType::kTHnSparseF, {dxAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaY = registry->add((path + "/deltaY").c_str(), "MFT-MCH #Deltay", {HistType::kTHnSparseF, {dyAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaPhi = registry->add((path + "/deltaPhi").c_str(), "MFT-MCH #Delta#phi", {HistType::kTHnSparseF, {dphiAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaTanl = registry->add((path + "/deltaTanl").c_str(), "MFT-MCH #DeltaTanl", {HistType::kTHnSparseF, {dtanlAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hDeltaEta = registry->add((path + "/deltaEta").c_str(), "MFT-MCH #Delta#eta", {HistType::kTHnSparseF, {detaAxis, scoreAxis, indexAxis, matchTypeAxis}}); - hRabs = registry->add((path + "/Rabs").c_str(), "MFT-MCH R_{abs}", {HistType::kTHnSparseF, {rabsAxis, scoreAxis, indexAxis, matchTypeAxis}}); + hDeltaP = registry->add((path + "/deltaP").c_str(), "MFT-MCH #Deltap", {HistType::kTHnSparseF, {dpAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaPt = registry->add((path + "/deltaPt").c_str(), "MFT-MCH #Deltap_{T}", {HistType::kTHnSparseF, {dptAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaX = registry->add((path + "/deltaX").c_str(), "MFT-MCH #Deltax", {HistType::kTHnSparseF, {dxAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaY = registry->add((path + "/deltaY").c_str(), "MFT-MCH #Deltay", {HistType::kTHnSparseF, {dyAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaPhi = registry->add((path + "/deltaPhi").c_str(), "MFT-MCH #Delta#phi", {HistType::kTHnSparseF, {dphiAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaTanl = registry->add((path + "/deltaTanl").c_str(), "MFT-MCH #DeltaTanl", {HistType::kTHnSparseF, {dtanlAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hDeltaEta = registry->add((path + "/deltaEta").c_str(), "MFT-MCH #Delta#eta", {HistType::kTHnSparseF, {detaAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); + hRabs = registry->add((path + "/Rabs").c_str(), "MFT-MCH R_{abs}", {HistType::kTHnSparseF, {rabsAxis, logpAxis, scoreAxis, scoreGapAxis, indexAxis, matchTypeAxis, taggedAxis}}); } }; @@ -2152,6 +2155,7 @@ struct QaMatching { template void fillMatchingPlots(C const& collision, TMUON const& muonTracks, + const std::vector& taggedMuons, const MatchingCandidates& matchingCandidates, MatchingPlotter* plotter) { @@ -2168,6 +2172,22 @@ struct QaMatching { if (!isGoodGlobalMuon(mchTrack, collision)) continue; + double logp = std::log10(mchTrack.p()); + + int isTagged = 0; + if (std::find(taggedMuons.begin(), taggedMuons.end(), mchIndex) != taggedMuons.end()) { + isTagged = 1; + } + + float scoreGap = 0; + if (globalTracksVector.size() > 1) { + // we have at least two candidates, so we can check the score difference + // between the leading and the sub-leading + auto leadingScore = globalTracksVector[0].matchScore; + auto subleadingScore = globalTracksVector[1].matchScore; + scoreGap = leadingScore - subleadingScore; + } + for (const auto& candidate : globalTracksVector) { double dp = candidate.mchTrackProp.getP() - candidate.mftTrackProp.getP(); double dpt = candidate.mchTrackProp.getPt() - candidate.mftTrackProp.getPt(); @@ -2177,14 +2197,15 @@ struct QaMatching { double dtanl = candidate.mchTrackProp.getTanl() - candidate.mftTrackProp.getTanl(); double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); int matchType = static_cast(candidate.matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), candidate.matchScore, candidate.matchRanking, matchType); + int ranking = candidate.matchRanking - 1; + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); } } @@ -2215,6 +2236,7 @@ struct QaMatching { const CollisionInfo& collisionInfo, TMUON const& muonTracks, TMFT const& mftTracks, + const std::vector& taggedMuons, const MatchingCandidates& matchingCandidates, const MatchingCandidates& matchingCandidatesProd, const std::vector>& matchablePairs, @@ -2315,6 +2337,22 @@ struct QaMatching { } if (isGoodMCH) { + double logp = std::log10(mchTrack.p()); + + int isTagged = 0; + if (std::find(taggedMuons.begin(), taggedMuons.end(), mchIndex) != taggedMuons.end()) { + isTagged = 1; + } + + float scoreGap = 0; + if (globalTracksVector.size()) { + // we have a matchable pair with at least two candidates, so we can check the score difference + // between the leading and the sub-leading + auto leadingScore = globalTracksVector[0].matchScore; + auto subleadingScore = globalTracksVector[1].matchScore; + scoreGap = leadingScore - subleadingScore; + } + for (const auto& candidate : globalTracksVector) { double dp = candidate.mchTrackProp.getP() - candidate.mftTrackProp.getP(); double dpt = candidate.mchTrackProp.getPt() - candidate.mftTrackProp.getPt(); @@ -2324,14 +2362,15 @@ struct QaMatching { double dtanl = candidate.mchTrackProp.getTanl() - candidate.mftTrackProp.getTanl(); double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); int matchType = static_cast(candidate.matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, candidate.matchScore, candidate.matchRanking, matchType); - std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), candidate.matchScore, candidate.matchRanking, matchType); + int ranking = candidate.matchRanking - 1; + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); } } @@ -2937,9 +2976,9 @@ struct QaMatching { // Chi2-based matching from production fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, collisionInfo.matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMuons, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); } else { - fillMatchingPlots(collision, muonTracks, collisionInfo.matchingCandidates, fChi2MatchingPlotter.get()); + fillMatchingPlots(collision, muonTracks, taggedMuons, collisionInfo.matchingCandidates, fChi2MatchingPlotter.get()); } //------------------------------- @@ -2974,9 +3013,9 @@ struct QaMatching { } } if constexpr (isMC) { - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fTaggedMuonsMatchingPlotter.get()); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMuons, taggedMatchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, cfgMatchingChi2ScoreMftMchLow, fTaggedMuonsMatchingPlotter.get()); } else { - fillMatchingPlots(collision, muonTracks, taggedMatchingCandidates, fTaggedMuonsMatchingPlotter.get()); + fillMatchingPlots(collision, muonTracks, taggedMuons, taggedMatchingCandidates, fTaggedMuonsMatchingPlotter.get()); } //------------------------------- @@ -2991,9 +3030,9 @@ struct QaMatching { matchingMethodCounter += 1; fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMuons, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter, false); } else { - fillMatchingPlots(collision, muonTracks, matchingCandidates, plotter); + fillMatchingPlots(collision, muonTracks, taggedMuons, matchingCandidates, plotter); } } @@ -3009,9 +3048,9 @@ struct QaMatching { matchingMethodCounter += 1; fillQaMatchingAodTablesForCollision(collision, muonTracks, mftTracks, matchingCandidates, matchingMethodCounter, collisionInfo.reducedEventId, collisionInfo.reducedMchTrackIds); if constexpr (isMC) { - fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); + fillMatchingPlotsMc(collision, collisionInfo, muonTracks, mftTracks, taggedMuons, matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, matchingScoreCut, plotter); } else { - fillMatchingPlots(collision, muonTracks, matchingCandidates, plotter); + fillMatchingPlots(collision, muonTracks, taggedMuons, matchingCandidates, plotter); } } From 4cf8591723bde0155ec6e80094eebf2d36f451a7 Mon Sep 17 00:00:00 2001 From: Uliana Dmitrieva Date: Fri, 29 May 2026 14:12:04 +0200 Subject: [PATCH 340/449] [Common] Rename event selection bits (#16423) --- .../TableProducer/zdcExtraTableProducer.cxx | 100 ++++++++++-------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/Common/TableProducer/zdcExtraTableProducer.cxx b/Common/TableProducer/zdcExtraTableProducer.cxx index 58098f02576..f0a5cc9080e 100644 --- a/Common/TableProducer/zdcExtraTableProducer.cxx +++ b/Common/TableProducer/zdcExtraTableProducer.cxx @@ -73,16 +73,16 @@ struct ZdcExtraTableProducer { Configurable cfgSaveQaHistos{"cfgSaveQaHistos", false, "Flag to save QA histograms"}; enum SelectionCriteria { - evSel_zvtx, - evSel_sel8, - evSel_occupancy, - evSel_kNoSameBunchPileup, - evSel_kIsGoodZvtxFT0vsPV, - evSel_kNoCollInTimeRangeStandard, - evSel_kIsVertexITSTPC, - evSel_kIsGoodITSLayersAll, - evSel_allEvents, - nEventSelections + ZVtxCut, + Sel8, + OccupancyCut, + NoSameBunchPileup, + IsGoodZvtxFT0vsPV, + NoCollInTimeRangeStandard, + IsVertexITSTPC, + IsGoodITSLayersAll, + AllEvents, + NEventSelections }; HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -90,16 +90,16 @@ struct ZdcExtraTableProducer { void init(InitContext const&) { - registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_allEvents + 1, "All events"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_zvtx + 1, "vtxZ"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoSameBunchPileup + 1, "kNoSameBunchPileup"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsVertexITSTPC + 1, "kIsVertexITSTPC"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{NEventSelections, 0, NEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(AllEvents + 1, "AllEvents"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(ZVtxCut + 1, "ZVtxCut"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(Sel8 + 1, "Sel8"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(OccupancyCut + 1, "OccupancyCut"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(NoSameBunchPileup + 1, "NoSameBunchPileup"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(IsGoodZvtxFT0vsPV + 1, "IsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(NoCollInTimeRangeStandard + 1, "NoCollInTimeRangeStandard"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(IsVertexITSTPC + 1, "IsVertexITSTPC"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(IsGoodITSLayersAll + 1, "IsGoodITSLayersAll"); // Skip histogram registration if QA flag is false if (!cfgSaveQaHistos) { @@ -129,55 +129,55 @@ struct ZdcExtraTableProducer { uint8_t selectionBits = 0; bool selected; - registry.fill(HIST("hEventCount"), evSel_allEvents); + registry.fill(HIST("hEventCount"), AllEvents); selected = std::fabs(collision.posZ()) < cfgEvSelVtxZ; if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_zvtx); - registry.fill(HIST("hEventCount"), evSel_zvtx); + SETBIT(selectionBits, ZVtxCut); + registry.fill(HIST("hEventCount"), ZVtxCut); } selected = collision.sel8(); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_sel8); - registry.fill(HIST("hEventCount"), evSel_sel8); + SETBIT(selectionBits, Sel8); + registry.fill(HIST("hEventCount"), Sel8); } auto occupancy = collision.trackOccupancyInTimeRange(); selected = occupancy <= cfgEvSelsMaxOccupancy; if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_occupancy); - registry.fill(HIST("hEventCount"), evSel_occupancy); + SETBIT(selectionBits, OccupancyCut); + registry.fill(HIST("hEventCount"), OccupancyCut); } selected = collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_kNoSameBunchPileup); - registry.fill(HIST("hEventCount"), evSel_kNoSameBunchPileup); + SETBIT(selectionBits, NoSameBunchPileup); + registry.fill(HIST("hEventCount"), NoSameBunchPileup); } selected = collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodZvtxFT0vsPV); - registry.fill(HIST("hEventCount"), evSel_kIsGoodZvtxFT0vsPV); + SETBIT(selectionBits, IsGoodZvtxFT0vsPV); + registry.fill(HIST("hEventCount"), IsGoodZvtxFT0vsPV); } selected = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_kNoCollInTimeRangeStandard); - registry.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeStandard); + SETBIT(selectionBits, NoCollInTimeRangeStandard); + registry.fill(HIST("hEventCount"), NoCollInTimeRangeStandard); } selected = collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_kIsVertexITSTPC); - registry.fill(HIST("hEventCount"), evSel_kIsVertexITSTPC); + SETBIT(selectionBits, IsVertexITSTPC); + registry.fill(HIST("hEventCount"), IsVertexITSTPC); } selected = collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); if (selected) { - selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodITSLayersAll); - registry.fill(HIST("hEventCount"), evSel_kIsGoodITSLayersAll); + SETBIT(selectionBits, IsGoodITSLayersAll); + registry.fill(HIST("hEventCount"), IsGoodITSLayersAll); } return selectionBits; @@ -185,6 +185,7 @@ struct ZdcExtraTableProducer { void process(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) { + // collision-based event selection constexpr int NTowers = 4; // number of ZDC towers @@ -195,23 +196,30 @@ struct ZdcExtraTableProducer { uint8_t evSelection = eventSelected(collision); - // add event selection - if (cfgEvSelSel8 && !(evSelection & (1 << evSel_sel8))) + if (cfgEvSelSel8 && !TESTBIT(evSelection, Sel8)) { continue; - if (!(evSelection & (1 << evSel_zvtx))) + } + if (!TESTBIT(evSelection, ZVtxCut)) { continue; - if (cfgEvSelsDoOccupancySel && !(evSelection & (1 << evSel_occupancy))) + } + if (cfgEvSelsDoOccupancySel && !TESTBIT(evSelection, OccupancyCut)) { continue; - if (cfgEvSelsNoSameBunchPileupCut && !(evSelection & (1 << evSel_kNoSameBunchPileup))) + } + if (cfgEvSelsNoSameBunchPileupCut && !TESTBIT(evSelection, NoSameBunchPileup)) { continue; - if (cfgEvSelsIsGoodZvtxFT0vsPV && !(evSelection & (1 << evSel_kIsGoodZvtxFT0vsPV))) + } + if (cfgEvSelsIsGoodZvtxFT0vsPV && !TESTBIT(evSelection, IsGoodZvtxFT0vsPV)) { continue; - if (cfgEvSelsNoCollInTimeRangeStandard && !(evSelection & (1 << evSel_kNoCollInTimeRangeStandard))) + } + if (cfgEvSelsNoCollInTimeRangeStandard && !TESTBIT(evSelection, NoCollInTimeRangeStandard)) { continue; - if (cfgEvSelsIsVertexITSTPC && !(evSelection & (1 << evSel_kIsVertexITSTPC))) + } + if (cfgEvSelsIsVertexITSTPC && !TESTBIT(evSelection, IsVertexITSTPC)) { continue; - if (cfgEvSelsIsGoodITSLayersAll && !(evSelection & (1 << evSel_kIsGoodITSLayersAll))) + } + if (cfgEvSelsIsGoodITSLayersAll && !TESTBIT(evSelection, IsGoodITSLayersAll)) { continue; + } float centrality = collision.centFT0C(); From 7030bae82723aaca1ba39e970c25d1785ec53269 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 29 May 2026 14:40:15 +0200 Subject: [PATCH 341/449] [PWGEM/Dilepton] add a task for SCT (#16449) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/Dilepton.h | 91 +++++++++++++++++------ PWGEM/Dilepton/DataModel/dileptonTables.h | 4 +- PWGEM/Dilepton/Tasks/CMakeLists.txt | 5 ++ PWGEM/Dilepton/Tasks/dielectron.cxx | 2 +- PWGEM/Dilepton/Tasks/dielectronSCT.cxx | 29 ++++++++ PWGEM/Dilepton/Tasks/dimuon.cxx | 2 +- PWGEM/Dilepton/Utils/ElectronModule.h | 9 ++- PWGEM/Dilepton/Utils/MlResponseSCT.h | 4 + 8 files changed, 116 insertions(+), 30 deletions(-) create mode 100644 PWGEM/Dilepton/Tasks/dielectronSCT.cxx diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 5bce11ac26f..e5aa7fbfe02 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -94,6 +94,11 @@ using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; +using MyElectronsSCT = o2::soa::Join; +using MyElectronSCT = MyElectronsSCT::iterator; +using FilteredMyElectronsSCT = o2::soa::Filtered; +using FilteredMyElectronSCT = FilteredMyElectronsSCT::iterator; + using MyMuons = o2::soa::Join; using MyMuon = MyMuons::iterator; using FilteredMyMuons = o2::soa::Filtered; @@ -102,7 +107,7 @@ using FilteredMyMuon = FilteredMyMuons::iterator; using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMFwdTrack>; -template +template struct Dilepton { // Configurables @@ -257,15 +262,20 @@ struct Dilepton { o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; // configuration for PID ML - o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; - o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - o2::framework::Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; - o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + // o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + // o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMLPID{"binsMLPID", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMLPID{"cutsMLPID", std::vector{0.97, 0.97, 0.97, 0.8, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + // o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + // o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + // o2::framework::Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + // o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + o2::framework::Configurable> binsMLSCT{"binsMLSCT", std::vector{0.1, 0.4, 0.6, 0.8, 1, 2, 4, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMLSCTeT_prompt_hc{"cutsMLSCTeT_prompt_hc", std::vector{0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8}, "ML cuts per bin for prompt hc"}; + o2::framework::Configurable> cutsMLSCTeT_nonprompt_hc{"cutsMLSCTeT_nonprompt_hc", std::vector{0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8}, "ML cuts per bin for nonprompt hc"}; + o2::framework::Configurable> cutsMLSCTeT_hb{"cutsMLSCTeT_hb", std::vector{0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8}, "ML cuts per bin for hb"}; } dielectroncuts; DimuonCut fDimuonCut; @@ -328,8 +338,8 @@ struct Dilepton { o2::aod::rctsel::RCTFlagsChecker rctChecker; // o2::ccdb::CcdbApi ccdbApi; o2::framework::Service ccdb; - int mRunNumber; - float d_bz; + int mRunNumber{0}; + float d_bz{0}; o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; // static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; @@ -793,14 +803,14 @@ struct Dilepton { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut std::vector binsML{}; - binsML.reserve(dielectroncuts.binsMl.value.size()); - for (size_t i = 0; i < dielectroncuts.binsMl.value.size(); i++) { - binsML.emplace_back(dielectroncuts.binsMl.value[i]); + binsML.reserve(dielectroncuts.binsMLPID.value.size()); + for (size_t i = 0; i < dielectroncuts.binsMLPID.value.size(); i++) { + binsML.emplace_back(dielectroncuts.binsMLPID.value[i]); } std::vector thresholdsML{}; - thresholdsML.reserve(dielectroncuts.cutsMl.value.size()); - for (size_t i = 0; i < dielectroncuts.cutsMl.value.size(); i++) { - thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); + thresholdsML.reserve(dielectroncuts.cutsMLPID.value.size()); + for (size_t i = 0; i < dielectroncuts.cutsMLPID.value.size(); i++) { + thresholdsML.emplace_back(dielectroncuts.cutsMLPID.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); } // end of PID ML @@ -837,6 +847,26 @@ struct Dilepton { fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } + template + bool foundHFSV(TTrack const& track) + { + int ptbin = lower_bound(dielectroncuts.binsMLSCT.value.begin(), dielectroncuts.binsMLSCT.value.end(), track.pt()) - dielectroncuts.binsMLSCT.value.begin() - 1; + if (ptbin < 0) { + ptbin = 0; + } else if (static_cast(dielectroncuts.binsMLSCT.value.size()) - 2 < ptbin) { + ptbin = static_cast(dielectroncuts.binsMLSCT.value.size()) - 2; + } + + for (int i = 0; i < static_cast(track.nSV()); i++) { + auto probaSCT = track.probaSCT(i); + // LOGF(info, "track.globalIndex() = %d, pt = %f, i = %d, probaSCT[0] = %f, probaSCT[1] = %f, probaSCT[2] = %f, probaSCT[3] = %f", track.globalIndex(), track.pt(), i, probaSCT[0], probaSCT[1], probaSCT[2], probaSCT[3]); + if (probaSCT[1] > dielectroncuts.cutsMLSCTeT_prompt_hc.value[ptbin] || probaSCT[2] > dielectroncuts.cutsMLSCTeT_nonprompt_hc.value[ptbin] || probaSCT[3] > dielectroncuts.cutsMLSCTeT_hb.value[ptbin]) { + return true; + } + } + return false; + } + template bool isGoodQvector(TQvectors const& qvectors) { @@ -889,6 +919,11 @@ struct Dilepton { return false; } } + if constexpr (withSCT) { + if (foundHFSV(t1) || foundHFSV(t2)) { + return false; + } + } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; @@ -1244,7 +1279,8 @@ struct Dilepton { using FilteredMyCollisions = o2::soa::Filtered; o2::framework::SliceCache cache; - o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + // o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; o2::framework::expressions::Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); @@ -1266,10 +1302,14 @@ struct Dilepton { ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), o2::aod::emprimaryelectron::pfb >= static_cast(0)); - o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); - o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + // o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + // o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + using TElectronType = std::tuple_element_t<0, std::tuple>; + o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); - o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + // o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track; o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), @@ -1545,6 +1585,13 @@ struct Dilepton { return false; } } + + if constexpr (withSCT) { + if (foundHFSV(t1) || foundHFSV(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { if (!cut.IsSelectedTrack(t1) || !cut.IsSelectedTrack(t2)) { return false; diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index a3a7d52b4e2..27d06147986 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -697,7 +697,7 @@ DECLARE_SOA_COLUMN(BDTScoreNonpromptHcUINT8, bdtScoreNonpromptHcUINT8, std::vect DECLARE_SOA_COLUMN(BDTScoreHbUINT8, bdtScoreHbUINT8, std::vector); //! scaling factor is 255. DECLARE_SOA_COLUMN(HadronType, hadronType, std::vector); //! 0:track, 1:K0S, 2:Lambda, 3:AntiLambda, 4:XiMinus, 5:XiPlus, 6:OmegaMinus, 7:OmegaPlus -DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](std::vector p0, std::vector p1, std::vector p2, std::vector p3, std::vector type, int index) -> std::array { +DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](gsl::span p0, gsl::span p1, gsl::span p2, gsl::span p3, gsl::span type, const int index) -> std::array { return std::array{ std::nextafter(p0[index] / 255.f, std::numeric_limits::infinity()), std::nextafter(p1[index] / 255.f, std::numeric_limits::infinity()), @@ -705,7 +705,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](std::vector p0, std:: std::nextafter(p3[index] / 255.f, std::numeric_limits::infinity()), static_cast(type[index])}; }); -DECLARE_SOA_DYNAMIC_COLUMN(NSV, nSV, [](std::vector type) -> size_t { return type.size(); }); +DECLARE_SOA_DYNAMIC_COLUMN(NSV, nSV, [](gsl::span type) -> size_t { return type.size(); }); DECLARE_SOA_COLUMN(ITSNSigmaEl, itsNSigmaEl, float); //! DECLARE_SOA_COLUMN(ITSNSigmaMu, itsNSigmaMu, float); //! diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index 473e24c969d..c872babef87 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -90,6 +90,11 @@ o2physics_add_dpl_workflow(dielectron-mc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(dielectron-sct + SOURCES dielectronSCT.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(dimuon SOURCES dimuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils diff --git a/PWGEM/Dilepton/Tasks/dielectron.cxx b/PWGEM/Dilepton/Tasks/dielectron.cxx index 042831bff30..27f5d13802e 100644 --- a/PWGEM/Dilepton/Tasks/dielectron.cxx +++ b/PWGEM/Dilepton/Tasks/dielectron.cxx @@ -25,5 +25,5 @@ using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"dielectron"})}; + adaptAnalysisTask>(cfgc, TaskName{"dielectron"})}; } diff --git a/PWGEM/Dilepton/Tasks/dielectronSCT.cxx b/PWGEM/Dilepton/Tasks/dielectronSCT.cxx new file mode 100644 index 00000000000..646069802b5 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dielectronSCT.cxx @@ -0,0 +1,29 @@ +// 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. +// +// ======================== +// +// This code is for dielectron analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/Dilepton.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dielectron-sct"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dimuon.cxx b/PWGEM/Dilepton/Tasks/dimuon.cxx index be0a7d8386b..a964f00a1c8 100644 --- a/PWGEM/Dilepton/Tasks/dimuon.cxx +++ b/PWGEM/Dilepton/Tasks/dimuon.cxx @@ -25,5 +25,5 @@ using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"dimuon"})}; + adaptAnalysisTask>(cfgc, TaskName{"dimuon"})}; } diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index c2d7d343c75..99a40c8d28b 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -278,7 +278,7 @@ struct cfgDFeT : o2::framework::ConfigurableGroup { o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -295,7 +295,7 @@ struct cfgDFeV0 : o2::framework::ConfigurableGroup { o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -312,7 +312,7 @@ struct cfgDFeC : o2::framework::ConfigurableGroup { o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "impPar3DinSigma", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -1665,7 +1665,7 @@ class ElectronModule registry.fill(HIST("SCT/eT/hMass"), eTpair.mass); if (eTpair.isOK && fConfigDFeT.useML) { o2::analysis::pwgem::dilepton::sct::candidate candidate; - fillCandidate(candidate, eTpair, trackParCov, mDcaInfoCov); + fillCandidate(candidate, eTpair, hadronParCov, mDcaInfoCov); candidate.ptL = trackParCov.getPt(); candidate.signLH = electron.sign() * hadron.sign(); candidate.signedMassLH = electron.sign() * hadron.sign() * eTpair.mass; @@ -2167,6 +2167,7 @@ class ElectronModule candidate.impPar3DHinSigma = dca3DinSigmaOTF(candidate.impParXYH, candidate.impParZH, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY()); candidate.signLH = 0; candidate.dcaLH = pair.dca2legs; + candidate.logChi2PCA = std::log10(std::pow(pair.dca2legs, 2)); candidate.massLH = pair.mass; candidate.signedMassLH = pair.mass; candidate.cpa = pair.cospa; diff --git a/PWGEM/Dilepton/Utils/MlResponseSCT.h b/PWGEM/Dilepton/Utils/MlResponseSCT.h index 8a00659ecc0..c55e10da8c4 100644 --- a/PWGEM/Dilepton/Utils/MlResponseSCT.h +++ b/PWGEM/Dilepton/Utils/MlResponseSCT.h @@ -63,6 +63,7 @@ enum class InputFeaturesSCT : uint8_t { impPar3DHinSigma, signLH, dcaLH, + logChi2PCA, massLH, signedMassLH, missingPtNuPerpToFD, @@ -109,6 +110,7 @@ struct candidate { // LH pair information int signLH{0}; float dcaLH{0}; + float logChi2PCA{0}; float massLH{0}; float signedMassLH{0}; float missingPtNuPerpToFD{0}; @@ -162,6 +164,7 @@ class MlResponseSCT : public MlResponse CHECK_AND_FILL_TRACK(impPar3DHinSigma); CHECK_AND_FILL_TRACK(signLH); CHECK_AND_FILL_TRACK(dcaLH); + CHECK_AND_FILL_TRACK(logChi2PCA); CHECK_AND_FILL_TRACK(massLH); CHECK_AND_FILL_TRACK(signedMassLH); CHECK_AND_FILL_TRACK(missingPtNuPerpToFD); @@ -240,6 +243,7 @@ class MlResponseSCT : public MlResponse FILL_MAP_TRACK(impPar3DHinSigma), FILL_MAP_TRACK(signLH), FILL_MAP_TRACK(dcaLH), + FILL_MAP_TRACK(logChi2PCA), FILL_MAP_TRACK(massLH), FILL_MAP_TRACK(signedMassLH), FILL_MAP_TRACK(missingPtNuPerpToFD), From c1823649fd7b4d6eefedf537b0483747245bb220 Mon Sep 17 00:00:00 2001 From: lcernusa Date: Fri, 29 May 2026 16:23:35 +0200 Subject: [PATCH 342/449] [PWGCF] Bug-fix MC truth-truth and recon-truth (#16452) --- .../Tasks/flowDecorrelation.cxx | 32 +++++++++++- .../Tasks/longRangeDihadronCor.cxx | 50 +++++++++++++++++-- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index d1ff0dc929a..0e55c1fa1d9 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -1841,6 +1841,23 @@ struct FlowDecorrelation { for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; + int tpcMult1 = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult1 += 1; + } + int tpcMult2 = 0; + for (const auto& track : tracks2) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult2 += 1; + } + + if (cfgSelCollByNch && (tpcMult1 < cfgGeneralCuts.cfgCutMultMin || tpcMult1 >= cfgGeneralCuts.cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tpcMult2 < cfgGeneralCuts.cfgCutMultMin || tpcMult2 >= cfgGeneralCuts.cfgCutMultMax)) + continue; + auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); auto groupedCollisions2 = collisions.sliceBy(collisionPerMCCollision, collision2.globalIndex()); float cent1 = -1; @@ -1939,10 +1956,21 @@ struct FlowDecorrelation { for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - if (cfgSelCollByNch && (tracks1.size() < cfgGeneralCuts.cfgCutMultMin || tracks1.size() >= cfgGeneralCuts.cfgCutMultMax)) + int tpcMult1 = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult1 += 1; + } + int tpcMult2 = 0; + for (const auto& track : tracks2) { + if (std::abs(track.eta()) < cfgMcTrue.cfgEtaTpcCut) + tpcMult2 += 1; + } + + if (cfgSelCollByNch && (tpcMult1 < cfgGeneralCuts.cfgCutMultMin || tpcMult1 >= cfgGeneralCuts.cfgCutMultMax)) continue; - if (cfgSelCollByNch && (tracks2.size() < cfgGeneralCuts.cfgCutMultMin || tracks2.size() >= cfgGeneralCuts.cfgCutMultMax)) + if (cfgSelCollByNch && (tpcMult2 < cfgGeneralCuts.cfgCutMultMin || tpcMult2 >= cfgGeneralCuts.cfgCutMultMax)) continue; auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx index 513ed42dbd8..c716056e223 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx @@ -2105,10 +2105,21 @@ struct LongRangeDihadronCor { for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) + int tpcMult1 = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult1 += 1; + } + int tpcMult2 = 0; + for (const auto& track : tracks2) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult2 += 1; + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult1 < cfgGeneral.cfgCutMultMin || tpcMult1 >= cfgGeneral.cfgCutMultMax)) continue; - if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tpcMult2 < cfgGeneral.cfgCutMultMin || tpcMult2 >= cfgGeneral.cfgCutMultMax)) continue; auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); @@ -2164,10 +2175,21 @@ struct LongRangeDihadronCor { for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - if (cfgGeneral.cfgSelCollByNch && (tracks1.size() < cfgGeneral.cfgCutMultMin || tracks1.size() >= cfgGeneral.cfgCutMultMax)) + int tpcMult1 = 0; + for (const auto& track : tracks1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult1 += 1; + } + int tpcMult2 = 0; + for (const auto& track : tracks2) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult2 += 1; + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult1 < cfgGeneral.cfgCutMultMin || tpcMult1 >= cfgGeneral.cfgCutMultMax)) continue; - if (cfgGeneral.cfgSelCollByNch && (tracks2.size() < cfgGeneral.cfgCutMultMin || tracks2.size() >= cfgGeneral.cfgCutMultMax)) + if (cfgGeneral.cfgSelCollByNch && (tpcMult2 < cfgGeneral.cfgCutMultMin || tpcMult2 >= cfgGeneral.cfgCutMultMax)) continue; auto groupedCollisions1 = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); @@ -2363,6 +2385,16 @@ struct LongRangeDihadronCor { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); } + + int tpcMult = 0; + for (const auto& track : tracksTruth1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) + continue; + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracksRecon1.size(), cent1, false)) continue; if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracksRecon2.size(), cent2, false)) @@ -2429,6 +2461,16 @@ struct LongRangeDihadronCor { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); } + + int tpcMult = 0; + for (const auto& track : tracksTruth1) { + if (std::abs(track.eta()) < cfgGeneral.cfgEtaTpcCut) + tpcMult += 1; + } + + if (cfgGeneral.cfgSelCollByNch && (tpcMult < cfgGeneral.cfgCutMultMin || tpcMult >= cfgGeneral.cfgCutMultMax)) + continue; + if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision1, tracksRecon1.size(), cent1, false)) continue; if (cfgGeneral.cfgUseAdditionalEventCut && !eventSelected(collision2, tracksRecon2.size(), cent2, false)) From aa9b2ba7435e8eb9f380f538f950e12556d868f7 Mon Sep 17 00:00:00 2001 From: Jinhyun Park <125851562+jinhyunni@users.noreply.github.com> Date: Fri, 29 May 2026 23:25:24 +0900 Subject: [PATCH 343/449] [PWGHF] Update tree creator for Xic0Omegac0 (#16421) Co-authored-by: Jinhyun Park Co-authored-by: ALICE Action Bot --- PWGHF/TableProducer/treeCreatorToXiPiQa.cxx | 188 +++++++++++++++++--- 1 file changed, 166 insertions(+), 22 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx index 2e219e14355..000c7d09b6e 100644 --- a/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx +++ b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx @@ -17,6 +17,7 @@ /// \author Krista Smith , Pusan National University #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannelsLegacy.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -38,6 +39,7 @@ using namespace o2; using namespace o2::framework; +using namespace o2::framework::expressions; // SV Reco method enum { @@ -124,6 +126,8 @@ DECLARE_SOA_COLUMN(EtaPiFromCasc, etaPiFromCasc, float); DECLARE_SOA_COLUMN(EtaPiFromCharmBaryon, etaPiFromCharmBaryon, float); DECLARE_SOA_COLUMN(EtaCharmBaryon, etaCharmBaryon, float); DECLARE_SOA_COLUMN(EtaCascade, etaCascade, float); +DECLARE_SOA_COLUMN(PhiCharmBaryon, phiCharmBaryon, float); +DECLARE_SOA_COLUMN(YCharmBaryon, yCharmBaryon, float); DECLARE_SOA_COLUMN(EtaV0, etaV0, float); DECLARE_SOA_COLUMN(DcaXYToPvV0Dau0, dcaXYToPvV0Dau0, float); DECLARE_SOA_COLUMN(DcaXYToPvV0Dau1, dcaXYToPvV0Dau1, float); @@ -212,6 +216,8 @@ DECLARE_SOA_COLUMN(CascChi2OverNdf, cascChi2OverNdf, float); DECLARE_SOA_COLUMN(XicChi2OverNdf, xicChi2OverNdf, float); DECLARE_SOA_COLUMN(MassV0Chi2OverNdf, massV0Chi2OverNdf, float); DECLARE_SOA_COLUMN(MassCascChi2OverNdf, massCascChi2OverNdf, float); +// MC +DECLARE_SOA_COLUMN(ParticlePdg, particlePdg, int); } // namespace full DECLARE_SOA_TABLE(HfToXiPiEvs, "AOD", "HFTOXIPIEV", @@ -303,6 +309,15 @@ DECLARE_SOA_TABLE(HfKfXicFulls, "AOD", "HFKFXICFULL", full::ResultSelections, full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); +DECLARE_SOA_TABLE(HfCandToXiPiGen, "AOD", "HFCANDTOXIPIGEN", + full::InvMassCharmBaryon, + full::PtCharmBaryon, + full::EtaCharmBaryon, + full::PhiCharmBaryon, + full::YCharmBaryon, + full::FlagMcMatchRec, + full::OriginRec, + full::ParticlePdg) } // namespace o2::aod /// Writes the full information in an output TTree @@ -311,15 +326,21 @@ struct HfTreeCreatorToXiPiQa { Produces rowCandidateFull; Produces rowCandidateLite; Produces rowKfCandidate; + Produces rowCandidateParticles; Produces rowEv; Configurable zPvCut{"zPvCut", 10., "Cut on absolute value of primary vertex z coordinate"}; + Configurable genSelection{"genSelection", o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi, "Decay channel to be used to match particle information"}; + Configurable fillGenTable{"fillGenTable", true, "Fill generated MC information if requested"}; using MyTrackTable = soa::Join; using MyEventTable = soa::Join; using MyEventTableWithFT0C = soa::Join; using MyEventTableWithFT0M = soa::Join; using MyEventTableWithNTracksPV = soa::Join; + using MatchedGenXiPi = soa::Filtered>; + + Filter filterGenXiPi = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(genSelection)); void init(InitContext const&) { @@ -611,6 +632,19 @@ struct HfTreeCreatorToXiPiQa { } } + template + void fillParticle(const T& particle, double massCharmBaryon) + { + rowCandidateParticles(RecoDecay::m(particle.pVector(), particle.e()), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(particle.pVector(), massCharmBaryon), + particle.flagMcMatchGen(), + particle.originMcGen(), + particle.pdgCode()); + } + //////////////////////////////////// // // // Process functions // @@ -783,8 +817,10 @@ struct HfTreeCreatorToXiPiQa { //*~~~~~~~MC with DCAFitter~~~~~~~~*// //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// - void processMcFullXic0(MyEventTable const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcFullXic0(MyEventTable const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -797,10 +833,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processMcFullOmegac0(MyEventTable const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcFullOmegac0(MyEventTable const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -813,10 +859,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassOmegaC0); + } + } } - void processMcLiteXic0(MyEventTable const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcLiteXic0(MyEventTable const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -829,10 +885,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processMcLiteXic0WithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcLiteXic0WithFT0C(MyEventTableWithFT0C const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -845,10 +911,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processMcLiteXic0WithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcLiteXic0WithFT0M(MyEventTableWithFT0M const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -861,10 +937,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processMcLiteXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcLiteXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -877,10 +963,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processMcLiteOmegac0(MyEventTable const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processMcLiteOmegac0(MyEventTable const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -893,6 +989,14 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassOmegaC0); + } + } } PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcFullXic0, "Process MC with full information for xic0 w/o centrality", false); @@ -906,8 +1010,10 @@ struct HfTreeCreatorToXiPiQa { //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// //*~~~~~~~MC with KFParticle~~~~~~~~*// //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// - void processKfMcXic0(MyEventTable const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processKfMcXic0(MyEventTable const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -920,10 +1026,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processKfMcXic0WithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processKfMcXic0WithFT0C(MyEventTableWithFT0C const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -936,10 +1052,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processKfMcXic0WithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processKfMcXic0WithFT0M(MyEventTableWithFT0M const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -952,10 +1078,20 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } - void processKfMcXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, - soa::Join const& candidates) + void processKfMcXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, + MyTrackTable const&, + soa::Join const& candidates, + MatchedGenXiPi const& mcParticles) { // Filling event properties rowEv.reserve(collisions.size()); @@ -968,6 +1104,14 @@ struct HfTreeCreatorToXiPiQa { for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } + + // Filling particle properties if requested + if (fillGenTable) { + rowCandidateParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + fillParticle(particle, o2::constants::physics::MassXiC0); + } + } } PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0, "Process MC with information for xic0", false); From db0b63aa9e6d6eb7a6d0382dbaffad2fdef28af7 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 29 May 2026 16:33:43 +0200 Subject: [PATCH 344/449] [PWGEM/Dilepton] reduce data in taggingHFE (#16453) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 44 +++++---- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 126 ++++++++++++------------ PWGEM/Dilepton/Utils/ElectronModule.h | 16 +-- PWGEM/Dilepton/Utils/MlResponseSCT.h | 48 ++++----- PWGEM/Dilepton/Utils/SemiCharmTag.h | 121 ++++++++++++----------- 5 files changed, 181 insertions(+), 174 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 86b24480660..fed4529ed29 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -261,6 +261,7 @@ DECLARE_SOA_COLUMN(CascadeType, cascadeType, uint8_t); //! cascade type, 0 = XiM // LH pair variables DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming kaon DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pt of LH +DECLARE_SOA_COLUMN(PLH, pLH, float); //! p of LH DECLARE_SOA_COLUMN(PtSVL, ptSVL, float); //! pT of lepton at SV // DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV @@ -275,10 +276,11 @@ DECLARE_SOA_COLUMN(PtSVH, ptSVH, float); //! pT of associated hadron at SV DECLARE_SOA_COLUMN(PtFD, ptFD, float); //! visible momentum of LH pair perpendicular to flight direction = - missing pT due to neutrino perpendicular to flight direction DECLARE_SOA_COLUMN(PlFD, plFD, float); //! visible momentum of LH pair in parallel to flight direction -DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron -DECLARE_SOA_COLUMN(CPA, cpa, float); //! cosine of pointing angle of LH pair -DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); //! cosine of pointing angle of LH pair in XY -DECLARE_SOA_COLUMN(CPARZ, cpaRZ, float); //! cosine of pointing angle of LH pair in RZ +// DECLARE_SOA_COLUMN(DcaLH, dcalh, float); //! DCA between lepton and hadron +DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); //! DCA between lepton and hadron +DECLARE_SOA_COLUMN(CPA, cpa, float); //! cosine of pointing angle of LH pair +DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); //! cosine of pointing angle of LH pair in XY +DECLARE_SOA_COLUMN(CPARZ, cpaRZ, float); //! cosine of pointing angle of LH pair in RZ DECLARE_SOA_COLUMN(Lxy, lxy, float); //! decay length of LH pair DECLARE_SOA_COLUMN(Lz, lz, float); //! decay length of LH pair @@ -287,11 +289,11 @@ DECLARE_SOA_COLUMN(LxyErr, lxyErr, float); //! decay length resolution of LH p DECLARE_SOA_COLUMN(LzErr, lzErr, float); //! decay length resolution of LH pair DECLARE_SOA_COLUMN(LxyzErr, lxyzErr, float); //! decay length resolution of LH pair -DECLARE_SOA_COLUMN(ImpParXY, impParXY, float); //! impact parameter for LH in XY plane -DECLARE_SOA_COLUMN(ImpParZ, impParZ, float); //! impact parameter for LH in Z plane -DECLARE_SOA_COLUMN(ImpParCYY, impParCYY, float); //! sigma of impact parameter for LH in XY -DECLARE_SOA_COLUMN(ImpParCZY, impParCZY, float); //! sigma of impact parameter for LH, correlation term -DECLARE_SOA_COLUMN(ImpParCZZ, impParCZZ, float); //! sigma of impact parameter for LH in Z +// DECLARE_SOA_COLUMN(ImpParXY, impParXY, float); //! impact parameter for LH in XY plane +// DECLARE_SOA_COLUMN(ImpParZ, impParZ, float); //! impact parameter for LH in Z plane +// DECLARE_SOA_COLUMN(ImpParCYY, impParCYY, float); //! sigma of impact parameter for LH in XY +// DECLARE_SOA_COLUMN(ImpParCZY, impParCZY, float); //! sigma of impact parameter for LH, correlation term +// DECLARE_SOA_COLUMN(ImpParCZZ, impParCZZ, float); //! sigma of impact parameter for LH in Z DECLARE_SOA_COLUMN(PdgCodeH, pdgCodeH, int); //! pdg code of associated hadron DECLARE_SOA_COLUMN(PdgCodeIM, pdgCodeIM, int); //! pdg code of intermediate hadron from HF hadrons. e.g K*, D* @@ -305,11 +307,11 @@ DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! // pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, // pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, - emmllhpair::PtFD, emmllhpair::PlFD, - emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + emmllhpair::MassLH, emmllhpair::PLH, + // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, + emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, - emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, + // emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLTPair = EMMLLTPairs::iterator; @@ -319,11 +321,11 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, - emmllhpair::PtFD, emmllhpair::PlFD, - emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + emmllhpair::MassLH, emmllhpair::PLH, + // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, + emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, - emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, + // emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLV0Pair = EMMLLV0Pairs::iterator; @@ -333,11 +335,11 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PtLH, emmllhpair::PtSVL, emmllhpair::PtSVH, - emmllhpair::PtFD, emmllhpair::PlFD, - emmllhpair::DcaLH, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, + emmllhpair::MassLH, emmllhpair::PLH, + // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, + emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, - emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, + // emmllhpair::ImpParXY, emmllhpair::ImpParZ, emmllhpair::ImpParCYY, emmllhpair::ImpParCZY, emmllhpair::ImpParCZZ, emmllhpair::PdgCodeH, emmllhpair::PdgCodeIM, emmllhpair::FoundCommonMother); // iterators using EMMLLCascPair = EMMLLCascPairs::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index d97f4837579..2b1d89a4436 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -273,21 +273,21 @@ struct taggingHFE { std::string prefix = "lKPairCut"; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; + Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; } lKPairCut; struct : ConfigurableGroup { std::string prefix = "lV0PairCut"; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; + Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; } lV0PairCut; struct : ConfigurableGroup { std::string prefix = "lCPairCut"; Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; - Configurable cfg_max_dca2legs{"cfg_max_dca2legs", 1.0, "max distance between 2 legs"}; + Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; } lCPairCut; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -1727,7 +1727,7 @@ struct taggingHFE { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { continue; } @@ -1762,11 +1762,11 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, - eKpair.ptFD, eKpair.plFD, - eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + eKpair.mass, eKpair.p, + // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, + eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, - eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, + // eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1788,7 +1788,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { continue; } @@ -1823,11 +1823,11 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, - eKpair.ptFD, eKpair.plFD, - eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + eKpair.mass, eKpair.p, + // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, + eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, - eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, + // eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -1858,7 +1858,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { continue; } @@ -1902,11 +1902,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, - eV0pair.ptFD, eV0pair.plFD, - eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.p, + // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, + eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, - eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, + // eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -1937,7 +1937,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { continue; } @@ -1965,11 +1965,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, - eV0pair.ptFD, eV0pair.plFD, - eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.p, + // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, + eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, - eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, + // eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Lambda loop @@ -1999,7 +1999,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { continue; } @@ -2033,11 +2033,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, - eCpair.ptFD, eCpair.plFD, - eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.p, + // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, + eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, - eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, + // eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi- loop @@ -2067,7 +2067,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { continue; } @@ -2101,11 +2101,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, - eCpair.ptFD, eCpair.plFD, - eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.p, + // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, + eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, - eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, + // eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega- loop @@ -2163,7 +2163,7 @@ struct taggingHFE { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { continue; } @@ -2198,11 +2198,11 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, - eKpair.ptFD, eKpair.plFD, - eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + eKpair.mass, eKpair.p, + // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, + eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, - eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, + // eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -2225,7 +2225,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_dca2legs < eKpair.dca2legs) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { continue; } @@ -2260,11 +2260,11 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.pt, eKpair.ptSVL, eKpair.ptSVH, - eKpair.ptFD, eKpair.plFD, - eKpair.dca2legs, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, + eKpair.mass, eKpair.p, + // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, + eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, - eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, + // eKpair.impParXY, eKpair.impParZ, eKpair.impParCYY, eKpair.impParCZY, eKpair.impParCZZ, mckaon.pdgCode(), pdgCodeIM, foundCommonMother); } // end of kaon loop @@ -2295,7 +2295,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { continue; } @@ -2338,11 +2338,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, - eV0pair.ptFD, eV0pair.plFD, - eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.p, + // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, + eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, - eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, + // eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of K0S loop @@ -2373,7 +2373,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_dca2legs < eV0pair.dca2legs) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { continue; } @@ -2401,11 +2401,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.pt, eV0pair.ptSVL, eV0pair.ptSVH, - eV0pair.ptFD, eV0pair.plFD, - eV0pair.dca2legs, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, + eV0pair.mass, eV0pair.p, + // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, + eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, - eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, + // eV0pair.impParXY, eV0pair.impParZ, eV0pair.impParCYY, eV0pair.impParCZY, eV0pair.impParCZZ, pdgCodeV0, pdgCodeIM, foundCommonMother); } // end of Anti-Lambda loop @@ -2435,7 +2435,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { continue; } @@ -2469,11 +2469,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, - eCpair.ptFD, eCpair.plFD, - eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.p, + // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, + eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, - eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, + // eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Xi+ loop @@ -2503,7 +2503,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_dca2legs < eCpair.dca2legs) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { continue; } @@ -2537,11 +2537,11 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.pt, eCpair.ptSVL, eCpair.ptSVH, - eCpair.ptFD, eCpair.plFD, - eCpair.dca2legs, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, + eCpair.mass, eCpair.p, + // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, + eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, - eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, + // eCpair.impParXY, eCpair.impParZ, eCpair.impParCYY, eCpair.impParCZY, eCpair.impParCZZ, pdgCodeCascade, pdgCodeIM, foundCommonMother); } // end of Omega+ loop diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index 99a40c8d28b..6b4bbfb1a3f 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -2166,18 +2166,18 @@ class ElectronModule candidate.impParZHinSigma = candidate.impParZH / std::sqrt(trackParCov.getSigmaZ2()); candidate.impPar3DHinSigma = dca3DinSigmaOTF(candidate.impParXYH, candidate.impParZH, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY()); candidate.signLH = 0; - candidate.dcaLH = pair.dca2legs; - candidate.logChi2PCA = std::log10(std::pow(pair.dca2legs, 2)); + candidate.dcaLH = std::sqrt(pair.chi2PCA); + candidate.logChi2PCA = std::log10(pair.chi2PCA); candidate.massLH = pair.mass; candidate.signedMassLH = pair.mass; candidate.cpa = pair.cospa; candidate.cpaXY = pair.cospaXY; - candidate.impParXY = pair.impParXY; - candidate.impParZ = pair.impParZ; - candidate.impPar3D = std::sqrt(std::pow(candidate.impParXY, 2) + std::pow(candidate.impParZ, 2)); - candidate.impParXYinSigma = candidate.impParXY / std::sqrt(pair.impParCYY); - candidate.impParZinSigma = candidate.impParZ / std::sqrt(pair.impParCZZ); - candidate.impPar3DinSigma = dca3DinSigmaOTF(candidate.impParXY, candidate.impParZ, pair.impParCYY, pair.impParCZY, pair.impParCZZ); + // candidate.impParXY = pair.impParXY; + // candidate.impParZ = pair.impParZ; + // candidate.impPar3D = std::sqrt(std::pow(candidate.impParXY, 2) + std::pow(candidate.impParZ, 2)); + // candidate.impParXYinSigma = candidate.impParXY / std::sqrt(pair.impParCYY); + // candidate.impParZinSigma = candidate.impParZ / std::sqrt(pair.impParCZZ); + // candidate.impPar3DinSigma = dca3DinSigmaOTF(candidate.impParXY, candidate.impParZ, pair.impParCYY, pair.impParCZY, pair.impParCZZ); candidate.decayLengthXY = pair.lxy; candidate.decayLengthZ = pair.lz; candidate.decayLength3D = pair.lxyz; diff --git a/PWGEM/Dilepton/Utils/MlResponseSCT.h b/PWGEM/Dilepton/Utils/MlResponseSCT.h index c55e10da8c4..172b2043ce6 100644 --- a/PWGEM/Dilepton/Utils/MlResponseSCT.h +++ b/PWGEM/Dilepton/Utils/MlResponseSCT.h @@ -70,12 +70,12 @@ enum class InputFeaturesSCT : uint8_t { correctedMass, cpa, cpaXY, - impParXY, - impParZ, - impPar3D, - impParXYinSigma, - impParZinSigma, - impPar3DinSigma, + // impParXY, + // impParZ, + // impPar3D, + // impParXYinSigma, + // impParZinSigma, + // impPar3DinSigma, decayLengthXY, decayLengthZ, decayLength3D, @@ -117,12 +117,12 @@ struct candidate { float correctedMass{0}; float cpa{0}; float cpaXY{0}; - float impParXY{0}; - float impParZ{0}; - float impPar3D{0}; - float impParXYinSigma{0}; - float impParZinSigma{0}; - float impPar3DinSigma{0}; + // float impParXY{0}; + // float impParZ{0}; + // float impPar3D{0}; + // float impParXYinSigma{0}; + // float impParZinSigma{0}; + // float impPar3DinSigma{0}; float decayLengthXY{0}; float decayLengthZ{0}; float decayLength3D{0}; @@ -171,12 +171,12 @@ class MlResponseSCT : public MlResponse CHECK_AND_FILL_TRACK(correctedMass); CHECK_AND_FILL_TRACK(cpa); CHECK_AND_FILL_TRACK(cpaXY); - CHECK_AND_FILL_TRACK(impParXY); - CHECK_AND_FILL_TRACK(impParZ); - CHECK_AND_FILL_TRACK(impPar3D); - CHECK_AND_FILL_TRACK(impParXYinSigma); - CHECK_AND_FILL_TRACK(impParZinSigma); - CHECK_AND_FILL_TRACK(impPar3DinSigma); + // CHECK_AND_FILL_TRACK(impParXY); + // CHECK_AND_FILL_TRACK(impParZ); + // CHECK_AND_FILL_TRACK(impPar3D); + // CHECK_AND_FILL_TRACK(impParXYinSigma); + // CHECK_AND_FILL_TRACK(impParZinSigma); + // CHECK_AND_FILL_TRACK(impPar3DinSigma); CHECK_AND_FILL_TRACK(decayLengthXY); CHECK_AND_FILL_TRACK(decayLengthZ); CHECK_AND_FILL_TRACK(decayLength3D); @@ -250,12 +250,12 @@ class MlResponseSCT : public MlResponse FILL_MAP_TRACK(correctedMass), FILL_MAP_TRACK(cpa), FILL_MAP_TRACK(cpaXY), - FILL_MAP_TRACK(impParXY), - FILL_MAP_TRACK(impParZ), - FILL_MAP_TRACK(impPar3D), - FILL_MAP_TRACK(impParXYinSigma), - FILL_MAP_TRACK(impParZinSigma), - FILL_MAP_TRACK(impPar3DinSigma), + // FILL_MAP_TRACK(impParXY), + // FILL_MAP_TRACK(impParZ), + // FILL_MAP_TRACK(impPar3D), + // FILL_MAP_TRACK(impParXYinSigma), + // FILL_MAP_TRACK(impParZinSigma), + // FILL_MAP_TRACK(impPar3DinSigma), FILL_MAP_TRACK(decayLengthXY), FILL_MAP_TRACK(decayLengthZ), FILL_MAP_TRACK(decayLength3D), diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index b02b377330a..d390940398a 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -36,7 +36,9 @@ namespace o2::aod::pwgem::dilepton::utils struct LHPair { // struct to store electron-hadron pair information float mass{-999.f}; float pt{-999.f}; + float p{-999.f}; float dca2legs{-999.f}; + float chi2PCA{-999.f}; float cospa{-999.f}; float cospaXY{-999.f}; float cospaRZ{-999.f}; @@ -52,9 +54,9 @@ struct LHPair { // struct to store electron-hadron pair information float impParCZY{-999.f}; float impParCZZ{-999.f}; - float ptSVL{-999.f}; + // float ptSVL{-999.f}; // float plSVL{-999.f}; - float ptSVH{-999.f}; + // float ptSVH{-999.f}; // float plSVH{-999.f}; // float ptFDL{-999.f}; @@ -62,8 +64,8 @@ struct LHPair { // struct to store electron-hadron pair information // float ptFDH{-999.f}; // float plFDH{-999.f}; - float ptFD{-999.f}; - float plFD{-999.f}; + // float ptFD{-999.f}; + // float plFD{-999.f}; bool isOK{false}; }; @@ -107,8 +109,8 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton fitter.getTrack(1).getPxPyPzGlo(pvec1); // track std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; - pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); - pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + // pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + // pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); // pair.plSVL = pvec0[2]; // pair.plSVH = pvec1[2]; @@ -116,6 +118,7 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); + pair.chi2PCA = fitter.getChi2AtPCACandidate(); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); pair.lxyz = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2) + std::pow(svpos[2] - collision.posZ(), 2)); @@ -128,29 +131,29 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLH, 0.) + getRotatedCovMatrixXX(covVtxLH, phiLH, 0.)); pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLH) + getRotatedCovMatrixXX(covVtxLH, 0, thetaLH)); - std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction - pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); - pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + // std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + // pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + // pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); - // propagate the 2 prongs to the secondary vertex - leptonParCov.propagateTo(vtx[0], fitter.getBz()); - trackParCov.propagateTo(vtx[0], fitter.getBz()); + // // propagate the 2 prongs to the secondary vertex + // leptonParCov.propagateTo(vtx[0], fitter.getBz()); + // trackParCov.propagateTo(vtx[0], fitter.getBz()); - // calculate impact parameter - o2::dataformats::DCA dcaLH; - auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, trackParCov); - trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + // // calculate impact parameter + // o2::dataformats::DCA dcaLH; + // auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, trackParCov); + // trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); - pair.impParXY = dcaLH.getY(); - pair.impParZ = dcaLH.getZ(); - pair.impParCYY = dcaLH.getSigmaY2(); - pair.impParCZY = dcaLH.getSigmaYZ(); - pair.impParCZZ = dcaLH.getSigmaZ2(); + // pair.impParXY = dcaLH.getY(); + // pair.impParZ = dcaLH.getZ(); + // pair.impParCYY = dcaLH.getSigmaY2(); + // pair.impParCZY = dcaLH.getSigmaYZ(); + // pair.impParCZZ = dcaLH.getSigmaZ2(); // LOGF(info, "fitter.getBz() = %f, dcaLH.getY() = %f, dcaLH.getZ() = %f", fitter.getBz(), dcaLH.getY(), dcaLH.getZ()); @@ -169,9 +172,7 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); pair.pt = v12.Pt(); - - // float tmp = v12.P() * std::sin(std::acos(pair.cospa)); - // LOGF(info, "pair.ptFD = %f, tmp = %f", pair.ptFD, tmp); + pair.p = v12.P(); pair.isOK = true; return pair; @@ -226,8 +227,8 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co fitter.getTrack(1).getPxPyPzGlo(pvec1); // v0 std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; - pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); - pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + // pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + // pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); // pair.plSVL = pvec0[2]; // pair.plSVH = pvec1[2]; @@ -235,6 +236,7 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); + pair.chi2PCA = fitter.getChi2AtPCACandidate(); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); pair.lxyz = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2) + std::pow(svpos[2] - collision.posZ(), 2)); @@ -247,29 +249,29 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.lxyErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLV0, 0.) + getRotatedCovMatrixXX(covVtxLV0, phiLV0, 0.)); pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLV0) + getRotatedCovMatrixXX(covVtxLV0, 0, thetaLV0)); - std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction - pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); - pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + // std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + // pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + // pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); - // propagate the 2 prongs to the secondary vertex - leptonParCov.propagateTo(vtx[0], fitter.getBz()); - v0ParCov.propagateTo(vtx[0], fitter.getBz()); + // // propagate the 2 prongs to the secondary vertex + // leptonParCov.propagateTo(vtx[0], fitter.getBz()); + // v0ParCov.propagateTo(vtx[0], fitter.getBz()); - // calculate impact parameter - o2::dataformats::DCA dcaLH; - auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, v0ParCov); - trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + // // calculate impact parameter + // o2::dataformats::DCA dcaLH; + // auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, v0ParCov); + // trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); - pair.impParXY = dcaLH.getY(); - pair.impParZ = dcaLH.getZ(); - pair.impParCYY = dcaLH.getSigmaY2(); - pair.impParCZY = dcaLH.getSigmaYZ(); - pair.impParCZZ = dcaLH.getSigmaZ2(); + // pair.impParXY = dcaLH.getY(); + // pair.impParZ = dcaLH.getZ(); + // pair.impParCYY = dcaLH.getSigmaY2(); + // pair.impParCZY = dcaLH.getSigmaYZ(); + // pair.impParCZZ = dcaLH.getSigmaZ2(); ROOT::Math::PxPyPzMVector v1(pvec0[0], pvec0[1], pvec0[2], o2::constants::physics::MassElectron); if (leptonId == o2::track::PID::Electron) { @@ -296,6 +298,7 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); pair.pt = v12.Pt(); + pair.p = v12.P(); pair.isOK = true; return pair; @@ -354,8 +357,8 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept fitter.getTrack(1).getPxPyPzGlo(pvec1); // cascade std::array pvecSum = {pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; - pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); - pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); + // pair.ptSVL = RecoDecay::sqrtSumOfSquares(pvec0[0], pvec0[1]); + // pair.ptSVH = RecoDecay::sqrtSumOfSquares(pvec1[0], pvec1[1]); // pair.plSVL = pvec0[2]; // pair.plSVH = pvec1[2]; @@ -363,6 +366,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.cospaXY = RecoDecay::cpaXY(vertex, svpos, pvecSum); pair.cospaRZ = RecoDecay::cpaRZ(vertex, svpos, pvecSum); pair.dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); + pair.chi2PCA = fitter.getChi2AtPCACandidate(); pair.lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); pair.lz = svpos[2] - collision.posZ(); pair.lxyz = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2) + std::pow(svpos[2] - collision.posZ(), 2)); @@ -375,29 +379,29 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.lzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), 0, thetaLC) + getRotatedCovMatrixXX(covVtxLC, 0, thetaLC)); pair.lxyzErr = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiLC, thetaLC) + getRotatedCovMatrixXX(covVtxLC, phiLC, thetaLC)); - std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction - pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); - pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); + // std::array uvFD = {(svpos[0] - collision.posX()) / pair.lxyz, (svpos[1] - collision.posY()) / pair.lxyz, (svpos[2] - collision.posZ()) / pair.lxyz}; // unit vector of flight direction + // pair.plFD = RecoDecay::dotProd(pvecSum, uvFD); + // pair.ptFD = RecoDecay::sqrtSumOfSquares(pvecSum[0] - pair.plFD * uvFD[0], pvecSum[1] - pair.plFD * uvFD[1], pvecSum[2] - pair.plFD * uvFD[2]); // pair.plFDL = RecoDecay::dotProd(pvec0, uvFD); // pair.plFDH = RecoDecay::dotProd(pvec1, uvFD); // pair.ptFDL = RecoDecay::sqrtSumOfSquares(pvec0[0] - pair.plFDL * uvFD[0], pvec0[1] - pair.plFDL * uvFD[1], pvec0[2] - pair.plFDL * uvFD[2]); // pair.ptFDH = RecoDecay::sqrtSumOfSquares(pvec1[0] - pair.plFDH * uvFD[0], pvec1[1] - pair.plFDH * uvFD[1], pvec1[2] - pair.plFDH * uvFD[2]); - // propagate the 2 prongs to the secondary vertex - leptonParCov.propagateTo(vtx[0], fitter.getBz()); - cascParCov.propagateTo(vtx[0], fitter.getBz()); + // // propagate the 2 prongs to the secondary vertex + // leptonParCov.propagateTo(vtx[0], fitter.getBz()); + // cascParCov.propagateTo(vtx[0], fitter.getBz()); - // calculate impact parameter - o2::dataformats::DCA dcaLH; - auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, cascParCov); - trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); + // // calculate impact parameter + // o2::dataformats::DCA dcaLH; + // auto trackParCovLH = o2::dataformats::V0(fitter.getPCACandidatePos(), pvecSum, fitter.calcPCACovMatrixFlat(), leptonParCov, cascParCov); + // trackParCovLH.propagateToDCA(primaryVertex, fitter.getBz(), &dcaLH); - pair.impParXY = dcaLH.getY(); - pair.impParZ = dcaLH.getZ(); - pair.impParCYY = dcaLH.getSigmaY2(); - pair.impParCZY = dcaLH.getSigmaYZ(); - pair.impParCZZ = dcaLH.getSigmaZ2(); + // pair.impParXY = dcaLH.getY(); + // pair.impParZ = dcaLH.getZ(); + // pair.impParCYY = dcaLH.getSigmaY2(); + // pair.impParCZY = dcaLH.getSigmaYZ(); + // pair.impParCZZ = dcaLH.getSigmaZ2(); ROOT::Math::PxPyPzMVector v1(pvec0[0], pvec0[1], pvec0[2], o2::constants::physics::MassElectron); if (leptonId == o2::track::PID::Electron) { @@ -424,6 +428,7 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept ROOT::Math::PxPyPzMVector v12 = v1 + v2; pair.mass = v12.M(); pair.pt = v12.Pt(); + pair.p = v12.P(); pair.isOK = true; return pair; From 09ad289f03359b96815e1c2173a0328efc98851d Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Sat, 30 May 2026 00:37:58 +0800 Subject: [PATCH 345/449] [PWGCF] fix some bugs in flowGfwOmegaXi.cxx (#16458) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 42 ++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index ad9ae6e0280..b0136c59acc 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -116,8 +116,10 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgv0_dcadaupitopv, float, 0.01f, "minimum daughter pion DCA to PV") O2_DEFINE_CONFIGURABLE(cfgv0_dcadauprtopv, float, 0.1f, "minimum daughter proton DCA to PV") O2_DEFINE_CONFIGURABLE(cfgv0_dcav0dau, float, 0.5f, "maximum DCA among V0 daughters") - O2_DEFINE_CONFIGURABLE(cfgv0_mk0swindow, float, 0.1f, "Invariant mass window of K0s") - O2_DEFINE_CONFIGURABLE(cfgv0_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") + O2_DEFINE_CONFIGURABLE(cfgv0_mk0slow, float, 0.4f, "minimun invariant mass cut of K0s") + O2_DEFINE_CONFIGURABLE(cfgv0_mk0shigh, float, 0.6f, "maximum invariant mass cut of K0s") + O2_DEFINE_CONFIGURABLE(cfgv0_mlambdalow, float, 1.08f, "minimun invariant mass cut of lambda") + O2_DEFINE_CONFIGURABLE(cfgv0_mlambdahigh, float, 1.16f, "maximum invariant mass cut of lambda") O2_DEFINE_CONFIGURABLE(cfgv0_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0") O2_DEFINE_CONFIGURABLE(cfgv0_compmassrejLambda, float, 0.01f, "competing mass rejection of lambda") O2_DEFINE_CONFIGURABLE(cfgv0_compmassrejK0s, float, 0.005f, "competing mass rejection of K0s") @@ -213,6 +215,7 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "do QA") O2_DEFINE_CONFIGURABLE(cfgUseT0MCent, bool, false, "Use T0M cent") + O2_DEFINE_CONFIGURABLE(cfgcheckhole, bool, true, "Check and reject vtxz-eta-phi hole") ConfigurableAxis cfgaxisVertex{"cfgaxisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"cfgaxisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -233,7 +236,7 @@ struct FlowGfwOmegaXi { AxisSpec axisMultiplicity{{0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "Centrality (%)"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && (aod::track::pt > trkQualityOpts.cfgCutPtPOIMin.value) && (aod::track::pt < trkQualityOpts.cfgCutPtPOIMax.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < trkQualityOpts.cfgCutDCAz.value) && (nabs(aod::track::dcaXY) < trkQualityOpts.cfgCutDCAxy.value); + Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); using TracksPID = soa::Join; using AodTracks = soa::Filtered>; // tracks filter @@ -959,10 +962,17 @@ struct FlowGfwOmegaXi { if (eff <= 0) return false; weight_nue = 1. / eff; - if (mAcceptance.size() == static_cast(nspecies)) + if (mAcceptance.size() == static_cast(nspecies)) { weight_nua = mAcceptance[ispecies]->getNUA(track.phi(), track.eta(), vtxz); - else + if (cfgcheckhole) { + float checkleft = mAcceptance[ispecies]->getNUA(1, track.eta(), vtxz); + float checkright = mAcceptance[ispecies]->getNUA(2, track.eta(), vtxz); + if (weight_nua == 1 && checkleft == 1 && checkright == 1) + return false; + } + } else { weight_nua = 1; + } return true; } @@ -1132,6 +1142,11 @@ struct FlowGfwOmegaXi { } if ((track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) || (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) || (track.itsNCls() <= trkQualityOpts.cfgChITSNCls.value)) continue; + if ((track.pt() < trkQualityOpts.cfgCutPtPOIMin.value) || (track.pt() > trkQualityOpts.cfgCutPtPOIMax.value)) + continue; + if ((std::fabs(track.dcaZ()) > trkQualityOpts.cfgCutDCAz.value) || (std::fabs(track.dcaXY()) > trkQualityOpts.cfgCutDCAxy.value)) + continue; + registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hPhicorr"), track.phi(), wacc); registry.fill(HIST("hEta"), track.eta()); @@ -1190,7 +1205,7 @@ struct FlowGfwOmegaXi { // K0short if (v0.pt() > trkQualityOpts.cfgCutPtK0sMin.value && v0.pt() < trkQualityOpts.cfgCutPtK0sMax.value) { if (v0.qtarm() / std::fabs(v0.alpha()) > v0BuilderOpts.cfgv0_ArmPodocut.value && - std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_mk0swindow.value && + v0.mK0Short() > v0BuilderOpts.cfgv0_mk0slow.value && v0.mK0Short() < v0BuilderOpts.cfgv0_mk0shigh.value && (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && ((std::fabs(v0.tofNSigmaK0PiPlus()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaK0PiMinus()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { @@ -1203,14 +1218,14 @@ struct FlowGfwOmegaXi { } // Lambda and antiLambda if (v0.pt() > trkQualityOpts.cfgCutPtLambdaMin.value && v0.pt() < trkQualityOpts.cfgCutPtLambdaMax.value) { - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && + if (v0.mLambda() > v0BuilderOpts.cfgv0_mlambdalow.value && v0.mLambda() < v0BuilderOpts.cfgv0_mlambdahigh.value && (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && ((std::fabs(v0.tofNSigmaLaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaLaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); isLambda = true; } - if (std::fabs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && + if (v0.mAntiLambda() > v0BuilderOpts.cfgv0_mlambdalow.value && v0.mAntiLambda() < v0BuilderOpts.cfgv0_mlambdahigh.value && (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]) && ((std::fabs(v0.tofNSigmaALaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaALaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { @@ -1399,9 +1414,9 @@ struct FlowGfwOmegaXi { } registry.fill(HIST("correction/hRunNumberPhiEtaVertexLambda"), matchedPosition, v0.phi(), v0.eta(), vtxz); if (isLambda) - registry.fill(HIST("correction/hPhiEtaInvmassLambda"), matchedPosition, v0.phi(), v0.eta(), v0.mLambda()); + registry.fill(HIST("correction/hPhiEtaInvmassLambda"), v0.phi(), v0.eta(), v0.mLambda()); if (isALambda) - registry.fill(HIST("correction/hPhiEtaInvmassLambda"), matchedPosition, v0.phi(), v0.eta(), v0.mAntiLambda()); + registry.fill(HIST("correction/hPhiEtaInvmassLambda"), v0.phi(), v0.eta(), v0.mAntiLambda()); } } } @@ -2244,7 +2259,6 @@ struct FlowGfwOmegaXi { // K0short if (std::abs(pdgCode) == kK0Short) { if (v0.qtarm() / std::fabs(v0.alpha()) > v0BuilderOpts.cfgv0_ArmPodocut.value && - std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_mk0swindow.value && (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 1); @@ -2260,8 +2274,7 @@ struct FlowGfwOmegaXi { } } // Lambda and antiLambda - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && - (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) { + if ((std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (std::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); @@ -2275,8 +2288,7 @@ struct FlowGfwOmegaXi { } fGFW->Fill(v0Eta, fLambdaPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); } - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && - (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0])) { + } else if ((std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (std::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); From 2b6c427df5468b22fe75fbd1e035e61b83e8de47 Mon Sep 17 00:00:00 2001 From: Nikita Gladin <72004465+AnalitikGnid@users.noreply.github.com> Date: Fri, 29 May 2026 19:57:56 +0200 Subject: [PATCH 346/449] [PWGCF] (Anti)triton analysis (#16433) --- .../Femto3D/TableProducer/singleTrackSelector.cxx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx b/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx index b1704a160b5..8dfdc58f4e5 100644 --- a/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx +++ b/PWGCF/Femto3D/TableProducer/singleTrackSelector.cxx @@ -183,9 +183,11 @@ struct singleTrackSelector { registry.add("hGen_EtaPhiPt_Proton", "Gen (anti)protons in true collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hGen_EtaPhiPt_Deuteron", "Gen (anti)deuteron in true collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hGen_EtaPhiPt_Helium3", "Gen (anti)Helium3 in true collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); + registry.add("hGen_EtaPhiPt_Triton", "Gen (anti)triton in true collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hReco_EtaPhiPt_Proton", "Gen (anti)protons in reco collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hReco_EtaPhiPt_Deuteron", "Gen (anti)deuteron in reco collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); registry.add("hReco_EtaPhiPt_Helium3", "Gen (anti)Helium3 in reco collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); + registry.add("hReco_EtaPhiPt_Triton", "Gen (anti)triton in reco collisions", {HistType::kTH3F, {{100, -1., 1., "#eta"}, {157, 0., o2::constants::math::TwoPI, "#phi"}, {100, -5.f, 5.f, "p_{T} GeV/c"}}}); } } @@ -582,6 +584,12 @@ struct singleTrackSelector { } else if (mcParticle.pdgCode() == -1000020030) { registry.fill(HIST("hReco_EtaPhiPt_Helium3"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt() * -1); } + + if (mcParticle.pdgCode() == 1000010030) { + registry.fill(HIST("hReco_EtaPhiPt_Triton"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt()); + } else if (mcParticle.pdgCode() == -1000010030) { + registry.fill(HIST("hReco_EtaPhiPt_Triton"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt() * -1); + } } } } @@ -622,6 +630,12 @@ struct singleTrackSelector { } else if (mcParticle.pdgCode() == -1000020030) { registry.fill(HIST("hGen_EtaPhiPt_Helium3"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt() * -1); } + + if (mcParticle.pdgCode() == 1000010030) { + registry.fill(HIST("hGen_EtaPhiPt_Triton"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt()); + } else if (mcParticle.pdgCode() == -1000010030) { + registry.fill(HIST("hGen_EtaPhiPt_Triton"), mcParticle.eta(), mcParticle.phi(), mcParticle.pt() * -1); + } } } PROCESS_SWITCH(singleTrackSelector, processGenRun3, "process MC Gen collisions Run3", false); From c94082b0bcdd82300186e3520c5cf763658c4011 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Sat, 30 May 2026 00:09:57 +0530 Subject: [PATCH 347/449] [PWGCF] Use ITS pid instead of TPC when configured (#16459) --- .../Tasks/v0ptHadPiKaProt.cxx | 130 ++++++++++++------ 1 file changed, 85 insertions(+), 45 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index a10705d4c0c..d1f455cfbad 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -546,18 +545,31 @@ struct V0ptHadPiKaProt { return false; int flag = 0; //! pid check main flag + float partNsigmaTpcOrItsPi = 0.0; + float partNsigmaTpcOrItsKa = 0.0; + float partNsigmaTpcOrItsPr = 0.0; + if (cfgUseItsPID) { + partNsigmaTpcOrItsPi = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsKa = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsPr = itsResponse.nSigmaITS(candidate); + } else { + partNsigmaTpcOrItsPi = candidate.tpcNSigmaPi(); + partNsigmaTpcOrItsKa = candidate.tpcNSigmaKa(); + partNsigmaTpcOrItsPr = candidate.tpcNSigmaPr(); + } + if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { + if (!candidate.hasTOF() && std::abs(partNsigmaTpcOrItsPr) < cfgnSigmaCutTPC) { flag = 1; } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF) { + if (candidate.hasTOF() && std::abs(partNsigmaTpcOrItsPr) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF) { flag = 1; } } if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - const float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - const float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(std::pow(partNsigmaTpcOrItsPr, 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); + const float combNSigmaPi = std::sqrt(std::pow(partNsigmaTpcOrItsPi, 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(std::pow(partNsigmaTpcOrItsKa, 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); int flag2 = 0; if (combNSigmaPr < cfgnSigmaOtherParticles) @@ -568,8 +580,8 @@ struct V0ptHadPiKaProt { flag2 += 1; if (cfgUseNewSeperationPid) { - if (std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOFHigherPt) { - if (!(flag2 > 1) && std::abs(candidate.tpcNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(candidate.tpcNSigmaKa()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaSeperationCut) + if (std::abs(partNsigmaTpcOrItsPr) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOFHigherPt) { + if (!(flag2 > 1) && std::abs(partNsigmaTpcOrItsPi) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(partNsigmaTpcOrItsKa) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaSeperationCut) flag = 1; } } else { @@ -600,18 +612,31 @@ struct V0ptHadPiKaProt { return false; int flag = 0; //! pid check main flag + float partNsigmaTpcOrItsPi = 0.0; + float partNsigmaTpcOrItsKa = 0.0; + float partNsigmaTpcOrItsPr = 0.0; + if (cfgUseItsPID) { + partNsigmaTpcOrItsPi = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsKa = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsPr = itsResponse.nSigmaITS(candidate); + } else { + partNsigmaTpcOrItsPi = candidate.tpcNSigmaPi(); + partNsigmaTpcOrItsKa = candidate.tpcNSigmaKa(); + partNsigmaTpcOrItsPr = candidate.tpcNSigmaPr(); + } + if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC) { + if (!candidate.hasTOF() && std::abs(partNsigmaTpcOrItsPi) < cfgnSigmaCutTPC) { flag = 1; } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOF) { + if (candidate.hasTOF() && std::abs(partNsigmaTpcOrItsPi) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOF) { flag = 1; } } if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - const float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - const float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(std::pow(partNsigmaTpcOrItsPr, 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); + const float combNSigmaPi = std::sqrt(std::pow(partNsigmaTpcOrItsPi, 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(std::pow(partNsigmaTpcOrItsKa, 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); int flag2 = 0; if (combNSigmaPr < cfgnSigmaOtherParticles) @@ -622,8 +647,8 @@ struct V0ptHadPiKaProt { flag2 += 1; if (cfgUseNewSeperationPid) { - if (std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOFHigherPt) { - if (!(flag2 > 1) && std::abs(candidate.tpcNSigmaKa()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaSeperationCut && std::abs(candidate.tpcNSigmaPr()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPr()) > cfgnSigmaSeperationCut) + if (std::abs(partNsigmaTpcOrItsPi) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOFHigherPt) { + if (!(flag2 > 1) && std::abs(partNsigmaTpcOrItsKa) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaSeperationCut && std::abs(partNsigmaTpcOrItsPr) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPr()) > cfgnSigmaSeperationCut) flag = 1; } } else { @@ -654,18 +679,31 @@ struct V0ptHadPiKaProt { return false; int flag = 0; //! pid check main flag + float partNsigmaTpcOrItsPi = 0.0; + float partNsigmaTpcOrItsKa = 0.0; + float partNsigmaTpcOrItsPr = 0.0; + if (cfgUseItsPID) { + partNsigmaTpcOrItsPi = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsKa = itsResponse.nSigmaITS(candidate); + partNsigmaTpcOrItsPr = itsResponse.nSigmaITS(candidate); + } else { + partNsigmaTpcOrItsPi = candidate.tpcNSigmaPi(); + partNsigmaTpcOrItsKa = candidate.tpcNSigmaKa(); + partNsigmaTpcOrItsPr = candidate.tpcNSigmaPr(); + } + if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC) { + if (!candidate.hasTOF() && std::abs(partNsigmaTpcOrItsKa) < cfgnSigmaCutTPC) { flag = 1; } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOF) { + if (candidate.hasTOF() && std::abs(partNsigmaTpcOrItsKa) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOF) { flag = 1; } } if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - const float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - const float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); + const float combNSigmaPr = std::sqrt(std::pow(partNsigmaTpcOrItsPr, 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); + const float combNSigmaPi = std::sqrt(std::pow(partNsigmaTpcOrItsPi, 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(std::pow(partNsigmaTpcOrItsKa, 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); int flag2 = 0; if (combNSigmaPr < cfgnSigmaOtherParticles) @@ -676,8 +714,8 @@ struct V0ptHadPiKaProt { flag2 += 1; if (cfgUseNewSeperationPid) { - if (std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOFHigherPt) { - if (!(flag2 > 1) && std::abs(candidate.tpcNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(candidate.tpcNSigmaPr()) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPr()) > cfgnSigmaSeperationCut) + if (std::abs(partNsigmaTpcOrItsKa) < cfgnSigmaCutTPCHigherPt && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOFHigherPt) { + if (!(flag2 > 1) && std::abs(partNsigmaTpcOrItsPi) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaSeperationCut && std::abs(partNsigmaTpcOrItsPr) > cfgnSigmaSeperationCut && std::abs(candidate.tofNSigmaPr()) > cfgnSigmaSeperationCut) flag = 1; } } else { @@ -1335,16 +1373,21 @@ struct V0ptHadPiKaProt { double trkEta = track.eta(); double trkPhi = track.phi(); + double effweight = 1.0; + if (cfgLoadPtEffWeights) { + effweight = 1.0 / getEffAllCharged(track); // NUE weight + } + // inclusive charged particles if (track.sign() != 0) { if (trkEta < cfgCutEtaLeft) { fPtProfileHad->Fill(trkPt); - pTsumEtaLeftHad += trkPt; - nSumEtaLeftHad += 1.0; + pTsumEtaLeftHad += trkPt * effweight; + nSumEtaLeftHad += effweight; } if (trkEta > cfgCutEtaRight) { - pTsumEtaRightHad += trkPt; - nSumEtaRightHad += 1.0; + pTsumEtaRightHad += trkPt * effweight; + nSumEtaRightHad += effweight; } } @@ -1352,10 +1395,7 @@ struct V0ptHadPiKaProt { if (cfgLoadPhiWeights) { phiweight = getPhiWeight(track, coll.posZ()); // NUA weight } - double effweight = 1.0; - if (cfgLoadPtEffWeights) { - effweight = 1.0 / getEffAllCharged(track); // NUE weight - } + double weight = phiweight * effweight; if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { @@ -1433,34 +1473,34 @@ struct V0ptHadPiKaProt { histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), trkPt, nSigmaTpcProt, nSigmaTofProt); } + double effweightPion = 1.0; + double effweightKaon = 1.0; + double effweightProton = 1.0; + if (cfgLoadPtEffWeights) { + effweightPion = 1.0 / getEffPion(track); // NUE weight for pion + effweightKaon = 1.0 / getEffKaon(track); // NUE weight for kaon + effweightProton = 1.0 / getEffProton(track); // NUE weight for proton + } + if (track.sign() != 0) { if (trkPt < cfgCutPtUpperPID) { if (trkEta < cfgCutEtaLeft) { if (isPion) { - fPtProfilePi->Fill(trkPt); - nSumEtaLeftPi += 1.0; + fPtProfilePi->Fill(trkPt, effweightPion); + nSumEtaLeftPi += effweightPion; } if (isKaon) { - fPtProfileKa->Fill(trkPt); - nSumEtaLeftKa += 1.0; + fPtProfileKa->Fill(trkPt, effweightKaon); + nSumEtaLeftKa += effweightKaon; } if (isProton && trkPt > cfgCutPtLowerProt) { - fPtProfileProt->Fill(trkPt); - nSumEtaLeftProt += 1.0; + fPtProfileProt->Fill(trkPt, effweightProton); + nSumEtaLeftProt += effweightProton; } } } } - double effweightPion = 1.0; - double effweightKaon = 1.0; - double effweightProton = 1.0; - if (cfgLoadPtEffWeights) { - effweightPion = 1.0 / getEffPion(track); // NUE weight for pion - effweightKaon = 1.0 / getEffKaon(track); // NUE weight for kaon - effweightProton = 1.0 / getEffProton(track); // NUE weight for proton - } - // fill subevent B for ***identified particles'*** f(pT) in v02(pT) if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { if (std::abs(trkEta) < cfgCutEtaWindowB) { From b798a8925a33cbfac3a253b43816beacf66a043b Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Sat, 30 May 2026 00:47:16 +0530 Subject: [PATCH 348/449] Added PID ITS nsigma related histograms (#16462) --- .../Tasks/v0ptHadPiKaProt.cxx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index d1f455cfbad..a83f25f8e3b 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -354,7 +354,17 @@ struct V0ptHadPiKaProt { histos.add("h2DnsigmaPionTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH2F, {nSigmaAxis, nSigmaAxis}); histos.add("h2DnsigmaKaonTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH2F, {nSigmaAxis, nSigmaAxis}); histos.add("h2DnsigmaProtonTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionItsVsPtBeforeCut", "2D hist of nSigmaITS vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonItsVsPtBeforeCut", "2D hist of nSigmaITS vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonItsVsPtBeforeCut", "2D hist of nSigmaITS vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionItsVsTofBeforeCut", "2D hist of nSigmaITS vs. nSigmaTOF (pion)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonItsVsTofBeforeCut", "2D hist of nSigmaITS vs. nSigmaTOF (kaon)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonItsVsTofBeforeCut", "2D hist of nSigmaITS vs. nSigmaTOF (proton)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + // after cut + histos.add("h2DnsigmaPionItsVsPtAfterCut", "2D hist of nSigmaITS vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonItsVsPtAfterCut", "2D hist of nSigmaITS vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonItsVsPtAfterCut", "2D hist of nSigmaITS vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); histos.add("h2DnsigmaPionTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); histos.add("h2DnsigmaKaonTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); histos.add("h2DnsigmaProtonTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); @@ -364,6 +374,9 @@ struct V0ptHadPiKaProt { histos.add("h2DnsigmaPionTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); histos.add("h2DnsigmaKaonTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); histos.add("h2DnsigmaProtonTpcVsTofAfterCut", "3D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionItsVsTofAfterCut", "3D hist of nSigmaITS vs. nSigmaTOF (pion)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonItsVsTofAfterCut", "3D hist of nSigmaITS vs. nSigmaTOF (kaon)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonItsVsTofAfterCut", "3D hist of nSigmaITS vs. nSigmaTOF (proton)", kTH3F, {ptAxis, nSigmaAxis, nSigmaAxis}); // Analysis profiles @@ -1206,6 +1219,10 @@ struct V0ptHadPiKaProt { double nSigmaTofPi = track.tofNSigmaPi(); double nSigmaTofKa = track.tofNSigmaKa(); double nSigmaTofProt = track.tofNSigmaPr(); + double nSigmaItsPi = itsResponse.nSigmaITS(track); + double nSigmaItsKa = itsResponse.nSigmaITS(track); + double nSigmaItsProt = itsResponse.nSigmaITS(track); + histos.fill(HIST("h2DnsigmaPionTpcVsPtBeforeCut"), track.pt(), nSigmaTpcPi); histos.fill(HIST("h2DnsigmaKaonTpcVsPtBeforeCut"), track.pt(), nSigmaTpcKa); histos.fill(HIST("h2DnsigmaProtonTpcVsPtBeforeCut"), track.pt(), nSigmaTpcProt); @@ -1216,6 +1233,13 @@ struct V0ptHadPiKaProt { histos.fill(HIST("h2DnsigmaKaonTpcVsTofBeforeCut"), nSigmaTpcKa, nSigmaTofKa); histos.fill(HIST("h2DnsigmaProtonTpcVsTofBeforeCut"), nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaPionItsVsPtBeforeCut"), track.pt(), nSigmaItsPi); + histos.fill(HIST("h2DnsigmaKaonItsVsPtBeforeCut"), track.pt(), nSigmaItsKa); + histos.fill(HIST("h2DnsigmaProtonItsVsPtBeforeCut"), track.pt(), nSigmaItsProt); + histos.fill(HIST("h2DnsigmaPionItsVsTofBeforeCut"), track.pt(), nSigmaItsPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaKaonItsVsTofBeforeCut"), track.pt(), nSigmaItsKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaProtonItsVsTofBeforeCut"), track.pt(), nSigmaItsProt, nSigmaTofProt); + // identified particles selection bool isPion = false; bool isKaon = false; @@ -1240,16 +1264,22 @@ struct V0ptHadPiKaProt { histos.fill(HIST("h2DnsigmaPionTpcVsPtAfterCut"), track.pt(), nSigmaTpcPi); histos.fill(HIST("h2DnsigmaPionTofVsPtAfterCut"), track.pt(), nSigmaTofPi); histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), track.pt(), nSigmaTpcPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaPionItsVsPtAfterCut"), track.pt(), nSigmaItsPi); + histos.fill(HIST("h2DnsigmaPionItsVsTofAfterCut"), track.pt(), nSigmaItsPi, nSigmaTofPi); } if (isKaon) { histos.fill(HIST("h2DnsigmaKaonTpcVsPtAfterCut"), track.pt(), nSigmaTpcKa); histos.fill(HIST("h2DnsigmaKaonTofVsPtAfterCut"), track.pt(), nSigmaTofKa); histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), track.pt(), nSigmaTpcKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaKaonItsVsPtAfterCut"), track.pt(), nSigmaItsKa); + histos.fill(HIST("h2DnsigmaKaonItsVsTofAfterCut"), track.pt(), nSigmaItsKa, nSigmaTofKa); } if (isProton) { histos.fill(HIST("h2DnsigmaProtonTpcVsPtAfterCut"), track.pt(), nSigmaTpcProt); histos.fill(HIST("h2DnsigmaProtonTofVsPtAfterCut"), track.pt(), nSigmaTofProt); histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), track.pt(), nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaProtonItsVsPtAfterCut"), track.pt(), nSigmaItsProt); + histos.fill(HIST("h2DnsigmaProtonItsVsTofAfterCut"), track.pt(), nSigmaItsProt, nSigmaTofProt); } auto pdgcodeRec = std::abs(particle.pdgCode()); @@ -1427,6 +1457,9 @@ struct V0ptHadPiKaProt { double nSigmaTofPi = track.tofNSigmaPi(); double nSigmaTofKa = track.tofNSigmaKa(); double nSigmaTofProt = track.tofNSigmaPr(); + double nSigmaItsPi = itsResponse.nSigmaITS(track); + double nSigmaItsKa = itsResponse.nSigmaITS(track); + double nSigmaItsProt = itsResponse.nSigmaITS(track); histos.fill(HIST("h2DnsigmaPionTpcVsPtBeforeCut"), trkPt, nSigmaTpcPi); histos.fill(HIST("h2DnsigmaKaonTpcVsPtBeforeCut"), trkPt, nSigmaTpcKa); histos.fill(HIST("h2DnsigmaProtonTpcVsPtBeforeCut"), trkPt, nSigmaTpcProt); @@ -1437,6 +1470,13 @@ struct V0ptHadPiKaProt { histos.fill(HIST("h2DnsigmaKaonTpcVsTofBeforeCut"), nSigmaTpcKa, nSigmaTofKa); histos.fill(HIST("h2DnsigmaProtonTpcVsTofBeforeCut"), nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaPionItsVsPtBeforeCut"), trkPt, nSigmaItsPi); + histos.fill(HIST("h2DnsigmaKaonItsVsPtBeforeCut"), trkPt, nSigmaItsKa); + histos.fill(HIST("h2DnsigmaProtonItsVsPtBeforeCut"), trkPt, nSigmaItsProt); + histos.fill(HIST("h2DnsigmaPionItsVsTofBeforeCut"), trkPt, nSigmaItsPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaKaonItsVsTofBeforeCut"), trkPt, nSigmaItsKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaProtonItsVsTofBeforeCut"), trkPt, nSigmaItsProt, nSigmaTofProt); + // identified particles selection bool isPion = false; bool isKaon = false; @@ -1461,16 +1501,22 @@ struct V0ptHadPiKaProt { histos.fill(HIST("h2DnsigmaPionTpcVsPtAfterCut"), trkPt, nSigmaTpcPi); histos.fill(HIST("h2DnsigmaPionTofVsPtAfterCut"), trkPt, nSigmaTofPi); histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), trkPt, nSigmaTpcPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaPionItsVsPtAfterCut"), trkPt, nSigmaItsPi); + histos.fill(HIST("h2DnsigmaPionItsVsTofAfterCut"), trkPt, nSigmaItsPi, nSigmaTofPi); } if (isKaon) { histos.fill(HIST("h2DnsigmaKaonTpcVsPtAfterCut"), trkPt, nSigmaTpcKa); histos.fill(HIST("h2DnsigmaKaonTofVsPtAfterCut"), trkPt, nSigmaTofKa); histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), trkPt, nSigmaTpcKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaKaonItsVsPtAfterCut"), trkPt, nSigmaItsKa); + histos.fill(HIST("h2DnsigmaKaonItsVsTofAfterCut"), trkPt, nSigmaItsKa, nSigmaTofKa); } if (isProton) { histos.fill(HIST("h2DnsigmaProtonTpcVsPtAfterCut"), trkPt, nSigmaTpcProt); histos.fill(HIST("h2DnsigmaProtonTofVsPtAfterCut"), trkPt, nSigmaTofProt); histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), trkPt, nSigmaTpcProt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaProtonItsVsPtAfterCut"), trkPt, nSigmaItsProt); + histos.fill(HIST("h2DnsigmaProtonItsVsTofAfterCut"), trkPt, nSigmaItsProt, nSigmaTofProt); } double effweightPion = 1.0; From 3fdd867806ead1e308ac9cc9b14bad047f87dd48 Mon Sep 17 00:00:00 2001 From: nepeivodaRS <94179174+nepeivodaRS@users.noreply.github.com> Date: Fri, 29 May 2026 21:46:21 +0200 Subject: [PATCH 349/449] [PWGLF] cascades in pp: add RCT selection for gen. MC (#16463) --- .../Strangeness/cascqaanalysis.cxx | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index 8ec9142efc3..c71d74f9d9e 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -121,6 +121,7 @@ struct Cascqaanalysis { Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", 1, "TF border cut"}; Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", 1, "ITS ROF border cut"}; Configurable applyBcBorderCutsOnGen{"applyBcBorderCutsOnGen", false, "Apply enabled BC-level TF and ITS ROF border cuts on generated-level MC collisions"}; + Configurable applyRCTOnGen{"applyRCTOnGen", false, "Apply enabled BC-level RCT run-condition selection on generated-level MC collisions"}; Configurable isNoCollInTimeRangeNarrow{"isNoCollInTimeRangeNarrow", 1, "No collisions in +-2us window"}; Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; @@ -223,7 +224,7 @@ struct Cascqaanalysis { void init(InitContext const&) { TString hCandidateCounterLabels[4] = {"All candidates", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; - TString hNEventsMCLabels[7] = {"All", "z vrtx", "BC TF/ITS ROF border", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; + TString hNEventsMCLabels[8] = {"All", "z vrtx", "BC TF/ITS ROF border", "RCTFlagsChecker", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; TString hNEventsLabels[14] = {"All", "kIsTriggerTVX", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kIsVertexITSTPC", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "isVertexTOFmatched", "kNoCollInTimeRangeNarrow", "z vrtx", "RCTFlagsChecker", "INEL", "INEL>0", "INEL>1"}; registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{14, 0.f, 14.f}}}); @@ -241,7 +242,7 @@ struct Cascqaanalysis { // Rec. lvl registry.add("fakeEvents", "fakeEvents", {HistType::kTH1F, {{1, -0.5f, 0.5f}}}); // Gen. lvl - registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1D, {{7, 0.0f, 7.0f}}}); + registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1D, {{8, 0.0f, 8.0f}}}); for (int n = 1; n <= registry.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { registry.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); } @@ -295,7 +296,7 @@ struct Cascqaanalysis { setEventTypeAxisLabels(registry.get(HIST("hFT0MsignalPVContr"))->GetZaxis()); } - rctChecker.init(cfgEvtRCTFlagCheckerLabel, cfgEvtRCTFlagCheckerZDCCheck, cfgEvtRCTFlagCheckerLimitAcceptAsBad); + rctChecker.init(cfgEvtRCTFlagCheckerLabel, cfgEvtRCTFlagCheckerZDCCheck, cfgEvtRCTFlagCheckerLimitAcceptAsBad, requireRCTFlagChecker || applyRCTOnGen); if (cfgEvtRCTFlagCheckerFV0Check) { rctChecker.set(o2::aod::rctsel::kFV0Bad); } @@ -498,6 +499,12 @@ struct Cascqaanalysis { return true; } + template + bool acceptGeneratedEventRCT(TBC const& bc) + { + return !applyRCTOnGen || rctChecker(bc); + } + void processData(soa::Join::iterator const& collision, @@ -709,28 +716,33 @@ struct Cascqaanalysis { return; } registry.fill(HIST("hNEventsMC"), 1.5); - if (!acceptGeneratedEventBcBorderCuts(mcCollision.bc_as())) { + const auto bc = mcCollision.bc_as(); + if (!acceptGeneratedEventBcBorderCuts(bc)) { return; } - registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); registry.fill(HIST("hNEventsMC"), 2.5); + if (!acceptGeneratedEventRCT(bc)) { + return; + } + registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); + registry.fill(HIST("hNEventsMC"), 3.5); // Define the type of generated MC collision EventTypeBin evType = kINEL; uint8_t flagsGen = 0; flagsGen |= o2::aod::myMCcascades::EvFlags::EvINEL; - registry.fill(HIST("hNEventsMC"), 3.5); + registry.fill(HIST("hNEventsMC"), 4.5); // Generated collision is INEL>0 if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt0; evType = kINELgt0; - registry.fill(HIST("hNEventsMC"), 4.5); + registry.fill(HIST("hNEventsMC"), 5.5); } // Generated collision is INEL>1 if (pwglf::isINELgtNmc(mcParticles, 1, pdgDB)) { flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt1; evType = kINELgt1; - registry.fill(HIST("hNEventsMC"), 5.5); + registry.fill(HIST("hNEventsMC"), 6.5); } registry.fill(HIST("hCentFT0M_genMC"), mcCollision.centFT0M(), evType); @@ -805,7 +817,7 @@ struct Cascqaanalysis { uint8_t flagsAssoc = 0; if (evtReconstructedAndINEL) { flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINEL; - registry.fill(HIST("hNEventsMC"), 6.5); + registry.fill(HIST("hNEventsMC"), 7.5); } if (evtReconstructedAndINELgt0) { flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINELgt0; From 282a50673797a540bbfbdf6b72d10dc6da15f37f Mon Sep 17 00:00:00 2001 From: Deependra Sharma <38365215+deependra170598@users.noreply.github.com> Date: Sat, 30 May 2026 02:53:03 +0530 Subject: [PATCH 350/449] [PWGHF/D2H] fixing B mother of dstar particle in MC Rec process function (#16455) --- PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index 08492f1e7fb..bc4c27adbc7 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -534,11 +534,11 @@ struct HfTaskDstarToD0Pi { /// @tparam T1 type of the candidate table /// @tparam applyMl a boolean to apply ML or not /// @param candsMcRecSel reconstructed candidates with selection flag - /// @param rowsMcPartilces generated particles table + // /// @param rowsMcPartilces generated particles table template - void runMcRecTaskDstar(T1 const& candsMcRecSel, CandDstarMcGen const& rowsMcPartilces) + void runMcRecTaskDstar(T1 const& candsMcRecSel /*, CandDstarMcGen const& rowsMcPartilces*/) { - int8_t signDstar = 0; + // int8_t signDstar = 0; // MC at Reconstruction level for (const auto& candDstarMcRec : candsMcRecSel) { auto ptDstarRecSig = candDstarMcRec.pt(); @@ -551,10 +551,11 @@ struct HfTaskDstarToD0Pi { auto nPVContributors = collision.numContrib(); // number of PV contributors if (std::abs(candDstarMcRec.flagMcMatchRec()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { // if MC matching is successful at Reconstruction Level // get MC Mother particle - auto prong0 = candDstarMcRec.template prong0_as(); - auto indexMother = RecoDecay::getMother(rowsMcPartilces, prong0.template mcParticle_as(), o2::constants::physics::Pdg::kDStar, true, &signDstar, 2); - auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? - auto ptMother = particleMother.pt(); + // auto prong0 = candDstarMcRec.template prong0_as(); + // auto indexMother = RecoDecay::getMother(rowsMcPartilces, prong0.template mcParticle_as(), o2::constants::physics::Pdg::kDStar, true, &signDstar, 2); + // auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? + // auto ptMother = particleMother.pt(); + auto ptMother = candDstarMcRec.ptBhadMotherPart(); int const pdgBhadMother = candDstarMcRec.pdgBhadMotherPart(); // For unknown reasons there are charm hadrons coming directly from beauty diquarks without an intermediate B-hadron which have an unreasonable correlation between the pT of the charm hadron and the beauty mother. We also remove charm hadrons from quarkonia. if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt && (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 557)) { // o2-linter: disable=pdg/explicit-code, magic-number (constants not in the PDG header) @@ -876,7 +877,7 @@ struct HfTaskDstarToD0Pi { aod::TracksWMc const&) { rowsSelectedCandDstarMcRec.bindExternalIndices(&collisions); - runMcRecTaskDstar>(rowsSelectedCandDstarMcRec, rowsMcPartilces); + runMcRecTaskDstar>(rowsSelectedCandDstarMcRec /*, rowsMcPartilces*/); runMcGenTaskDstar(collisions, rowsMcPartilces); } PROCESS_SWITCH(HfTaskDstarToD0Pi, processMcWoMl, "Process MC Data without ML", false); @@ -887,7 +888,7 @@ struct HfTaskDstarToD0Pi { aod::TracksWMc const&) { rowsSelectedCandDstarMcRecWMl.bindExternalIndices(&collisions); - runMcRecTaskDstar>(rowsSelectedCandDstarMcRecWMl, rowsMcPartilces); + runMcRecTaskDstar>(rowsSelectedCandDstarMcRecWMl /*, rowsMcPartilces*/); runMcGenTaskDstar(collisions, rowsMcPartilces); } PROCESS_SWITCH(HfTaskDstarToD0Pi, processMcWML, "Process MC Data with ML", false); From eb828a35c587d8cfbe5946ef2516e1fd4835dccc Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Sat, 30 May 2026 01:19:09 +0200 Subject: [PATCH 351/449] [PWGCF] Remove dynamic columns and checks of reassociated MFT tracks (#16464) --- .../DataModel/LongRangeDerived.h | 233 ++++-------------- .../TableProducer/longrangeMaker.cxx | 202 +++++++++------ .../Tasks/longrangecorrDerived.cxx | 27 +- 3 files changed, 184 insertions(+), 278 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index de216b6727a..af4916671da 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -142,90 +142,10 @@ using LRZdc = LRZdcs::iterator; namespace lrcorrtrktable { - -template -inline typename binningType::binned_t packInTable(const float& valueToBin) -{ - if (valueToBin <= binningType::binned_min) { - return binningType::underflowBin; - } else if (valueToBin >= binningType::binned_max) { - return binningType::overflowBin; - } else { - return static_cast((valueToBin - binningType::binned_min) / binningType::bin_width); - } -} - -template -inline float unPack(const typename binningType::binned_t& b) -{ - return binningType::bin_width * b + binningType::binned_min; -} - -template -inline typename binningType::binned_t packSymmetric(const float& valueToBin) -{ - if (valueToBin <= binningType::binned_min) { - return (binningType::underflowBin); - } else if (valueToBin >= binningType::binned_max) { - return (binningType::overflowBin); - } else if (valueToBin >= 0) { - return (static_cast((valueToBin * binningType::inv_bin_width) + 0.5f)); - } else { - return (static_cast((valueToBin * binningType::inv_bin_width) - 0.5f)); - } -} - -template -inline float unPackSymmetric(const typename binningType::binned_t& b) -{ - return binningType::bin_width * static_cast(b); -} - -namespace binning -{ - -template lim, typename binVariable = int8_t> -struct binningParent { - public: - typedef binVariable binned_t; - - // Reserve two bins: one for overflow and one for underflow - static constexpr int nbins = (1 << (8 * sizeof(binned_t))) - 2; - static constexpr binned_t overflowBin = nbins; - static constexpr binned_t underflowBin = -1; - static constexpr float binned_min = lim.first; - static constexpr float binned_max = lim.second; - static constexpr float binned_center = 0.5 * (binned_min + binned_max); - static constexpr float bin_width = (binned_max - binned_min) / static_cast(nbins); - static constexpr float inv_bin_width = 1. / bin_width; - static_assert(binned_min < binned_max, "Invalid binning range"); - static void print() - { - LOG(info) << "Binning: " << binned_min << " - " << binned_max << " with " << nbins << " bins, width = " - << bin_width << ". Overflow bin " << static_cast(overflowBin) << " Underflow bin " << static_cast(underflowBin); - } -}; - -using trkdca_v0 = binningParent(-2.0f, 2.0f), int8_t>; -using trkphi_v0 = binningParent(0.0f, o2::constants::math::TwoPI), uint16_t>; -using trkamp_v0 = binningParent(0.0f, 5000.0f), uint16_t>; -using trkpt_v0 = binningParent(0.0f, 10.0f), uint8_t>; -using trketa_v0 = binningParent(-5.0f, 5.0f), int16_t>; -using trkchi2_v0 = binningParent(0.0f, 10.0f), int8_t>; - -using trkdca = trkdca_v0; -using trkchi2 = trkchi2_v0; -using trkpt = trkpt_v0; -using trketa = trketa_v0; -using trkphi = trkphi_v0; -using trkamp = trkamp_v0; - -} // namespace binning - DECLARE_SOA_INDEX_COLUMN(LRCollision, lrCollision); DECLARE_SOA_INDEX_COLUMN(UpcLRCollision, upcLRCollision); DECLARE_SOA_COLUMN(ChannelID, channelID, uint8_t); -DECLARE_SOA_COLUMN(AmplitudeStore, amplitudeStore, binning::trkamp::binned_t); +DECLARE_SOA_COLUMN(Amplitude, amplitude, float); DECLARE_SOA_COLUMN(InvMass, invMass, float); DECLARE_SOA_COLUMN(IdPos, idPos, int64_t); DECLARE_SOA_COLUMN(IdNeg, idNeg, int64_t); @@ -234,29 +154,12 @@ DECLARE_SOA_COLUMN(V0Type, v0Type, uint8_t); DECLARE_SOA_COLUMN(AmbDegree, ambDegree, uint8_t); DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); -DECLARE_SOA_COLUMN(TPCChi2NClStore, tpcChi2NClStore, binning::trkchi2::binned_t); //! Stored binned chi2 -DECLARE_SOA_COLUMN(DCAzStore, dcazStore, binning::trkdca::binned_t); //! Stored binned dcaz -DECLARE_SOA_COLUMN(BestDCAxyStore, bestdcaxyStore, binning::trkdca::binned_t); //! Stored binned best dcaxy -DECLARE_SOA_COLUMN(BestDCAzStore, bestdcazStore, binning::trkdca::binned_t); //! Stored binned best dcaz -DECLARE_SOA_COLUMN(PtStore, ptStore, binning::trkpt::binned_t); //! Stored binned pt -DECLARE_SOA_COLUMN(EtaStore, etaStore, binning::trketa::binned_t); //! Stored binned eta -DECLARE_SOA_COLUMN(PhiStore, phiStore, binning::trkphi::binned_t); //! Stored binned phi -DECLARE_SOA_DYNAMIC_COLUMN(TPCChi2NCl, tpcChi2NCl, - [](binning::trkchi2::binned_t chi2_binned) -> float { return unPack(chi2_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(DCAz, dcaZ, - [](binning::trkdca::binned_t dcaz_binned) -> float { return unPackSymmetric(dcaz_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, - [](binning::trkpt::binned_t pt_binned) -> float { return unPack(pt_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, - [](binning::trketa::binned_t eta_binned) -> float { return unPackSymmetric(eta_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, - [](binning::trkphi::binned_t phi_binned) -> float { return unPackSymmetric(phi_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(BestDCAXY, bestDCAXY, - [](binning::trkdca::binned_t bestdcaxy_binned) -> float { return unPackSymmetric(bestdcaxy_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(BestDCAZ, bestDCAZ, - [](binning::trkdca::binned_t bestdcaz_binned) -> float { return unPackSymmetric(bestdcaz_binned); }); -DECLARE_SOA_DYNAMIC_COLUMN(Amplitude, amplitude, - [](binning::trkamp::binned_t amp_binned) -> float { return unPack(amp_binned); }); +DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, float); +DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); + enum TrackPid { kSpCharge, kSpPion, @@ -276,41 +179,30 @@ DECLARE_SOA_TABLE(LRMidTracks, "AOD", "LRMIDTRACK", lrcorrtrktable::LRCollisionId, lrcorrtrktable::TPCNClsFound, lrcorrtrktable::TPCNClsCrossedRows, - lrcorrtrktable::TPCChi2NClStore, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::DCAzStore, - lrcorrtrktable::TrackType, - lrcorrtrktable::TPCChi2NCl, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, - lrcorrtrktable::DCAz); + lrcorrtrktable::TPCChi2NCl, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, + lrcorrtrktable::DcaZ, + lrcorrtrktable::TrackType); using LRMidTrack = LRMidTracks::iterator; DECLARE_SOA_TABLE(LRFt0aTracks, "AOD", "LRFT0ATRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::AmplitudeStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::Amplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRFt0aTrack = LRFt0aTracks::iterator; DECLARE_SOA_TABLE(LRFt0cTracks, "AOD", "LRFT0CTRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::AmplitudeStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::Amplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using LRFt0cTrack = LRFt0cTracks::iterator; DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", @@ -318,31 +210,23 @@ DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", lrcorrtrktable::LRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, lrcorrtrktable::InvMass, - lrcorrtrktable::V0Type, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::V0Type); using LRV0Track = LRV0Tracks::iterator; DECLARE_SOA_TABLE(LRMftTracks, "AOD", "LRMFTTRACK", o2::soa::Index<>, lrcorrtrktable::LRCollisionId, lrcorrtrktable::AmbDegree, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, fwdtrack::NClusters, - lrcorrtrktable::BestDCAxyStore, - lrcorrtrktable::BestDCAzStore, - lrcorrtrktable::BestDCAXY, - lrcorrtrktable::BestDCAZ, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + fwdtrack::BestDCAXY, + fwdtrack::BestDCAZ); using LRMftTrack = LRMftTracks::iterator; DECLARE_SOA_TABLE(UpcLRMidTracks, "AOD", "UPCLRMIDTRACK", @@ -350,41 +234,30 @@ DECLARE_SOA_TABLE(UpcLRMidTracks, "AOD", "UPCLRMIDTRACK", lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::TPCNClsFound, lrcorrtrktable::TPCNClsCrossedRows, - lrcorrtrktable::TPCChi2NClStore, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::DCAzStore, - lrcorrtrktable::TrackType, - lrcorrtrktable::TPCChi2NCl, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi, - lrcorrtrktable::DCAz); + lrcorrtrktable::TPCChi2NCl, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, + lrcorrtrktable::DcaZ, + lrcorrtrktable::TrackType); using UpcLRMidTrack = UpcLRMidTracks::iterator; DECLARE_SOA_TABLE(UpcLRFt0aTracks, "AOD", "UPCLRFT0ATRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::AmplitudeStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::Amplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRFt0aTrack = UpcLRFt0aTracks::iterator; DECLARE_SOA_TABLE(UpcLRFt0cTracks, "AOD", "UPCLRFT0CTRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, - lrcorrtrktable::AmplitudeStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, - lrcorrtrktable::Amplitude, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::Amplitude, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi); using UpcLRFt0cTrack = UpcLRFt0cTracks::iterator; DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", @@ -392,31 +265,23 @@ DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, lrcorrtrktable::InvMass, - lrcorrtrktable::V0Type, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + lrcorrtrktable::V0Type); using UpcLRV0Track = UpcLRV0Tracks::iterator; DECLARE_SOA_TABLE(UpcLRMftTracks, "AOD", "UPCLRMFTTRACK", o2::soa::Index<>, lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::AmbDegree, - lrcorrtrktable::PtStore, - lrcorrtrktable::EtaStore, - lrcorrtrktable::PhiStore, + lrcorrtrktable::Pt, + lrcorrtrktable::Eta, + lrcorrtrktable::Phi, fwdtrack::NClusters, - lrcorrtrktable::BestDCAxyStore, - lrcorrtrktable::BestDCAzStore, - lrcorrtrktable::BestDCAXY, - lrcorrtrktable::BestDCAZ, - lrcorrtrktable::Pt, - lrcorrtrktable::Eta, - lrcorrtrktable::Phi); + fwdtrack::BestDCAXY, + fwdtrack::BestDCAZ); using UpcLRMftTrack = UpcLRMftTracks::iterator; } // namespace o2::aod diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 79a9465064c..61d404d5890 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -198,6 +198,7 @@ struct LongrangeMaker { ConfigurableAxis axisSpecies = {"axisSpecies", {4, 0.5, 4.5}, "Species axis"}; ConfigurableAxis axisAmplitude{"axisAmplitude", {5000, 0, 10000}, "FT0 amplitude"}; ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; + ConfigurableAxis axisMFTAmbDegree{"axisMFTAmbDegree", {50, -0.5, 49.5}, "Track Ambiguity axis"}; } cfgAxis; Configurable> itsNsigmaPidCut{"itsNsigmaPidCut", std::vector{3, 2.5, 2, -3, -2.5, -2}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; @@ -276,6 +277,9 @@ struct LongrangeMaker { xMftBestTrk->SetBinLabel(4, "DCAxy selection"); xMftBestTrk->SetBinLabel(5, "DCAz selection"); + histos.add("ReassignedMFTtrackAmbDegree", "ReassignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + histos.add("AssignedMFTtrackAmbDegree", "AssignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + histos.add("FT0A_Amp", "FT0A_Amp", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0A_Amp_gaincorrected", "FT0A_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0A_Channel_vs_Amp", "FT0A_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); @@ -393,22 +397,22 @@ struct LongrangeMaker { lrmidtracks(lrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), aod::lrcorrtrktable::kSpCharge); if (pid != aod::lrcorrtrktable::kSpCharge) { lrmidtracks(lrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), pid); } } @@ -433,11 +437,14 @@ struct LongrangeMaker { if (cfgfittrksel.cfgVerbosity > 0) { LOGF(info, "FT0A info: Channel = %d | indexchannel = %d | %f | %f", chanelid, iCh, ft0gainvalues[chanelid], ft0gainvalues[iCh]); } + if (eta > cfgfittrksel.cfgFt0aEtaMax || eta < cfgfittrksel.cfgFt0aEtaMin) { + continue; + } lrft0atracks(lrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(gainampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + gainampl, + eta, + phi); histos.fill(HIST("FT0A_Amp"), ampl); histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); @@ -452,11 +459,14 @@ struct LongrangeMaker { if (cfgfittrksel.cfgVerbosity > 0) { LOGF(info, "FT0C info: Channel = %d | indexchannel = %d | %f | %f", chanelid, iCh, ft0gainvalues[chanelid], ft0gainvalues[iCh]); } + if (eta > cfgfittrksel.cfgFt0cEtaMax || eta < cfgfittrksel.cfgFt0cEtaMin) { + continue; + } lrft0ctracks(lrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(gainampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + gainampl, + eta, + phi); histos.fill(HIST("FT0C_Amp"), ampl); histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); @@ -473,15 +483,21 @@ struct LongrangeMaker { continue; } auto phi = itrack.phi(); + if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } + if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } o2::math_utils::bringTo02Pi(phi); lrmfttracks(lrcollision.lastIndex(), reassoMftTrack.ambDegree(), - aod::lrcorrtrktable::packInTable(itrack.pt()), - aod::lrcorrtrktable::packSymmetric(itrack.eta()), - aod::lrcorrtrktable::packSymmetric(phi), + itrack.pt(), + itrack.eta(), + phi, itrack.nClusters(), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); + reassoMftTrack.bestDCAXY(), + reassoMftTrack.bestDCAZ()); } // v0 loop @@ -498,9 +514,9 @@ struct LongrangeMaker { lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); } @@ -515,9 +531,9 @@ struct LongrangeMaker { lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); } @@ -526,9 +542,9 @@ struct LongrangeMaker { lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing @@ -586,22 +602,22 @@ struct LongrangeMaker { upclrmidtracks(upclrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), aod::lrcorrtrktable::kSpCharge); if (pid != aod::lrcorrtrktable::kSpCharge) { upclrmidtracks(upclrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), pid); } } @@ -614,22 +630,28 @@ struct LongrangeMaker { float ampl = ft0.amplitudeA()[iCh]; auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); + if (eta > cfgfittrksel.cfgFt0aEtaMax || eta < cfgfittrksel.cfgFt0aEtaMin) { + continue; + } upclrft0atracks(upclrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(ampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + ampl, + eta, + phi); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh] + KminFt0cCell; float ampl = ft0.amplitudeC()[iCh]; auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); + if (eta > cfgfittrksel.cfgFt0cEtaMax || eta < cfgfittrksel.cfgFt0cEtaMin) { + continue; + } upclrft0ctracks(upclrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(ampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + ampl, + eta, + phi); } } @@ -642,14 +664,20 @@ struct LongrangeMaker { } auto phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); + if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } + if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } upclrmfttracks(upclrcollision.lastIndex(), reassoMftTrack.ambDegree(), - aod::lrcorrtrktable::packInTable(itrack.pt()), - aod::lrcorrtrktable::packSymmetric(itrack.eta()), - aod::lrcorrtrktable::packSymmetric(phi), + itrack.pt(), + itrack.eta(), + phi, itrack.nClusters(), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); + reassoMftTrack.bestDCAXY(), + reassoMftTrack.bestDCAZ()); } // v0 loop @@ -666,9 +694,9 @@ struct LongrangeMaker { upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); } @@ -683,9 +711,9 @@ struct LongrangeMaker { upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); } @@ -694,9 +722,9 @@ struct LongrangeMaker { upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - aod::lrcorrtrktable::packInTable(v0.pt()), - aod::lrcorrtrktable::packSymmetric(v0.eta()), - aod::lrcorrtrktable::packSymmetric(v0.phi()), + v0.pt(), + v0.eta(), + v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing @@ -768,22 +796,22 @@ struct LongrangeMaker { lrmidtracks(lrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), aod::lrcorrtrktable::kSpCharge); if (pid != aod::lrcorrtrktable::kSpCharge) { lrmidtracks(lrcollision.lastIndex(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - aod::lrcorrtrktable::packInTable(track.tpcChi2NCl()), - aod::lrcorrtrktable::packInTable(track.pt()), - aod::lrcorrtrktable::packSymmetric(track.eta()), - aod::lrcorrtrktable::packSymmetric(track.phi()), - aod::lrcorrtrktable::packSymmetric(track.dcaZ()), + track.tpcChi2NCl(), + track.pt(), + track.eta(), + track.phi(), + track.dcaZ(), pid); } } @@ -797,11 +825,14 @@ struct LongrangeMaker { auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); auto gainampl = ampl / ft0gainvalues[chanelid]; + if (eta > cfgfittrksel.cfgFt0aEtaMax || eta < cfgfittrksel.cfgFt0aEtaMin) { + continue; + } lrft0atracks(lrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(gainampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + gainampl, + eta, + phi); histos.fill(HIST("FT0A_Amp"), ampl); histos.fill(HIST("FT0A_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0A_Amp_gaincorrected"), gainampl); @@ -813,11 +844,14 @@ struct LongrangeMaker { auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); auto gainampl = ampl / ft0gainvalues[chanelid]; + if (eta > cfgfittrksel.cfgFt0cEtaMax || eta < cfgfittrksel.cfgFt0cEtaMin) { + continue; + } lrft0ctracks(lrcollision.lastIndex(), chanelid, - aod::lrcorrtrktable::packInTable(gainampl), - aod::lrcorrtrktable::packSymmetric(eta), - aod::lrcorrtrktable::packSymmetric(phi)); + gainampl, + eta, + phi); histos.fill(HIST("FT0C_Amp"), ampl); histos.fill(HIST("FT0C_Channel_vs_Amp"), chanelid, ampl); histos.fill(HIST("FT0C_Amp_gaincorrected"), gainampl); @@ -835,14 +869,20 @@ struct LongrangeMaker { } auto phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); + if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } + if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { + histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); + } lrmfttracks(lrcollision.lastIndex(), reassoMftTrack.ambDegree(), - aod::lrcorrtrktable::packInTable(itrack.pt()), - aod::lrcorrtrktable::packSymmetric(itrack.eta()), - aod::lrcorrtrktable::packSymmetric(phi), + itrack.pt(), + itrack.eta(), + phi, itrack.nClusters(), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAXY()), - aod::lrcorrtrktable::packSymmetric(reassoMftTrack.bestDCAZ())); + reassoMftTrack.bestDCAXY(), + reassoMftTrack.bestDCAZ()); } for (const auto& particle : mcparticles) { diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index f387acbbd2b..866fcdeba90 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -57,6 +59,7 @@ struct LongrangecorrDerived { struct : ConfigurableGroup { Configurable cfgNmixedevent{"cfgNmixedevent", 5, "how many events are mixed"}; + Configurable cfgSampleSize{"cfgSampleSize", 10, "Sample size for bootstrapping"}; Configurable cfgPidMask{"cfgPidMask", 0, "Selection bitmask for the TPC particle"}; Configurable cfgV0Mask{"cfgV0Mask", 0, "Selection bitmask for the V0 particle"}; Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; @@ -80,7 +83,6 @@ struct LongrangecorrDerived { ConfigurableAxis axisPhi{"axisPhi", {96, 0, TwoPI}, "#phi axis"}; ConfigurableAxis axisEtaTrig{"axisEtaTrig", {40, -1., 1.}, "#eta trig axis"}; ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; - ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt assoc axis for histograms"}; ConfigurableAxis axisVtxZ{"axisVtxZ", {40, -20, 20}, "vertex axis"}; ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {96, 3.5, 4.9}, "#eta assoc axis"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; @@ -91,6 +93,7 @@ struct LongrangecorrDerived { ConfigurableAxis axisChannel{"axisChannel", {208, 0, 208}, "FT0 channel"}; ConfigurableAxis axisMultME{"axisMultME", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 1000}, "Mixing bins - multiplicity"}; ConfigurableAxis axisVtxZME{"axisVtxZME", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis axisSample{"axisSample", {10, 0, 10}, "sample axis for histograms"}; ConfigurableAxis axisTPCNClsFound{"axisTPCNClsFound", {200, -0.5, 199.5}, "TPC Cluster axis"}; ConfigurableAxis axisTPCNClsCrossedRows{"axisTPCNClsCrossedRows", {200, -0.5, 199.5}, "TPC NCrossedRow axis"}; @@ -155,10 +158,10 @@ struct LongrangecorrDerived { void init(InitContext const&) { - std::vector corrAxis = {{cfgAxis.axisVtxZ, "z-vtx (cm)"}, + std::vector corrAxis = {{cfgAxis.axisSample, "Sample"}, + {cfgAxis.axisVtxZ, "z-vtx (cm)"}, {cfgAxis.axisMultiplicity, "multiplicity"}, {cfgAxis.axisPtTrigger, "p_{T} (GeV/c)"}, - {cfgAxis.axisPtAssoc, "p_{T} (GeV/c)"}, {cfgAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, {cfgAxis.axisDeltaEta, "#Delta#eta"}}; std::vector effAxis = {{cfgAxis.axisVertexEfficiency, "z-vtx (cm)"}, @@ -182,14 +185,13 @@ struct LongrangecorrDerived { histos.add("Trig_etavsphi", "Trig_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaTrig}); histos.add("Trig_pt", "Trig_pt", kTH1D, {cfgAxis.axisPtTrigger}); histos.add("Trig_invMass", "Trig_invMass", kTH1D, {cfgAxis.axisInvMassQA}); - histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {cfgAxis.axisVtxZ, cfgAxis.axisMultiplicity, cfgAxis.axisPtTrigger, cfgAxis.axisInvMass}); + histos.add("Trig_hist", "Trig_hist", kTHnSparseF, {cfgAxis.axisSample, cfgAxis.axisVtxZ, cfgAxis.axisMultiplicity, cfgAxis.axisPtTrigger, cfgAxis.axisInvMass}); histos.add("Trig_amp", "Trig_amp", kTH1D, {cfgAxis.axisAmplitude}); histos.add("Channel_vs_Trig_amp", "Channel_vs_Trig_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); histos.add("Assoc_eta", "Assoc_eta", kTH1D, {cfgAxis.axisEtaAssoc}); histos.add("Assoc_phi", "Assoc_phi", kTH1D, {cfgAxis.axisPhi}); histos.add("Assoc_etavsphi", "Assoc_etavsphi", kTH2D, {cfgAxis.axisPhi, cfgAxis.axisEtaAssoc}); - histos.add("Assoc_pt", "Assoc_pt", kTH1D, {cfgAxis.axisPtAssoc}); histos.add("Assoc_amp", "Assoc_amp", kTH1D, {cfgAxis.axisAmplitude}); histos.add("Channel_vs_Assoc_amp", "Channel_vs_Assoc_amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); @@ -285,8 +287,6 @@ struct LongrangecorrDerived { if constexpr (requires { track.channelID(); }) { histos.fill(HIST("Assoc_amp"), track.amplitude()); histos.fill(HIST("Channel_vs_Assoc_amp"), track.channelID(), track.amplitude()); - } else { - histos.fill(HIST("Assoc_pt"), track.pt()); } if constexpr (requires { track.nClusters(); }) { histos.fill(HIST("MFTNClusters"), track.nClusters()); @@ -317,6 +317,7 @@ struct LongrangecorrDerived { template void fillCorrHist(TTarget target, TTriggers const& triggers, TAssocs const& assocs, bool mixing, float vz, float multiplicity, float eventWeight) { + int fSampleIndex = gRandom->Uniform(0, cfgSel.cfgSampleSize); for (auto const& triggerTrack : triggers) { auto trigAmpl = 1.0f; if constexpr (requires { triggerTrack.channelID(); }) { @@ -338,11 +339,11 @@ struct LongrangecorrDerived { if (!mixing) { fillTrigTrackQA(triggerTrack); if constexpr (requires { triggerTrack.channelID(); }) { - histos.fill(HIST("Trig_hist"), vz, multiplicity, 1.0, 1.0, eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, 1.0, 1.0, eventWeight * trigAmpl); } else if constexpr (requires { triggerTrack.invMass(); }) { - histos.fill(HIST("Trig_hist"), vz, multiplicity, triggerTrack.pt(), triggerTrack.invMass(), eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), triggerTrack.invMass(), eventWeight * trigAmpl); } else { - histos.fill(HIST("Trig_hist"), vz, multiplicity, triggerTrack.pt(), 1.0, eventWeight * trigAmpl); + histos.fill(HIST("Trig_hist"), fSampleIndex, vz, multiplicity, triggerTrack.pt(), 1.0, eventWeight * trigAmpl); } } for (auto const& assoTrack : assocs) { @@ -365,11 +366,11 @@ struct LongrangecorrDerived { histos.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * trigAmpl * assoAmpl); } if constexpr (requires { triggerTrack.channelID(); }) { - target->getPairHist()->Fill(step, vz, multiplicity, 1.0, 1.0, deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, 1.0, deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); } else if constexpr (requires { triggerTrack.invMass(); }) { - target->getPairHist()->Fill(step, vz, multiplicity, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta, triggerTrack.invMass(), eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, triggerTrack.invMass(), eventWeight * trigAmpl * assoAmpl); } else { - target->getPairHist()->Fill(step, vz, multiplicity, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); + target->getPairHist()->Fill(step, fSampleIndex, vz, multiplicity, triggerTrack.pt(), deltaPhi, deltaEta, 1.0, eventWeight * trigAmpl * assoAmpl); } } // associated tracks } // trigger tracks From 8f9f6ce0de4703d4c0bf2e2095874c1966b2fee6 Mon Sep 17 00:00:00 2001 From: Fernanda Torres <135931275+mtorresc15@users.noreply.github.com> Date: Fri, 29 May 2026 23:56:43 -0600 Subject: [PATCH 352/449] [PWGHF] Set cascade PDG codes in Xic0/Omegac0 candidate creator (#16460) --- PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index ecf43e86a6d..394d9628e4c 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -832,7 +832,7 @@ struct HfCandidateCreatorXic0Omegac0 { KFParticle const kfNegKa(kfTrackBach, kKMinus); KFParticle const kfNegPiRej(kfTrackBach, kPiMinus); // rej KFParticle const kfPosPi(kfTrack0, kPiPlus); - KFParticle const kfNegPr(kfTrack1, kProton); + KFParticle const kfNegPr(kfTrack1, kProtonBar); KFParticle const kfPosKa(kfTrackBach, kKPlus); KFParticle const kfPosPiRej(kfTrackBach, kPiPlus); // rej @@ -890,6 +890,8 @@ struct HfCandidateCreatorXic0Omegac0 { // construct cascade KFParticle kfOmega; KFParticle kfOmegarej; // rej + kfOmega.SetPDG(bachCharge < 0 ? kOmegaMinus : kOmegaPlusBar); + kfOmegarej.SetPDG(bachCharge < 0 ? kOmegaMinus : kOmegaPlusBar); kfOmega.SetConstructMethod(kfConstructMethod); kfOmegarej.SetConstructMethod(kfConstructMethod); // rej try { @@ -1325,7 +1327,7 @@ struct HfCandidateCreatorXic0Omegac0 { KFParticle const kfNegPi(kfTrack1, kPiMinus); KFParticle const kfNegBachPi(kfTrackBach, kPiMinus); KFParticle const kfPosPi(kfTrack0, kPiPlus); - KFParticle const kfNegPr(kfTrack1, kProton); + KFParticle const kfNegPr(kfTrack1, kProtonBar); KFParticle const kfPosBachPi(kfTrackBach, kPiPlus); KFParticle kfBachPion; @@ -1383,6 +1385,7 @@ struct HfCandidateCreatorXic0Omegac0 { const KFParticle* xiDaugthers[2] = {&kfBachPion, &kfV0}; // construct cascade KFParticle kfXi; + kfXi.SetPDG(bachCharge < 0 ? kXiMinus : kXiPlusBar); kfXi.SetConstructMethod(kfConstructMethod); try { kfXi.Construct(xiDaugthers, 2); From 239dbcf01cf22f318676379c0cc4059baccbce2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Sat, 30 May 2026 09:58:25 +0200 Subject: [PATCH 353/449] [ALICE3] Implement basic bremsstrahlung model in OTF tracker (#16417) --- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 85 ++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 0ba1c3e57e0..0a91840c819 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -193,6 +193,9 @@ struct OnTheFlyTracker { ConfigurableAxis axisRadius{"axisRadius", {2500, 0.0f, +250.0f}, "R (cm)"}; ConfigurableAxis axisZ{"axisZ", {100, -250.0f, +250.0f}, "Z (cm)"}; + + ConfigurableAxis axisNphotons{"axisNphotons", {10, 0.5f, 10.5f}, "N_{#gamma}"}; + ConfigurableAxis axisBRenergyLoss{"axisBRenergyLoss", {500, 0.0f, 1.0f}, "#Delta p / p"}; } axes; // for topo var QA @@ -246,6 +249,15 @@ struct OnTheFlyTracker { Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; } cfgFitter; + struct : ConfigurableGroup { + std::string prefix = "cfgBR"; // configuration for bremsstrahlung + Configurable radiateBR{"radiateBR", false, "simulate bremsstrahlung"}; + Configurable doBRQA{"doBRQA", false, "Do QA for bremsstrahlung"}; + Configurable minBREnergyFraction{"minEnergyFraction", 0.001f, "Minimum energy fraction a bremsstrahlung photon can carry"}; + Configurable maxBREnergyFraction{"maxEnergyFraction", 0.95f, "Maximum energy fraction a bremsstrahlung photon can carry"}; + Configurable radiationStrength{"radiationStrength", 1e-6f, "Strenght of the bremsstrahlung radiation"}; + } brSettings; + using PVertex = o2::dataformats::PrimaryVertex; // for secondary vertex finding @@ -568,6 +580,14 @@ struct OnTheFlyTracker { insertHist(histPath + "h2dDCAz", "h2dDCAz;p_{T};DCA_{z}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); } + if (brSettings.doBRQA) { + insertHist(histPath + "h1dNBRPhotons", "h1dNBRPhotons;N_{#gamma};Counts", {kTH1D, {{axes.axisNphotons}}}); + insertHist(histPath + "h1dBREnergyLoss", "h1dBREnergyLoss;#Delta p / p;Counts", {kTH1D, {{axes.axisBRenergyLoss}}}); + + insertHist(histPath + "h2dBRPtRes", "h2dPtRes;Gen p_{T};#Delta p_{T} / Reco p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); + insertHist(histPath + "h2dBRPtResAbs", "h2dPtResAbs;Gen p_{T};#Delta p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); + } + } // end config loop // Basic QA @@ -1749,6 +1769,67 @@ struct OnTheFlyTracker { } } + /// Function to compute the bremsstrahlung loss of charged-particles for each layer of the current configuration + /// \param icfg index of the current configuration + /// \param mcParticle true MC particle to identify particle and get the energy + /// \param trackParCov track of the particle to compute bremsstrahlung for + void computeBremsstrahlungLoss(const int icfg, const auto& mcParticle, o2::track::TrackParCov& trackParCov) + { + if (brSettings.radiateBR) { + const o2::fastsim::GeometryEntry geoEntry = mGeoContainer.getEntry(icfg); + + for (auto const& layerName : geoEntry.getLayerNames()) { + if (layerName.find("global") != std::string::npos) { // Layers with global tag are skipped + continue; + } + + float mass = o2::constants::physics::MassElectron; + + switch (std::abs(mcParticle.pdgCode())) { + case kElectron: + mass = o2::constants::physics::MassElectron; + break; + case kMuonMinus: + mass = o2::constants::physics::MassMuon; + break; + case kPiPlus: + mass = o2::constants::physics::MassPionCharged; + break; + case kKPlus: + mass = o2::constants::physics::MassKaonCharged; + break; + case kProton: + mass = o2::constants::physics::MassProton; + break; + default: + break; + } + + float lambda = brSettings.radiationStrength * mcParticle.e() * geoEntry.getFloatValue(layerName, "x0") / (mass * mass); + ULong64_t nPhotons = gRandom->Poisson(lambda); + + double initialMomentum = trackParCov.getP(); + + for (ULong64_t photon = 0; photon < nPhotons; ++photon) { + float radiativeLoss = 1.0f - brSettings.minBREnergyFraction * std::pow(brSettings.maxBREnergyFraction / brSettings.minBREnergyFraction, gRandom->Rndm()); + trackParCov.setQ2Pt(trackParCov.getQ2Pt() / radiativeLoss); + } + + double afterRadiationMomentum = trackParCov.getP(); + + if (brSettings.doBRQA) { + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + + getHist(TH1, histPath + "h1dNBRPhotons")->Fill(static_cast(nPhotons)); + getHist(TH1, histPath + "h1dBREnergyLoss")->Fill((initialMomentum - afterRadiationMomentum) / afterRadiationMomentum); + + getHist(TH2, histPath + "h2dBRPtRes")->Fill(trackParCov.getPt(), (trackParCov.getPt() - mcParticle.pt()) / trackParCov.getPt()); + getHist(TH2, histPath + "h2dBRPtResAbs")->Fill(trackParCov.getPt(), trackParCov.getPt() - mcParticle.pt()); + } + } + } + } + void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) { const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; @@ -1811,12 +1892,14 @@ struct OnTheFlyTracker { o2::track::TrackParCov perfectTrackParCov; o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); + computeBremsstrahlungLoss(icfg, mcParticle, perfectTrackParCov); nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { reconstructed = false; } } else { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + computeBremsstrahlungLoss(icfg, mcParticle, trackParCov); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); nTrkHits = fastTrackerSettings.minSiliconHits; } @@ -2002,11 +2085,13 @@ struct OnTheFlyTracker { int nTrkHits = 0; if (enablePrimarySmearing && mcParticle.isPrimary()) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + computeBremsstrahlungLoss(icfg, mcParticle, trackParCov); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); nTrkHits = fastTrackerSettings.minSiliconHits; } else if (enableSecondarySmearing) { o2::track::TrackParCov perfectTrackParCov; o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); + computeBremsstrahlungLoss(icfg, mcParticle, perfectTrackParCov); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); if (nTrkHits < fastTrackerSettings.minSiliconHits) { From 3ecbbefc3a678eb1513cf7e26ed3a662e28214a0 Mon Sep 17 00:00:00 2001 From: Fan-Cao <15835781687@163.com> Date: Sat, 30 May 2026 16:00:43 +0800 Subject: [PATCH 354/449] [PWGHF] taskD0: Add axis for the number of primary-vertex contributors (#16350) --- PWGHF/D2H/Tasks/taskD0.cxx | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index 088c3847b90..df1630a1cb7 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -349,6 +349,7 @@ struct HfTaskD0 { } if (storeCentrality) { axes.push_back(thnAxisCent); + axes.push_back(thnAxisNumPvContr); } if (storeOccupancyAndIR) { axes.push_back(thnAxisOccupancy); @@ -556,10 +557,12 @@ struct HfTaskD0 { float cent{-1.f}; float occ{-1.f}; float ir{-1.f}; + int numPvContributors = -1; if (storeCentrality || storeOccupancyAndIR) { auto collision = candidate.template collision_as(); if (storeCentrality && centEstimator != CentralityEstimator::None) { cent = getCentralityColl(collision, centEstimator); + numPvContributors = collision.numContrib(); } if (storeOccupancyAndIR && occEstimator != OccupancyEstimator::None) { occ = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); @@ -575,21 +578,21 @@ struct HfTaskD0 { if constexpr (ApplyMl) { if (storeCentrality && storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, occ, ir); - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, occ, ir); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, numPvContributors, occ, ir); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, numPvContributors, occ, ir); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, occ, ir); - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, occ, ir); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, numPvContributors, occ, ir); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, numPvContributors, occ, ir); } } else if (storeCentrality && !storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent); - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, numPvContributors); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0()[0], candidate.mlProbD0()[1], candidate.mlProbD0()[2], massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, numPvContributors); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent); - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, numPvContributors); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"), candidate.mlProbD0bar()[0], candidate.mlProbD0bar()[1], candidate.mlProbD0bar()[2], massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, numPvContributors); } } else if (!storeCentrality && storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { @@ -622,21 +625,21 @@ struct HfTaskD0 { } else { if (storeCentrality && storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, occ, ir); - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, occ, ir); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, numPvContributors, occ, ir); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, numPvContributors, occ, ir); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, occ, ir); - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, occ, ir); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, numPvContributors, occ, ir); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, numPvContributors, occ, ir); } } else if (storeCentrality && !storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent); - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), SigD0, cent, numPvContributors); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0bar() ? ReflectedD0 : PureSigD0, cent, numPvContributors); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent); - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), SigD0bar, cent, numPvContributors); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsD0Type"), massD0bar, ptCandidate, HfHelper::yD0(candidate), candidate.isSelD0() ? ReflectedD0bar : PureSigD0bar, cent, numPvContributors); } } else if (!storeCentrality && storeOccupancyAndIR) { if (candidate.isSelD0() >= selectionFlagD0) { From 899d99542a55ae594a1eb012af2979837a70c174 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Sat, 30 May 2026 10:02:11 +0200 Subject: [PATCH 355/449] [ALICE3] Switch from McPartWithDaus to McParticles with --aod-origin-replace in otf decayer (#16448) --- ALICE3/Core/Decayer.h | 1 + ALICE3/Core/OTFParticle.h | 48 +++++-- ALICE3/DataModel/OTFMCParticle.h | 94 ------------- ALICE3/DataModel/tracksAlice3.h | 4 + ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx | 69 ++++++---- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 12 +- .../TableProducer/alice3strangenessFinder.cxx | 63 ++++----- ALICE3/Tasks/alice3DecayerQa.cxx | 130 +++++++++--------- ALICE3/Tasks/alice3Strangeness.cxx | 3 +- 9 files changed, 177 insertions(+), 247 deletions(-) delete mode 100644 ALICE3/DataModel/OTFMCParticle.h diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 51296ffe67d..52ca0a75adb 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -126,6 +126,7 @@ class Decayer particle.setPDG(pdgCodesDaughters[i]); particle.setVxVyVz(mVx, mVy, mVz); particle.setPxPyPzE(dau.Px(), dau.Py(), dau.Pz(), dau.E()); + particle.setBitOn(o2::upgrade::DecayerBits::ProducedByDecayer); decayProducts.push_back(particle); } diff --git a/ALICE3/Core/OTFParticle.h b/ALICE3/Core/OTFParticle.h index b6ca1f246c3..9f93ea59597 100644 --- a/ALICE3/Core/OTFParticle.h +++ b/ALICE3/Core/OTFParticle.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,10 @@ namespace o2::upgrade { +enum class DecayerBits { ProducedByDecayer = 0, + IsPrimary, + IsAlive }; + class OTFParticle { public: @@ -47,20 +52,29 @@ class OTFParticle mVy = particle.vy(); mVz = particle.vz(); mVt = particle.vt(); + mFlag = particle.flags(); + mStatusCode = particle.statusCode(); mIsFromMcParticles = true; if (particle.has_mothers()) { mIndicesMother = {particle.mothersIds().front(), particle.mothersIds().back()}; } + if constexpr (requires { particle.decayerBits(); }) { + mBits = particle.decayerBits(); + } else { + // If we are here, we created particle in the standard workflow -- without secondaries + // Then we should set all particles as physical primaries accordingly + setBitOn(DecayerBits::IsPrimary); + } } // Setters - void setIsAlive(const bool isAlive) { mIsAlive = isAlive; } void setIsPrimary(const bool isPrimary) { mIsPrimary = isPrimary; } void setCollisionId(const int collisionId) { mCollisionId = collisionId; } void setPDG(const int pdg) { mPdgCode = pdg; } void setIndicesMother(const int start, const int stop) { mIndicesMother = {start, stop}; } void setIndicesDaughter(const int start, const int stop) { mIndicesDaughter = {start, stop}; } void setProductionTime(const float vt) { mVt = vt; } + void setFlags(uint8_t flag) { mFlag = flag; } void setVxVyVz(const float vx, const float vy, const float vz) { mVx = vx; @@ -87,16 +101,8 @@ class OTFParticle static constexpr float Weight = 1.f; return Weight; } - uint8_t flags() const - { - static constexpr uint8_t Flags = 1; - return Flags; // todo - } - int statusCode() const - { - static constexpr int StatusCode = 1; - return StatusCode; // todo - } + uint8_t flags() const { return mFlag; } + int statusCode() const { return mStatusCode; } float vx() const { return mVx; } float vy() const { return mVy; } float vz() const { return mVz; } @@ -112,7 +118,8 @@ class OTFParticle float phi() const { return o2::constants::math::PI + std::atan2(-1.0f * py(), -1.0f * px()); } float eta() const { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 + // Conditionally defined to avoid FPEs + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1959 static constexpr float Tolerance = 1e-7f; if ((p() - mPz) < Tolerance) { return (mPz < 0.0f) ? -100.0f : 100.0f; @@ -122,7 +129,8 @@ class OTFParticle } float y() const { - // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 + // Conditionally defined to avoid FPEs + // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1980 static constexpr float Tolerance = 1e-7f; if ((e() - mPz) < Tolerance) { return (mPz < 0.0f) ? -100.0f : 100.0f; @@ -151,6 +159,16 @@ class OTFParticle return (mGlobalIndex != -1); } + // Bits + bool checkBit(DecayerBits bit) const { return mBits.test(static_cast(bit)); } + void setBit(DecayerBits bit, bool value = true) { mBits.set(static_cast(bit), value); } + void setBitOn(DecayerBits bit) { mBits.set(static_cast(bit), true); } + void setBitOff(DecayerBits bit) { mBits.set(static_cast(bit), false); } + + std::bitset<8> getBits() const { return mBits; } + uint8_t getBitsValue() const { return static_cast(mBits.to_ulong()); } + void setBits(std::bitset<8> bits) { mBits = bits; } + private: int mPdgCode{}, mGlobalIndex{-1}; int mCollisionId{}; @@ -158,6 +176,10 @@ class OTFParticle float mPx{}, mPy{}, mPz{}, mE{}; bool mIsAlive{}, mIsFromMcParticles{false}; bool mIsPrimary{}; + + int mStatusCode{}; + uint8_t mFlag{}; + std::bitset<8> mBits{}; std::array mIndicesMother{-1, -1}, mIndicesDaughter{-1, -1}; }; diff --git a/ALICE3/DataModel/OTFMCParticle.h b/ALICE3/DataModel/OTFMCParticle.h deleted file mode 100644 index 56a1400a2e9..00000000000 --- a/ALICE3/DataModel/OTFMCParticle.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// -/// \file OTFMCParticle.h -/// \author Jesper Karlsson Gumprecht -/// \since 16/12/2025 -/// \brief Redefinition of the mcparticles table specifically for the fast sim -/// - -#ifndef ALICE3_DATAMODEL_OTFMCPARTICLE_H_ -#define ALICE3_DATAMODEL_OTFMCPARTICLE_H_ - -#include - -#include - -namespace o2::aod -{ - -namespace otfmcparticle -{ -DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Eta, eta, float); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(P, p, float); -DECLARE_SOA_COLUMN(Y, y, float); -DECLARE_SOA_COLUMN(IsAlive, isAlive, bool); -DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); - -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother0, mother0, int, "McPartsWithDau_Mother0"); //! Track index of the first mother -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother1, mother1, int, "McPartsWithDau_Mother1"); //! Track index of the last mother -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter0, daughter0, int, "McPartsWithDau_Daughter0"); //! Track index of the first daugther -DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter1, daughter1, int, "McPartsWithDau_Daughter1"); //! Track index of the last daugther -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) -DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) -} // namespace otfmcparticle - -DECLARE_SOA_TABLE_FULL(McPartWithDaus, "McPartWithDaus", "AOD", "MCPARTSWITHDAU", - o2::soa::Index<>, - mcparticle::McCollisionId, - mcparticle::PdgCode, - mcparticle::StatusCode, - mcparticle::Flags, - otfmcparticle::MothersIds, - otfmcparticle::DaughtersIdSlice, - mcparticle::Weight, - mcparticle::Px, - mcparticle::Py, - mcparticle::Pz, - mcparticle::E, - mcparticle::Vx, - mcparticle::Vy, - mcparticle::Vz, - mcparticle::Vt, - otfmcparticle::Phi, - otfmcparticle::Eta, - otfmcparticle::Pt, - otfmcparticle::P, - otfmcparticle::Y, - otfmcparticle::IsAlive, - otfmcparticle::IsPrimary, - mcparticle::PVector, - mcparticle::ProducedByGenerator, - mcparticle::FromBackgroundEvent, - mcparticle::GetGenStatusCode, - mcparticle::GetHepMCStatusCode, - mcparticle::GetProcess, - mcparticle::IsPhysicalPrimary); - -using McPartWithDau = McPartWithDaus::iterator; - -namespace otfmctracklable -{ -DECLARE_SOA_INDEX_COLUMN(McPartWithDau, mcPartWithDau); //! MC particle -DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); //! Bit mask to indicate detector mismatches (bit ON means mismatch). Bit 0-6: mismatch at ITS layer. Bit 12: ITSAB tracklet mismatch. Bit 13: ITS-TPC mismatch. Bit 14: isNoise == True (global track), Bit 15: isFake == True (global track) -} // namespace otfmctracklable - -DECLARE_SOA_TABLE(McTrackWithDauLabels, "AOD", "MCTRACKWithDAULABEL", //! Table joined to the track table containing the MC index - otfmctracklable::McPartWithDauId, otfmctracklable::McMask); - -using McTrackWithDauLabel = McTrackWithDauLabels::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_OTFMCPARTICLE_H_ diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 374069de4cb..b6ccc587d91 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -50,11 +50,15 @@ namespace mcparticle_alice3 { DECLARE_SOA_COLUMN(NHits, nHits, int); //! number of silicon hits DECLARE_SOA_COLUMN(Charge, charge, float); //! particle charge +DECLARE_SOA_BITMAP_COLUMN(DecayerBits, decayerBits, 8); //! Bit mask for particle produced by the OTF decayer } // namespace mcparticle_alice3 DECLARE_SOA_TABLE(MCParticlesExtraA3, "AOD", "MCParticlesExtraA3", mcparticle_alice3::NHits, mcparticle_alice3::Charge); using MCParticleExtraA3 = MCParticlesExtraA3::iterator; + +DECLARE_SOA_TABLE(OTFDecayerBits, "AOD", "OTFDecayerBits", mcparticle_alice3::DecayerBits); + } // namespace o2::aod #endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index ae0d61bcd82..b568364b80c 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -18,7 +18,7 @@ #include "ALICE3/Core/Decayer.h" #include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/OTFMCParticle.h" +#include "ALICE3/DataModel/tracksAlice3.h" #include #include @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -67,12 +66,18 @@ static const std::vector pdgCodes{PDG_t::kK0Short, PDG_t::kOmegaMinus, PDG_t::kOmegaPlusBar}; +namespace o2::aod +{ +O2ORIGIN("TMP"); +} + struct OnTheFlyDecayer { - Produces tableMcParticlesWithDau; + Produces tableMcCollisions; + Produces tableMcParticles; + Produces tableOTFDecayerBits; o2::upgrade::Decayer decayer; Service pdgDB; - std::map> mDecayDaughters; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable seed{"seed", 0, "Set seed for particle decayer"}; @@ -117,18 +122,18 @@ struct OnTheFlyDecayer { void decayParticles(const int start, const int stop) { int ndau = 0; - for (int i = start; i < stop; i++) { + for (int i = start; i < stop; ++i) { o2::upgrade::OTFParticle& particle = allParticles[i]; if (particle.isFromMcParticles()) { - particle.setIsPrimary(true); - particle.setIsAlive(true); + particle.setBitOn(o2::upgrade::DecayerBits::IsPrimary); + particle.setBitOn(o2::upgrade::DecayerBits::IsAlive); } if (!canDecay(particle)) { continue; } - particle.setIsAlive(false); + particle.setBitOff(o2::upgrade::DecayerBits::IsAlive); std::vector decayStack = decayer.decayParticle(pdgDB, particle); const float decayRadius = decayer.getDecayRadius(); const float trackVelocity = o2::upgrade::computeParticleVelocity(particle.p(), pdgDB->GetParticle(particle.pdgCode())->Mass()); @@ -150,8 +155,8 @@ struct OnTheFlyDecayer { for (o2::upgrade::OTFParticle daughter : decayStack) { daughter.setIndicesMother(i, i); daughter.setCollisionId(mCollisionId); - daughter.setIsAlive(true); - daughter.setIsPrimary(false); + daughter.setBitOn(o2::upgrade::DecayerBits::IsAlive); + daughter.setBitOff(o2::upgrade::DecayerBits::IsPrimary); daughter.setProductionTime(trackTimeNS); allParticles.push_back(daughter); ndau++; @@ -165,42 +170,54 @@ struct OnTheFlyDecayer { decayParticles(stop, stop + ndau); } - void process(aod::McCollision const& collision, aod::McParticles const& mcParticles) + void process(aod::McCollisions_001From>::iterator const& collision, aod::McParticles_001From> const& mcParticles) { - mCollisionId = collision.globalIndex(); allParticles.clear(); + // Reproduce collision table to have AOD origin + mCollisionId = collision.globalIndex(); + tableMcCollisions(collision.bcId(), + collision.generatorsID(), + collision.posX(), + collision.posY(), + collision.posZ(), + collision.t(), + collision.weight(), + collision.impactParameter(), + collision.eventPlaneAngle()); + // First we copy the particles from the table into a vector that is extendable - for (int index{0}; index < static_cast(mcParticles.size()); ++index) { - const auto& mcParticle = mcParticles.rawIteratorAt(index); - allParticles.push_back(o2::upgrade::OTFParticle{mcParticle}); + for (const auto& particle : mcParticles) { + allParticles.emplace_back(o2::upgrade::OTFParticle{particle}); } // Do all decays decayParticles(0, allParticles.size()); // Fill output table - for (int index{0}; index < static_cast(allParticles.size()); ++index) { - const auto& otfParticle = allParticles[index]; - + for (const auto& otfParticle : allParticles) { if (otfParticle.hasNaN()) { histos.fill(HIST("hNaNBookkeeping"), 1); } else { histos.fill(HIST("hNaNBookkeeping"), 0); } - // todo: status codes - tableMcParticlesWithDau(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), - otfParticle.flags(), otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), - otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), - otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt(), - otfParticle.phi(), otfParticle.eta(), otfParticle.pt(), otfParticle.p(), otfParticle.y(), - otfParticle.isAlive(), otfParticle.isPrimary()); + tableOTFDecayerBits(otfParticle.getBitsValue()); + tableMcParticles(otfParticle.collisionId(), otfParticle.pdgCode(), otfParticle.statusCode(), otfParticle.flags(), + otfParticle.getMotherSpan(), otfParticle.getDaughters().data(), otfParticle.weight(), + otfParticle.px(), otfParticle.py(), otfParticle.pz(), otfParticle.e(), + otfParticle.vx(), otfParticle.vy(), otfParticle.vz(), otfParticle.vt()); } } }; +struct OnTheFlyDecayerExtensionSpawner { + Spawns spawnMcParticlesExtensions; + void init(o2::framework::InitContext&) {} +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 0a91840c819..69b9419f9b9 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -30,7 +30,6 @@ #include "ALICE3/Core/OTFParticle.h" #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFCollision.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" #include "ALICE3/DataModel/collisionAlice3.h" #include "ALICE3/DataModel/tracksAlice3.h" @@ -137,7 +136,6 @@ struct OnTheFlyTracker { Produces tableStoredTracksCov; Produces tableTracksCovExtension; Produces tableMcTrackLabels; - Produces tableMcTrackWithDauLabels; Produces tableTracksDCA; Produces tableTracksDCACov; Produces tableCollisionsAlice3; @@ -1751,7 +1749,6 @@ struct OnTheFlyTracker { trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), trackParCov.getSigma1Pt2()); tableMcTrackLabels(trackParCov.mcLabel, 0); - tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits, trackParCov.trackType); // populate extra tables if required to do so @@ -2016,7 +2013,8 @@ struct OnTheFlyTracker { } } - void processConfigurationDev(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles, const int icfg) + template + void processConfigurationDev(aod::McCollision const& mcCollision, TMcParticles const& mcParticles, const int icfg) { const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; tracksAlice3.clear(); @@ -2083,12 +2081,12 @@ struct OnTheFlyTracker { bool reconstructed = false; int nTrkHits = 0; - if (enablePrimarySmearing && mcParticle.isPrimary()) { + if (enablePrimarySmearing && otfParticle.checkBit(o2::upgrade::DecayerBits::IsPrimary)) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); computeBremsstrahlungLoss(icfg, mcParticle, trackParCov); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); nTrkHits = fastTrackerSettings.minSiliconHits; - } else if (enableSecondarySmearing) { + } else if (enableSecondarySmearing && !otfParticle.checkBit(o2::upgrade::DecayerBits::IsPrimary) && otfParticle.checkBit(o2::upgrade::DecayerBits::ProducedByDecayer) && otfParticle.checkBit(o2::upgrade::DecayerBits::IsAlive)) { o2::track::TrackParCov perfectTrackParCov; o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); computeBremsstrahlungLoss(icfg, mcParticle, perfectTrackParCov); @@ -2159,7 +2157,7 @@ struct OnTheFlyTracker { fillTracksInfo(ghostTracksAlice3, primaryVertex, icfg); } - void processDecayer(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles) + void processDecayer(aod::McCollision const& mcCollision, soa::Join const& mcParticles) { for (size_t icfg = 0; icfg < mSmearer.size(); ++icfg) { processConfigurationDev(mcCollision, mcParticles, static_cast(icfg)); diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index e96db585c25..3599bc12d97 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -22,7 +22,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFPIDTrk.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFStrangeness.h" @@ -57,6 +56,7 @@ #include #include #include +#include #include using namespace o2; @@ -66,7 +66,7 @@ using namespace o2::constants::physics; using Alice3TracksWPid = soa::Join; using Alice3TracksACTS = soa::Join; -using Alice3TracksOTF = soa::Join; +using Alice3TracksOTF = soa::Join; using Alice3MCParticles = soa::Join; struct Alice3strangenessFinder { @@ -270,34 +270,21 @@ struct Alice3strangenessFinder { template bool checkSameMother(TTrackType const& track1, TTrackType const& track2) { - // MC label points to McPartWithDaus - if constexpr (requires { track1.has_mcPartWithDau(); }) { - if (!track1.has_mcPartWithDau() || !track2.has_mcPartWithDau()) { - return false; - } - auto mcParticle1 = track1.template mcPartWithDau_as(); - auto mcParticle2 = track2.template mcPartWithDau_as(); - if (mcParticle1.mothersIds().empty() || mcParticle2.mothersIds().empty()) { - return false; - } - return mcParticle1.mothersIds()[0] == mcParticle2.mothersIds()[0]; - } else { // MC label points directly to aod::McParticles - bool returnValue = false; - if (track1.has_mcParticle() && track2.has_mcParticle()) { - auto mcParticle1 = track1.template mcParticle_as(); - auto mcParticle2 = track2.template mcParticle_as(); - if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { - for (const auto& m1 : mcParticle1.template mothers_as()) { - for (const auto& m2 : mcParticle2.template mothers_as()) { - if (m1.globalIndex() == m2.globalIndex()) { - returnValue = true; - } + bool returnValue = false; + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcParticle1 = track1.template mcParticle_as(); + auto mcParticle2 = track2.template mcParticle_as(); + if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { + for (const auto& m1 : mcParticle1.template mothers_as()) { + for (const auto& m2 : mcParticle2.template mothers_as()) { + if (m1.globalIndex() == m2.globalIndex()) { + returnValue = true; } } } } - return returnValue; } + return returnValue; } template @@ -432,7 +419,7 @@ struct Alice3strangenessFinder { } template - void processFindV0CandidateNoPid(TCollision collision, TTracksGrouped negTracksGrouped, TTracksGrouped posTracksGrouped, TTracksGrouped bachTracksGrouped) + void processFindV0CandidateNoPid(const TCollision& collision, const TTracksGrouped& negTracksGrouped, const TTracksGrouped& posTracksGrouped, const TTracksGrouped& bachTracksGrouped) { const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; histos.fill(HIST("hEventCounter"), 1.0); @@ -465,18 +452,16 @@ struct Alice3strangenessFinder { } // OTF: pdg code from mcParticle table - if constexpr (requires { posTrack.has_mcPartWithDau(); }) { - if (!posTrack.has_mcPartWithDau() && !negTrack.has_mcPartWithDau()) { - continue; - } - auto mcParticlePos = posTrack.template mcPartWithDau_as(); - auto mcParticleNeg = negTrack.template mcPartWithDau_as(); - if ((mcParticlePos.pdgCode() != kPiPlus && mcParticleNeg.pdgCode() != kPiMinus) && isK0Gun) { - continue; - } - if ((mcParticlePos.pdgCode() != kProton && mcParticleNeg.pdgCode() != kPiMinus) && isLambdaGun) { - continue; - } + if (!posTrack.has_mcParticle() && !negTrack.has_mcParticle()) { + continue; + } + auto mcParticlePos = posTrack.template mcParticle_as(); + auto mcParticleNeg = negTrack.template mcParticle_as(); + if ((mcParticlePos.pdgCode() != kPiPlus && mcParticleNeg.pdgCode() != kPiMinus) && isK0Gun) { + continue; + } + if ((mcParticlePos.pdgCode() != kProton && mcParticleNeg.pdgCode() != kPiMinus) && isLambdaGun) { + continue; } histos.fill(HIST("hV0Building"), 2.0); @@ -682,7 +667,7 @@ struct Alice3strangenessFinder { processFindV0CandidateNoPid(collision, negTracksGrouped, posTracksGrouped, bachTracksGrouped); } - void processFindV0CandidateOTF(aod::Collision const& collision, Alice3TracksOTF const&, aod::McPartWithDaus const&) + void processFindV0CandidateOTF(aod::Collision const& collision, Alice3TracksOTF const&, aod::McParticles const&) { auto negTracksGrouped = negativeSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto posTracksGrouped = positiveSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx index 5ae57d33f66..7323e7f380b 100644 --- a/ALICE3/Tasks/alice3DecayerQa.cxx +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -17,8 +17,6 @@ /// \since Dec 23, 2025 /// -#include "ALICE3/DataModel/OTFMCParticle.h" - #include #include #include @@ -46,7 +44,7 @@ struct Alice3DecayerQa { ConfigurableAxis axisCollisionId{"axisCollisionId", {1000, 0, 999}, "CollisionId axis for QA histograms"}; ConfigurableAxis axisPdgCode{"axisPdgCode", {1000, 0, 999}, "PdgCode axis for QA histograms"}; ConfigurableAxis axisStatusCode{"axisStatusCode", {1000, 0, 999}, "StatusCode axis for QA histograms"}; - ConfigurableAxis axisFlags{"axisFlags", {10, 0, 9}, "Flags axis for QA histograms"}; + ConfigurableAxis axisFlags{"axisFlags", {256, 0, 255}, "Flags axis for QA histograms"}; ConfigurableAxis axisMothersIds{"axisMothersIds", {1000, 0, 999}, "MothersIds axis for QA histograms"}; ConfigurableAxis axisDaughtersIds{"axisDaughtersIds", {1000, 0, 999}, "DaughtersIds axis for QA histograms"}; ConfigurableAxis axisWeight{"axisWeight", {2, 0, 1}, "Weight axis for QA histograms"}; @@ -61,14 +59,14 @@ struct Alice3DecayerQa { ConfigurableAxis axisPtLog{"axisPtLog", {VARIABLE_WIDTH, 0.0f, 0.001f, 0.00104713f, 0.00109648f, 0.00114815f, 0.00120226f, 0.00125893f, 0.00131826f, 0.00138038f, 0.00144544f, 0.00151356f, 0.00158489f, 0.00165959f, 0.0017378f, 0.0018197f, 0.00190546f, 0.00199526f, 0.0020893f, 0.00218776f, 0.00229087f, 0.00239883f, 0.00251189f, 0.00263027f, 0.00275423f, 0.00288403f, 0.00301995f, 0.00316228f, 0.00331131f, 0.00346737f, 0.00363078f, 0.00380189f, 0.00398107f, 0.00416869f, 0.00436516f, 0.00457088f, 0.0047863f, 0.00501187f, 0.00524807f, 0.00549541f, 0.0057544f, 0.0060256f, 0.00630957f, 0.00660693f, 0.00691831f, 0.00724436f, 0.00758578f, 0.00794328f, 0.00831764f, 0.00870964f, 0.00912011f, 0.00954993f, 0.01f, 0.0104713f, 0.0109648f, 0.0114815f, 0.0120226f, 0.0125893f, 0.0131826f, 0.0138038f, 0.0144544f, 0.0151356f, 0.0158489f, 0.0165959f, 0.017378f, 0.018197f, 0.0190546f, 0.0199526f, 0.020893f, 0.0218776f, 0.0229087f, 0.0239883f, 0.0251189f, 0.0263027f, 0.0275423f, 0.0288403f, 0.0301995f, 0.0316228f, 0.0331131f, 0.0346737f, 0.0363078f, 0.0380189f, 0.0398107f, 0.0416869f, 0.0436516f, 0.0457088f, 0.047863f, 0.0501187f, 0.0524807f, 0.0549541f, 0.057544f, 0.060256f, 0.0630957f, 0.0660693f, 0.0691831f, 0.0724436f, 0.0758578f, 0.0794328f, 0.0831764f, 0.0870964f, 0.0912011f, 0.0954993f, 0.1f, 0.104713f, 0.109648f, 0.114815f, 0.120226f, 0.125893f, 0.131826f, 0.138038f, 0.144544f, 0.151356f, 0.158489f, 0.165959f, 0.17378f, 0.18197f, 0.190546f, 0.199526f, 0.20893f, 0.218776f, 0.229087f, 0.239883f, 0.251189f, 0.263027f, 0.275423f, 0.288403f, 0.301995f, 0.316228f, 0.331131f, 0.346737f, 0.363078f, 0.380189f, 0.398107f, 0.416869f, 0.436516f, 0.457088f, 0.47863f, 0.501187f, 0.524807f, 0.549541f, 0.57544f, 0.60256f, 0.630957f, 0.660693f, 0.691831f, 0.724436f, 0.758578f, 0.794328f, 0.831764f, 0.870964f, 0.912011f, 0.954993f, 1.0f, 1.04713f, 1.09648f, 1.14815f, 1.20226f, 1.25893f, 1.31826f, 1.38038f, 1.44544f, 1.51356f, 1.58489f, 1.65959f, 1.7378f, 1.8197f, 1.90546f, 1.99526f, 2.0893f, 2.18776f, 2.29087f, 2.39883f, 2.51189f, 2.63027f, 2.75423f, 2.88403f, 3.01995f, 3.16228f, 3.31131f, 3.46737f, 3.63078f, 3.80189f, 3.98107f, 4.16869f, 4.36516f, 4.57088f, 4.7863f, 5.01187f, 5.24807f, 5.49541f, 5.7544f, 6.0256f, 6.30957f, 6.60693f, 6.91831f, 7.24436f, 7.58578f, 7.94328f, 8.31764f, 8.70964f, 9.12011f, 9.54993f, 10.0f}, "pt axis for QA histograms"}; } axes; - Partition trueElectrons = aod::mcparticle::pdgCode == static_cast(PDG_t::kElectron); - Partition trueMuons = aod::mcparticle::pdgCode == static_cast(PDG_t::kMuonMinus); - Partition truePions = aod::mcparticle::pdgCode == static_cast(PDG_t::kPiPlus); - Partition trueKaons = aod::mcparticle::pdgCode == static_cast(PDG_t::kKMinus); - Partition trueProtons = aod::mcparticle::pdgCode == static_cast(PDG_t::kProton); - Partition trueK0Short = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); - Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); - Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); + Partition trueElectrons = aod::mcparticle::pdgCode == static_cast(PDG_t::kElectron); + Partition trueMuons = aod::mcparticle::pdgCode == static_cast(PDG_t::kMuonMinus); + Partition truePions = aod::mcparticle::pdgCode == static_cast(PDG_t::kPiPlus); + Partition trueKaons = aod::mcparticle::pdgCode == static_cast(PDG_t::kKMinus); + Partition trueProtons = aod::mcparticle::pdgCode == static_cast(PDG_t::kProton); + Partition trueK0Short = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); + Partition trueLambdas = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); + Partition trueXiMinus = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); static constexpr size_t NCascadeDaughters = 2; static constexpr size_t NV0Daughters = 2; @@ -82,33 +80,31 @@ struct Alice3DecayerQa { void init(o2::framework::InitContext&) { // QA with Table entries - histos.add("MCWithDau/hElPt", "hElPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); - histos.add("MCWithDau/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); - histos.add("MCWithDau/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); - histos.add("MCWithDau/hFlags", "hFlags", kTH1D, {axes.axisFlags}); - histos.add("MCWithDau/hMothersIds", "hMothersIds", kTH1D, {axes.axisMothersIds}); - histos.add("MCWithDau/hDaughtersIds", "hDaughtersIds", kTH1D, {axes.axisDaughtersIds}); - histos.add("MCWithDau/hWeight", "hWeight", kTH1D, {axes.axisWeight}); - histos.add("MCWithDau/hVx", "hVx", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVy", "hVy", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVz", "hVz", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hVt", "hVt", kTH1D, {axes.axisPos}); - histos.add("MCWithDau/hPhi", "hPhi", kTH1D, {axes.axisPhi}); - histos.add("MCWithDau/hEta", "hEta", kTH1D, {axes.axisEta}); - histos.add("MCWithDau/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); - histos.add("MCWithDau/hIsAlive", "hIsAlive", kTH1D, {axes.axisIsAlive}); - histos.add("MCWithDau/hIsPrimary", "hIsPrimary", kTH1D, {axes.axisIsPrimary}); - histos.add("MCWithDau/hPx", "hPx", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPy", "hPy", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPz", "hPz", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hPt", "hPt", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hP", "hP", kTH1D, {axes.axisPt}); - histos.add("MCWithDau/hE", "hE", kTH1D, {axes.axisPt}); + histos.add("McParticle/hElPt", "hElPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); + histos.add("McParticle/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); + histos.add("McParticle/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); + histos.add("McParticle/hFlags", "hFlags", kTH1D, {axes.axisFlags}); + histos.add("McParticle/hMothersIds", "hMothersIds", kTH1D, {axes.axisMothersIds}); + histos.add("McParticle/hDaughtersIds", "hDaughtersIds", kTH1D, {axes.axisDaughtersIds}); + histos.add("McParticle/hWeight", "hWeight", kTH1D, {axes.axisWeight}); + histos.add("McParticle/hVx", "hVx", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVy", "hVy", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVz", "hVz", kTH1D, {axes.axisPos}); + histos.add("McParticle/hVt", "hVt", kTH1D, {axes.axisPos}); + histos.add("McParticle/hPhi", "hPhi", kTH1D, {axes.axisPhi}); + histos.add("McParticle/hEta", "hEta", kTH1D, {axes.axisEta}); + histos.add("McParticle/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); + histos.add("McParticle/hPx", "hPx", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPy", "hPy", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPz", "hPz", kTH1D, {axes.axisPt}); + histos.add("McParticle/hPt", "hPt", kTH1D, {axes.axisPt}); + histos.add("McParticle/hP", "hP", kTH1D, {axes.axisPt}); + histos.add("McParticle/hE", "hE", kTH1D, {axes.axisPt}); // QA with daughters from Decayer histos.add("K0S/hGeneratedPt", "hGeneratedPt;#it{p}_{T} (GeV/#it{c})", kTH1D, {axes.axisPt}); @@ -134,8 +130,9 @@ struct Alice3DecayerQa { hCheckHasXiMinusDecayed->GetXaxis()->SetBinLabel(2, "Yes"); } - void process(const aod::McCollision& collision, const aod::McPartWithDaus& particles) + void process(const aod::McCollision& collision, const aod::McParticles& particles) { + LOG(info) << particles.size(); // Group with collision auto trueElectronsGrouped = trueElectrons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); auto trueMuonsGrouped = trueMuons->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); @@ -147,19 +144,19 @@ struct Alice3DecayerQa { auto trueXiMinusGrouped = trueXiMinus->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); for (const auto& particle : trueElectronsGrouped) { - histos.fill(HIST("MCWithDau/hElPt"), particle.pt()); + histos.fill(HIST("McParticle/hElPt"), particle.pt()); } for (const auto& particle : trueMuonsGrouped) { - histos.fill(HIST("MCWithDau/hMuPt"), particle.pt()); + histos.fill(HIST("McParticle/hMuPt"), particle.pt()); } for (const auto& particle : truePionsGrouped) { - histos.fill(HIST("MCWithDau/hPiPt"), particle.pt()); + histos.fill(HIST("McParticle/hPiPt"), particle.pt()); } for (const auto& particle : trueKaonsGrouped) { - histos.fill(HIST("MCWithDau/hKaPt"), particle.pt()); + histos.fill(HIST("McParticle/hKaPt"), particle.pt()); } for (const auto& particle : trueProtonsGrouped) { - histos.fill(HIST("MCWithDau/hPrPt"), particle.pt()); + histos.fill(HIST("McParticle/hPrPt"), particle.pt()); } for (const auto& particle : trueK0ShortGrouped) { histos.fill(HIST("K0S/hGeneratedPt"), particle.pt()); @@ -173,6 +170,7 @@ struct Alice3DecayerQa { // K0S -> pi+ pi- const bool k0sDecay = (dau0.pdgCode() == PDG_t::kPiPlus && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kPiPlus); + if (k0sDecay) { auto& positive = dau0.pdgCode() == PDG_t::kPiPlus ? dau0 : dau1; auto& negative = dau0.pdgCode() == PDG_t::kPiPlus ? dau1 : dau0; @@ -196,6 +194,7 @@ struct Alice3DecayerQa { // Lambda -> p pi- const bool lambdaDecay = (dau0.pdgCode() == PDG_t::kProton && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kProton); + if (lambdaDecay) { auto& positive = dau0.pdgCode() == PDG_t::kProton ? dau0 : dau1; auto& negative = dau0.pdgCode() == PDG_t::kProton ? dau1 : dau0; @@ -219,6 +218,7 @@ struct Alice3DecayerQa { // Xi- -> Lambda pi- const bool xiDecay = (dau0.pdgCode() == PDG_t::kLambda0 && dau1.pdgCode() == PDG_t::kPiMinus) || (dau0.pdgCode() == PDG_t::kPiMinus && dau1.pdgCode() == PDG_t::kLambda0); + if (xiDecay) { auto& v0 = dau0.pdgCode() == PDG_t::kLambda0 ? dau0 : dau1; auto& bachelor = dau0.pdgCode() == PDG_t::kLambda0 ? dau1 : dau0; @@ -249,31 +249,29 @@ struct Alice3DecayerQa { } for (const auto& particle : particles) { - histos.fill(HIST("MCWithDau/hCollisionId"), particle.mcCollisionId()); - histos.fill(HIST("MCWithDau/hPdgCode"), particle.pdgCode()); - histos.fill(HIST("MCWithDau/hStatusCode"), particle.statusCode()); - histos.fill(HIST("MCWithDau/hFlags"), particle.flags()); - histos.fill(HIST("MCWithDau/hWeight"), particle.weight()); - histos.fill(HIST("MCWithDau/hVx"), particle.vx()); - histos.fill(HIST("MCWithDau/hVy"), particle.vy()); - histos.fill(HIST("MCWithDau/hVz"), particle.vz()); - histos.fill(HIST("MCWithDau/hVt"), particle.vt()); - histos.fill(HIST("MCWithDau/hPhi"), particle.phi()); - histos.fill(HIST("MCWithDau/hEta"), particle.eta()); - histos.fill(HIST("MCWithDau/hRapidity"), particle.y()); - histos.fill(HIST("MCWithDau/hIsAlive"), particle.isAlive()); - histos.fill(HIST("MCWithDau/hIsPrimary"), particle.isPrimary()); - histos.fill(HIST("MCWithDau/hPx"), particle.px()); - histos.fill(HIST("MCWithDau/hPy"), particle.py()); - histos.fill(HIST("MCWithDau/hPz"), particle.pz()); - histos.fill(HIST("MCWithDau/hPt"), particle.pt()); - histos.fill(HIST("MCWithDau/hP"), particle.p()); - histos.fill(HIST("MCWithDau/hE"), particle.e()); + histos.fill(HIST("McParticle/hCollisionId"), particle.mcCollisionId()); + histos.fill(HIST("McParticle/hPdgCode"), particle.pdgCode()); + histos.fill(HIST("McParticle/hStatusCode"), particle.statusCode()); + histos.fill(HIST("McParticle/hFlags"), particle.flags()); + histos.fill(HIST("McParticle/hWeight"), particle.weight()); + histos.fill(HIST("McParticle/hVx"), particle.vx()); + histos.fill(HIST("McParticle/hVy"), particle.vy()); + histos.fill(HIST("McParticle/hVz"), particle.vz()); + histos.fill(HIST("McParticle/hVt"), particle.vt()); + histos.fill(HIST("McParticle/hPhi"), particle.phi()); + histos.fill(HIST("McParticle/hEta"), particle.eta()); + histos.fill(HIST("McParticle/hRapidity"), particle.y()); + histos.fill(HIST("McParticle/hPx"), particle.px()); + histos.fill(HIST("McParticle/hPy"), particle.py()); + histos.fill(HIST("McParticle/hPz"), particle.pz()); + histos.fill(HIST("McParticle/hPt"), particle.pt()); + histos.fill(HIST("McParticle/hP"), particle.p()); + histos.fill(HIST("McParticle/hE"), particle.e()); for (const auto& motherParticleId : particle.mothersIds()) { - histos.fill(HIST("MCWithDau/hMothersIds"), motherParticleId); + histos.fill(HIST("McParticle/hMothersIds"), motherParticleId); } for (const auto& dauParticleId : particle.daughtersIds()) { - histos.fill(HIST("MCWithDau/hDaughtersIds"), dauParticleId); + histos.fill(HIST("McParticle/hDaughtersIds"), dauParticleId); } } } diff --git a/ALICE3/Tasks/alice3Strangeness.cxx b/ALICE3/Tasks/alice3Strangeness.cxx index 7527db49495..499624cd6bf 100644 --- a/ALICE3/Tasks/alice3Strangeness.cxx +++ b/ALICE3/Tasks/alice3Strangeness.cxx @@ -20,7 +20,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/DataModel/OTFCollision.h" -#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -50,7 +49,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::constants::math; -using Alice3Tracks = soa::Join; +using Alice3Tracks = soa::Join; using FullV0Candidates = soa::Join; using FullCascadeCandidates = soa::Join; using FullCollisions = soa::Join; From 7f19fda8f4a4003602b53f2282f1c890854dd464 Mon Sep 17 00:00:00 2001 From: pengchon <149305981+pengchon@users.noreply.github.com> Date: Sat, 30 May 2026 12:31:57 +0200 Subject: [PATCH 356/449] [PWGCF] adding new analysis for multiharmonic correlations (#16457) Co-authored-by: Pengchong Hu --- .../Tasks/multiharmonicCorrelations.cxx | 284 ++++++++++++++---- 1 file changed, 224 insertions(+), 60 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx index 5ea45627e26..37529852836 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,12 @@ enum eEventHistograms { eEventHistograms_N }; +enum eCut { + eBefore = 0, + eAfter, + eCut_N +}; + // *) Main task: struct MultiharmonicCorrelations { // this name is used in lower-case format to name the TDirectoryFile in AnalysisResults.root Service ccdb; @@ -86,22 +93,27 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to // *) Define configurables: Configurable cfDryRun{"cfDryRun", false, "book all histos and run without filling and calculating anything"}; // example for built-in type (float, string, etc.) - Configurable> cf_pt_bins{"cf_pt_bins", {1000, 0., 100.}, "nPtBins, ptMin, ptMax"}; // example for an array - Configurable> cf_phi_bins{"cf_phi_bins", {100, 0., o2::constants::math::TwoPI}, "nPhiBins, phiMin, phiMax"}; - Configurable> cf_centr_bins{"cf_centr_bins", {1000, 0., 100.}, "nCentrBins, centrMin, centrMax"}; - Configurable> cf_x_bins{"cf_x_bins", {1000, -100., 100.}, "nXBins, xMin, xMax"}; - Configurable> cf_y_bins{"cf_y_bins", {1000, -100., 100.}, "nYBins, yMin, yMax"}; - Configurable> cf_z_bins{"cf_z_bins", {1000, -100., 100.}, "nZBins, zMin, zMax"}; - Configurable> cf_mult_bins{"cf_mult_bins", {50, 0, 3e3}, "nMultBins, multMin, multMax"}; - - Configurable cfCent{"cfCent", 1, "centrality estimator"}; - Configurable cfMult{"cfMult", 1, "multiplicity"}; + Configurable> cfPtBins{"cfPtBins", {1000, 0., 100.}, "nPtBins, ptMin, ptMax"}; // example for an array + Configurable> cfPhiBins{"cfPhiBins", {100, 0., o2::constants::math::TwoPI}, "nPhiBins, phiMin, phiMax"}; + Configurable> cfCentrBins{"cfCentrBins", {100, 0., 100.}, "nCentrBins, centrMin, centrMax"}; + Configurable> cfXBins{"cfXBins", {1000, -100., 100.}, "nXBins, xMin, xMax"}; + Configurable> cfYBins{"cfYBins", {1000, -100., 100.}, "nYBins, yMin, yMax"}; + Configurable> cfZBins{"cfZBins", {1000, -100., 100.}, "nZBins, zMin, zMax"}; + Configurable> cfMultBins{"cfMultBins", {50, 0, 3e3}, "nMultBins, multMin, multMax"}; + Configurable> cfTPCnclsBins{"cfTPCnclsBins", {100, 0., 1000.}, "ntpcnclsBins, tpnclsMin, tpcnclsMax"}; + Configurable> cfDCAxyBins{"cfDCAxyBins", {1000, -20., 20.}, "ndcaxyBins, dcaxyMin, dcaxyMax"}; + Configurable> cfDCAzBins{"cfDCAzBins", {1000, -10., 10.}, "ndcazBins, dcazMin, dcazMax"}; + Configurable> cfNcontrBins{"cfNcontrBins", {100, 0., 1000}, "nNContrBins, NContrMin, NContrMax"}; + + Configurable cfCent{"cfCent", "FT0C", "centrality estimator"}; + Configurable cfMult{"cfMult", "TPC", "multiplicity"}; Configurable cfQA{"cfQA", true, "quality assurance"}; Configurable> cfVertexZ{"cfVertexZ", {-10, 10.}, "vertex z position range: {min, max}[cm], with convention: min <= Vz < max"}; Configurable> cfPt{"cfPt", {0.2, 5.0}, "transverse momentum range"}; + Configurable> cfEta{"cfEta", {-0.8, 0.8}, "eta range"}; - Configurable cfFileWithWeights{"cfFileWithWeights", "~/O2/weights.root", "path to external ROOT file which holds all particle weights"}; + Configurable cfFileWithWeights{"cfFileWithWeights", "/alice-ccdb.cern.ch/Users/p/pengchon/test04", "path to external ROOT file which holds all particle weights"}; // *) Define and initialize all data members to be called in the main process* functions: // **) Task configuration: @@ -115,6 +127,10 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to TList* fParticleHistogramsList = NULL; //!Getenv("USER"), "", ""); // do not forget to add #include to the preamble of your analysis task @@ -302,7 +335,7 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to float vertexZmin = static_cast(vertexZ[0]); float vertexZmax = static_cast(vertexZ[1]); float posZ = collision.posZ(); - if (posZ < vertexZmin || posZ > vertexZmax) + if (posZ < vertexZmin || posZ > vertexZmax || (!collision.sel8())) return false; return true; } @@ -314,11 +347,32 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to float ptcutmin = static_cast(Pt[0]); float ptcutmax = static_cast(Pt[1]); float pt = track.pt(); - if (pt < ptcutmin || pt > ptcutmax) + vector Eta = cfEta.value; + float etacutmin = static_cast(Eta[0]); + float etacutmax = static_cast(Eta[1]); + float eta = track.eta(); + if (pt < ptcutmin || pt > ptcutmax || eta < etacutmin || eta > etacutmax) return false; return true; } + TComplex Q(Int_t n) + { + // Using the fact that Q{-n,p} = Q{n,p}^*. + if (n >= 0) { + return cor.Qvector[n]; + } + return TComplex::Conjugate(cor.Qvector[-n]); + } + + TComplex Four(Int_t n1, Int_t n2, Int_t n3, Int_t n4) + { // Generic four-particle correlation . + TComplex four = Q(n1) * Q(n2) * Q(n3) * Q(n4) - Q(n1 + n2) * Q(n3) * Q(n4) - Q(n2) * Q(n1 + n3) * Q(n4) - Q(n1) * Q(n2 + n3) * Q(n4) + 2. * Q(n1 + n2 + n3) * Q(n4) - Q(n2) * Q(n3) * Q(n1 + n4) + Q(n2 + n3) * Q(n1 + n4) - Q(n1) * Q(n3) * Q(n2 + n4) + Q(n1 + n3) * Q(n2 + n4) + 2. * Q(n3) * Q(n1 + n2 + n4) - Q(n1) * Q(n2) * Q(n3 + n4) + Q(n1 + n2) * Q(n3 + n4) + 2. * Q(n2) * Q(n1 + n3 + n4) + 2. * Q(n1) * Q(n2 + n3 + n4) - 6. * Q(n1 + n2 + n3 + n4); + + return four; + + } // TComplex Four(Int_t n1, Int_t n2, Int_t n3, Int_t n4) + template void Steer(T1 const& collision, T2 const& tracks) { @@ -327,37 +381,37 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to return; } // Print current run number: - LOGF(info, "Run number: %d", collision.bc().runNumber()); - // Print centrality estimated with "FT0M" estimator: - LOGF(info, "Centrality: %f", collision.centFT0M()); - // Print vertex X position: - LOGF(info, "Vertex X position: %f", collision.posX()); + // LOGF(info, "Run number: %d", collision.bc().runNumber()); + + float zrec = 0., zsim = 0., centr = 0, M = 0.; - float zrec = 0., zsim = 0.; if constexpr (rs == eRec || rs == eRecAndSim) { event.fHistX[eRec]->Fill(collision.posX()); event.fHistY[eRec]->Fill(collision.posY()); event.fHistZ[eRec]->Fill(collision.posZ()); event.fEventHistograms[eVertexZ][eRec][0]->Fill(collision.posZ()); zrec = collision.posZ(); - float centr = 0; - if (cfCent == 1) + event.fHistNContr->Fill(collision.numContrib()); + if (cfCent.value == "FT0C") centr = collision.centFT0C(); - if (cfCent == 2) + else if (cfCent.value == "FT0M") centr = collision.centFT0M(); - if (cfCent == 3) + else if (cfCent.value == "FT0A") centr = collision.centFT0A(); event.fHistCentr[eRec]->Fill(centr); - if (cfMult == 1) - event.fHistMult[eRec]->Fill(collision.multTPC()); - if (cfMult == 2) - event.fHistMult[eRec]->Fill(collision.multFV0M()); - if (cfMult == 3) - event.fHistMult[eRec]->Fill(collision.multFT0C()); - if (cfMult == 4) - event.fHistMult[eRec]->Fill(collision.multFT0M()); - if (cfMult == 5) - event.fHistMult[eRec]->Fill(collision.multNTracksPV()); + + std::string multType = "TPC"; + if (cfMult.value == "TPC") + M = collision.multTPC(); + else if (cfMult.value == "FV0M") + M = collision.multFV0M(); + else if (cfMult.value == "FT0C") + M = collision.multFT0C(); + else if (cfMult.value == "FT0M") + M = collision.multFT0M(); + else if (cfMult.value == "NTracksPV") + M = collision.multNTracksPV(); + event.fHistMult[eRec]->Fill(M); if constexpr (rs == eRecAndSim) { auto mccollision = collision.mcCollision(); @@ -369,12 +423,13 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to event.fEventHistograms[eVertexZ][eSim][0]->Fill(mccollision.posZ()); zsim = mccollision.posZ(); event.fHistCentr[eSim]->Fill(centrsim); - event.fQA->Fill(centrsim, centr); - // event.fHistMult[eSim]->Fill(tracks.size()); + qa.fQA->Fill(centrsim, centr); + centr = centrsim; } // *) Event cuts: - if (!EventCuts(collision)) { // Main call for event cuts + float centrcut = 80.; + if (!EventCuts(collision) || centr > centrcut) { // Main call for event cuts return; } event.fEventHistograms[eVertexZ][eRec][1]->Fill(zrec); @@ -382,11 +437,14 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to event.fEventHistograms[eVertexZ][eSim][1]->Fill(zsim); } - // Main loop over particles: - auto track = tracks.iteratorAt(0); // set the type and scope from one instance - for (int64_t i = 0; i < tracks.size(); i++) { + // before loop over particles + float phi = 0; + for (int ih = 0; ih < maxHarmonic; ih++) { + cor.Qvector[ih] = TComplex(0., 0.); + } - // Print track azimuthal angle: + // Main loop over particles: + for (const auto& track : tracks) { // Fill reconstructed ...: float ptrec = 0., ptsim = 0.; @@ -395,7 +453,12 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to pc.fHistPt[eRec]->Fill(track.pt()); event.fEventHistograms[ePt][eRec][0]->Fill(track.pt()); ptrec = track.pt(); + phi = track.phi(); pc.fHistPhi[eRec]->Fill(track.phi()); + pc.fHistCharge[eRec]->Fill(track.sign()); + pc.fHistTPCncls[eRec]->Fill(track.tpcNClsFindable()); + pc.fHistTracksdcaXY[eRec]->Fill(track.dcaXY()); + pc.fHistTracksdcaZ[eRec]->Fill(track.dcaZ()); // ... and corresponding MC truth simulated: // See https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/mcHistograms.cxx @@ -409,8 +472,13 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to pc.fHistPt[eSim]->Fill(mcparticle.pt()); event.fEventHistograms[ePt][eSim][0]->Fill(mcparticle.pt()); ptsim = mcparticle.pt(); + phi = mcparticle.phi(); pc.fHistPhi[eSim]->Fill(mcparticle.phi()); - } // end of if constexpr (rs == eRecAndSim) { + // pc.fHistCharge[eSim]->Fill(mcparticle.sign()); + // pc.fHistTPCncls[eSim]->Fill(mcparticle.tpcNClsFindable()); + // pc.fHistTracksdcaXY[eSim]->Fill(mcparticle.dcaXY()); + // pc.fHistTracksdcaZ[eSim]->Fill(mcparticle.dcaZ()); + } // end of if constexpr (rs == eRecAndSim) // *) Particle cuts: if (!ParticleCuts(track)) { // Main call for particle cuts. @@ -420,10 +488,27 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to if constexpr (rs == eRecAndSim) event.fEventHistograms[ePt][eSim][0]->Fill(ptsim); - } // if constexpr (rs == eRec || rs == eRecAndSim) { - } // end of for (int64_t i = 0; i < tracks.size(); i++) { + } // if constexpr (rs == eRec || rs == eRecAndSim) - } // end of template void Steer(T1 const& collision, T2 const& tracks) { + // analysis in the loop over particle + for (int ih = 0; ih < maxHarmonic; ih++) { + cor.Qvector[ih] += TComplex(TMath::Cos(ih * phi), TMath::Sin(ih * phi)); + } + } // end of for (auto track: tracks) + // calculate correlations + float four32 = Four(3, 2, -3, -2).Re() / Four(0, 0, 0, 0).Re(); + float four42 = Four(4, 2, -4, -2).Re() / Four(0, 0, 0, 0).Re(); + float v22 = (Q(2).Rho2() - M) / (M * (M - 1.)); + float v32 = (Q(3).Rho2() - M) / (M * (M - 1.)); + float v42 = (Q(4).Rho2() - M) / (M * (M - 1.)); + + cor.pv22_centr->Fill(centr, v22, M * (M - 1)); + cor.pv32_centr->Fill(centr, v32, M * (M - 1)); + cor.pv42_centr->Fill(centr, v42, M * (M - 1)); + cor.pfour32_centr->Fill(centr, four32, M * (M - 1)); + cor.pfour42_centr->Fill(centr, four42, M * (M - 1)); + + } // end of template void Steer(T1 const& collision, T2 const& tracks) // *) Initialize and book all objects: void init(InitContext&) @@ -454,14 +539,28 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to event.fEventHistogramsList->SetOwner(true); fBaseList->Add(event.fEventHistogramsList); + qa.fQAList = new TList(); + qa.fQAList->SetName("QAHistograms"); + qa.fQAList->SetOwner(true); + fBaseList->Add(qa.fQAList); + + cor.fCorrelationVariablesList = new TList(); + cor.fCorrelationVariablesList->SetName("CorrelationVariables"); + cor.fCorrelationVariablesList->SetOwner(true); + fBaseList->Add(cor.fCorrelationVariablesList); + // *) Book pt distribution with binning defined through configurables in the json file: - vector l_pt_bins = cf_pt_bins.value; // define local array and initialize it from an array set in the configurables - vector l_phi_bins = cf_phi_bins.value; - vector l_centr_bins = cf_centr_bins.value; - vector l_x_bins = cf_x_bins.value; - vector l_y_bins = cf_y_bins.value; - vector l_z_bins = cf_z_bins.value; - vector l_mult_bins = cf_mult_bins.value; + vector l_pt_bins = cfPtBins.value; // define local array and initialize it from an array set in the configurables + vector l_phi_bins = cfPhiBins.value; + vector l_centr_bins = cfCentrBins.value; + vector l_x_bins = cfXBins.value; + vector l_y_bins = cfYBins.value; + vector l_z_bins = cfZBins.value; + vector l_mult_bins = cfMultBins.value; + vector l_tpcncls_bins = cfTPCnclsBins.value; + vector l_dcaxy_bins = cfDCAxyBins.value; + vector l_dcaz_bins = cfDCAzBins.value; + vector l_ncontr_bins = cfNcontrBins.value; int nBins = static_cast(l_pt_bins[0]); int nBinsphi = static_cast(l_phi_bins[0]); int nBinscentr = static_cast(l_centr_bins[0]); @@ -469,6 +568,11 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to int nBinsy = static_cast(l_y_bins[0]); int nBinsz = static_cast(l_z_bins[0]); int nBinsmult = static_cast(l_mult_bins[0]); + int nBinscharge = 2; + int nBinstpcncls = static_cast(l_tpcncls_bins[0]); + int nBinsdcaxy = static_cast(l_dcaxy_bins[0]); + int nBinsdcaz = static_cast(l_dcaz_bins[0]); + int nBinsncontr = static_cast(l_ncontr_bins[0]); float min = l_pt_bins[1]; float max = l_pt_bins[2]; @@ -484,20 +588,54 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to float maxz = l_z_bins[2]; float minmult = l_mult_bins[1]; float maxmult = l_mult_bins[2]; + float mincharge = -2.; + float maxcharge = 2.; + float mintpcncls = l_tpcncls_bins[1]; + float maxtpcncls = l_tpcncls_bins[2]; + float mindcaxy = l_dcaxy_bins[1]; + float maxdcaxy = l_dcaxy_bins[2]; + float mindcaz = l_dcaz_bins[1]; + float maxdcaz = l_dcaz_bins[2]; + float maxncontr = l_ncontr_bins[1]; + float minncontr = l_ncontr_bins[2]; pc.fHistPt[eRec] = new TH1F("fHistPt[eRec]", "pt distribution for reconstructed particles", nBins, min, max); - pc.fHistPt[eRec]->GetXaxis()->SetTitle("p_{T}"); - pc.fParticleHistogramsList->Add(pc.fHistPt[eRec]); pc.fHistPhi[eRec] = new TH1F("fHistPhi[eRec]", "phi distribution for reconstructed particles", nBinsphi, minphi, maxphi); + pc.fHistCharge[eRec] = new TH1F("fHistCharge[eRec]", "charge distribution for reconstructed particles", nBinscharge, mincharge, maxcharge); + pc.fHistTPCncls[eRec] = new TH1F("fHistTPCncls[eRec]", "tpcncls distribution for reconstructed particles", nBinstpcncls, mintpcncls, maxtpcncls); + pc.fHistTracksdcaXY[eRec] = new TH1F("fHistTracksdcaXY[eRec]", "dcaxy distribution for reconstructed particles", nBinsdcaxy, mindcaxy, maxdcaxy); + pc.fHistTracksdcaZ[eRec] = new TH1F("fHistTracksdcaZ[eRec]", "dcaz distribution for reconstructed particles", nBinsdcaz, mindcaz, maxdcaz); + pc.fHistPt[eRec]->GetXaxis()->SetTitle("p_{T}"); pc.fHistPhi[eRec]->GetXaxis()->SetTitle("phi"); + pc.fHistCharge[eRec]->GetXaxis()->SetTitle("charge"); + pc.fHistTPCncls[eRec]->GetXaxis()->SetTitle("TPCNClsFindable"); + pc.fHistTracksdcaXY[eRec]->GetXaxis()->SetTitle("DCA XY"); + pc.fHistTracksdcaZ[eRec]->GetXaxis()->SetTitle("DCA Z"); + pc.fParticleHistogramsList->Add(pc.fHistPt[eRec]); pc.fParticleHistogramsList->Add(pc.fHistPhi[eRec]); + pc.fParticleHistogramsList->Add(pc.fHistCharge[eRec]); + pc.fParticleHistogramsList->Add(pc.fHistTPCncls[eRec]); + pc.fParticleHistogramsList->Add(pc.fHistTracksdcaXY[eRec]); + pc.fParticleHistogramsList->Add(pc.fHistTracksdcaZ[eRec]); pc.fHistPt[eSim] = new TH1F("fHistPt[eSim]", "pt distribution for simulated particles", nBins, min, max); - pc.fHistPt[eSim]->GetXaxis()->SetTitle("p_{T}"); - pc.fParticleHistogramsList->Add(pc.fHistPt[eSim]); pc.fHistPhi[eSim] = new TH1F("fHistPhi[eSim]", "phi distribution for simulated particles", nBinsphi, minphi, maxphi); + pc.fHistCharge[eSim] = new TH1F("fHistCharge[eSim]", "charge distribution for simulated particles", nBinscharge, mincharge, maxcharge); + pc.fHistTPCncls[eSim] = new TH1F("fHistTPCncls[eSim]", "tpcncls distribution for simulated particles", nBinstpcncls, minphi, maxtpcncls); + pc.fHistTracksdcaXY[eSim] = new TH1F("fHistTracksdcaXY[eSim]", "dcaxy distribution for simulated particles", nBinsdcaxy, mindcaxy, maxdcaxy); + pc.fHistTracksdcaZ[eSim] = new TH1F("fHistTracksdcaZ[eSim]", "dcaz distribution for simulated particles", nBinsdcaz, mindcaz, maxdcaz); + pc.fHistPt[eSim]->GetXaxis()->SetTitle("p_{T}"); pc.fHistPhi[eSim]->GetXaxis()->SetTitle("phi"); + pc.fHistCharge[eSim]->GetXaxis()->SetTitle("charge"); + pc.fHistTPCncls[eSim]->GetXaxis()->SetTitle("TPCNClsFindable"); + pc.fHistTracksdcaXY[eSim]->GetXaxis()->SetTitle("DCA XY"); + pc.fHistTracksdcaZ[eSim]->GetXaxis()->SetTitle("DCA Z"); + pc.fParticleHistogramsList->Add(pc.fHistPt[eSim]); pc.fParticleHistogramsList->Add(pc.fHistPhi[eSim]); + pc.fParticleHistogramsList->Add(pc.fHistCharge[eSim]); + pc.fParticleHistogramsList->Add(pc.fHistTPCncls[eSim]); + pc.fParticleHistogramsList->Add(pc.fHistTracksdcaXY[eSim]); + pc.fParticleHistogramsList->Add(pc.fHistTracksdcaZ[eSim]); pc.histWeights = GetHistogramWithWeights(cfFileWithWeights.value.c_str(), "000123456"); pc.fParticleHistogramsList->Add(pc.histWeights); @@ -507,16 +645,19 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to event.fHistY[eRec] = new TH1F("fHistY[eRec]", "posY distribution for reconstructed particles", nBinsy, miny, maxy); event.fHistZ[eRec] = new TH1F("fHistZ[eRec]", "posZ distribution for reconstructed particles", nBinsz, minz, maxz); event.fHistMult[eRec] = new TH1I("fHistMult[eRec]", "mult distribution for reconstructed particles", nBinsmult, minmult, maxmult); + event.fHistNContr = new TH1I("fHistNContr", "NContr distribution", nBinsncontr, minncontr, maxncontr); event.fHistCentr[eRec]->GetXaxis()->SetTitle("centrality"); event.fHistX[eRec]->GetXaxis()->SetTitle("x"); event.fHistY[eRec]->GetXaxis()->SetTitle("y"); event.fHistZ[eRec]->GetXaxis()->SetTitle("z"); event.fHistMult[eRec]->GetXaxis()->SetTitle("multiplicity"); + event.fHistNContr->GetXaxis()->SetTitle("numContrib"); event.fEventHistogramsList->Add(event.fHistCentr[eRec]); event.fEventHistogramsList->Add(event.fHistX[eRec]); event.fEventHistogramsList->Add(event.fHistY[eRec]); event.fEventHistogramsList->Add(event.fHistZ[eRec]); event.fEventHistogramsList->Add(event.fHistMult[eRec]); + event.fEventHistogramsList->Add(event.fHistNContr); event.fHistCentr[eSim] = new TH1F("fHistCentr[eSim]", "centrality distribution for simulated particles", nBinscentr, mincentr, maxcentr); event.fHistX[eSim] = new TH1F("fHistX[eSim]", "posX distribution for simulated particles", nBinsx, minx, maxx); @@ -538,8 +679,8 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to const char* cpro[] = {"rec", "sim"}; const char* ccut[] = {"before", "after"}; for (int i = 0; i < eEventHistograms_N; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { + for (int j = 0; j < eRecAndSim; j++) { + for (int k = 0; k < eCut_N; k++) { TString histname = Form("fEventHistograms[%s][%s][%s]", cevent[i], cpro[j], ccut[k]); TString histtitle = Form("%s distribution for %s, %s cut", cevent[i], cpro[j], ccut[k]); if (i == 0) @@ -552,11 +693,34 @@ struct MultiharmonicCorrelations { // this name is used in lower-case format to } } - event.fQA = new TH2F("QA", "quality assurance", nBinscentr, mincentr, maxcentr, nBinscentr, mincentr, maxcentr); + qa.fQA = new TH2F("QA", "quality assurance", nBinscentr, mincentr, maxcentr, nBinscentr, mincentr, maxcentr); if (cfQA) { - event.fEventHistogramsList->Add(event.fQA); + qa.fQAList->Add(qa.fQA); } + // float quantiles[10] = {0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; + float quantiles[10] = {0, 5, 10, 20, 30, 40, 50, 60, 70, 80}; + cor.pv22_centr = new TProfile("pv22", "profile of v_{2}^{2}", 9, quantiles); + cor.pv32_centr = new TProfile("pv32", "profile of v_{3}^{2}", 9, quantiles); + cor.pv42_centr = new TProfile("pv42", "profile of v_{4}^{2}", 9, quantiles); + cor.pfour32_centr = new TProfile("pfour32", "profile of v_{2}^{2}*v_{3}^{2}", 9, quantiles); + cor.pfour42_centr = new TProfile("pfour42", "profile of v_{2}^{2}*v_{4}^{2}", 9, quantiles); + cor.pv22_centr->GetYaxis()->SetTitle("v_{2}^{2}"); + cor.pv32_centr->GetYaxis()->SetTitle("v_{3}^{2}"); + cor.pv42_centr->GetYaxis()->SetTitle("v_{4}^{2}"); + cor.pv22_centr->GetXaxis()->SetTitle("centrality"); + cor.pv32_centr->GetXaxis()->SetTitle("centrality"); + cor.pv42_centr->GetXaxis()->SetTitle("centrality"); + cor.pfour32_centr->GetYaxis()->SetTitle("v_{2}^{2}v_{3}^{2}"); + cor.pfour42_centr->GetYaxis()->SetTitle("v_{2}^{2}v_{4}^{2}"); + cor.pfour32_centr->GetXaxis()->SetTitle("centrality"); + cor.pfour42_centr->GetXaxis()->SetTitle("centrality"); + cor.fCorrelationVariablesList->Add(cor.pv22_centr); + cor.fCorrelationVariablesList->Add(cor.pv32_centr); + cor.fCorrelationVariablesList->Add(cor.pv42_centr); + cor.fCorrelationVariablesList->Add(cor.pfour32_centr); + cor.fCorrelationVariablesList->Add(cor.pfour42_centr); + } // end of void init(InitContext&) { // A) Process only reconstructed data: From 36a28bffe376f89ccd6bb937cdf3c1dfb2ce26ff Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 30 May 2026 17:58:40 +0200 Subject: [PATCH 357/449] [PWGEM/Dilepton] reduce data size for SCT (#16468) --- PWGEM/Dilepton/DataModel/dileptonTables.h | 11 +++-- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 27 ++++++----- PWGEM/Dilepton/Utils/ElectronModule.h | 57 ++++++++++++----------- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 27d06147986..0b57232eea5 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -691,15 +691,16 @@ DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! DECLARE_SOA_COLUMN(ProbElBDT, probElBDT, float); //! -DECLARE_SOA_COLUMN(BDTScorePromptUINT8, bdtScorePromptUINT8, std::vector); //! scaling factor is 255. +// As sum of probability is 1, keeping 3 out of 4 is enough. +// DECLARE_SOA_COLUMN(BDTScorePromptUINT8, bdtScorePromptUINT8, std::vector); //! scaling factor is 255. DECLARE_SOA_COLUMN(BDTScorePromptHcUINT8, bdtScorePromptHcUINT8, std::vector); //! scaling factor is 255. DECLARE_SOA_COLUMN(BDTScoreNonpromptHcUINT8, bdtScoreNonpromptHcUINT8, std::vector); //! scaling factor is 255. DECLARE_SOA_COLUMN(BDTScoreHbUINT8, bdtScoreHbUINT8, std::vector); //! scaling factor is 255. DECLARE_SOA_COLUMN(HadronType, hadronType, std::vector); //! 0:track, 1:K0S, 2:Lambda, 3:AntiLambda, 4:XiMinus, 5:XiPlus, 6:OmegaMinus, 7:OmegaPlus -DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](gsl::span p0, gsl::span p1, gsl::span p2, gsl::span p3, gsl::span type, const int index) -> std::array { +DECLARE_SOA_DYNAMIC_COLUMN(ProbaSCT, probaSCT, [](gsl::span p1, gsl::span p2, gsl::span p3, gsl::span type, const int index) -> std::array { return std::array{ - std::nextafter(p0[index] / 255.f, std::numeric_limits::infinity()), + 1.f - (std::nextafter(p1[index] / 255.f, std::numeric_limits::infinity()) + std::nextafter(p2[index] / 255.f, std::numeric_limits::infinity()) + std::nextafter(p3[index] / 255.f, std::numeric_limits::infinity())), std::nextafter(p1[index] / 255.f, std::numeric_limits::infinity()), std::nextafter(p2[index] / 255.f, std::numeric_limits::infinity()), std::nextafter(p3[index] / 255.f, std::numeric_limits::infinity()), @@ -1024,9 +1025,9 @@ DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBDERIVED using EMPrimaryElectronPrefilterBitDerived = EMPrimaryElectronsPrefilterBitDerived::iterator; DECLARE_SOA_TABLE(EMPrimaryElectronsBDTSCT, "AOD", "ELBDTSCT", // To be joined with EMPrimaryElectrons table at analysis level. - emprimaryelectron::BDTScorePromptUINT8, emprimaryelectron::BDTScorePromptHcUINT8, emprimaryelectron::BDTScoreNonpromptHcUINT8, emprimaryelectron::BDTScoreHbUINT8, emprimaryelectron::HadronType, + /*emprimaryelectron::BDTScorePromptUINT8,*/ emprimaryelectron::BDTScorePromptHcUINT8, emprimaryelectron::BDTScoreNonpromptHcUINT8, emprimaryelectron::BDTScoreHbUINT8, emprimaryelectron::HadronType, emprimaryelectron::NSV, - emprimaryelectron::ProbaSCT); + emprimaryelectron::ProbaSCT); // iterators using EMPrimaryElectronBDTSCT = EMPrimaryElectronsBDTSCT::iterator; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 2b1d89a4436..86dd85cd25c 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -274,6 +274,7 @@ struct taggingHFE { Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable cfg_max_massLH{"cfg_max_massLH", 1e+10, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. } lKPairCut; struct : ConfigurableGroup { @@ -281,6 +282,7 @@ struct taggingHFE { Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable cfg_max_massLH{"cfg_max_massLH", 1e+10, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. } lV0PairCut; struct : ConfigurableGroup { @@ -288,6 +290,7 @@ struct taggingHFE { Configurable cfg_min_cospa{"cfg_min_cospa", -1e+10, "min cospa"}; Configurable cfg_max_lxyz{"cfg_max_lxyz", 1e+10, "min rxy for v0hadron"}; Configurable cfg_max_chi2PCA{"cfg_max_chi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable cfg_max_massLH{"cfg_max_massLH", 1e+10, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. } lCPairCut; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -1727,7 +1730,7 @@ struct taggingHFE { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA || lKPairCut.cfg_max_massLH < eKpair.mass) { continue; } @@ -1788,7 +1791,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA || lKPairCut.cfg_max_massLH < eKpair.mass) { continue; } @@ -1858,7 +1861,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA || lV0PairCut.cfg_max_massLH < eV0pair.mass) { continue; } @@ -1937,7 +1940,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA || lV0PairCut.cfg_max_massLH < eV0pair.mass) { continue; } @@ -1999,7 +2002,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA || lCPairCut.cfg_max_massLH < eCpair.mass) { continue; } @@ -2067,7 +2070,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA || lCPairCut.cfg_max_massLH < eCpair.mass) { continue; } @@ -2163,7 +2166,7 @@ struct taggingHFE { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA || lKPairCut.cfg_max_massLH < eKpair.mass) { continue; } @@ -2225,7 +2228,7 @@ struct taggingHFE { if (!eKpair.isOK) { continue; } - if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA) { + if (eKpair.cospa < lKPairCut.cfg_min_cospa || lKPairCut.cfg_max_lxyz < eKpair.lxyz || lKPairCut.cfg_max_chi2PCA < eKpair.chi2PCA || lKPairCut.cfg_max_massLH < eKpair.mass) { continue; } @@ -2295,7 +2298,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA || lV0PairCut.cfg_max_massLH < eV0pair.mass) { continue; } @@ -2373,7 +2376,7 @@ struct taggingHFE { if (!eV0pair.isOK) { continue; } - if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA) { + if (eV0pair.cospa < lV0PairCut.cfg_min_cospa || lV0PairCut.cfg_max_lxyz < eV0pair.lxyz || lV0PairCut.cfg_max_chi2PCA < eV0pair.chi2PCA || lV0PairCut.cfg_max_massLH < eV0pair.mass) { continue; } @@ -2435,7 +2438,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA || lCPairCut.cfg_max_massLH < eCpair.mass) { continue; } @@ -2503,7 +2506,7 @@ struct taggingHFE { if (!eCpair.isOK) { continue; } - if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA) { + if (eCpair.cospa < lCPairCut.cfg_min_cospa || lCPairCut.cfg_max_lxyz < eCpair.lxyz || lCPairCut.cfg_max_chi2PCA < eCpair.chi2PCA || lCPairCut.cfg_max_massLH < eCpair.mass) { continue; } diff --git a/PWGEM/Dilepton/Utils/ElectronModule.h b/PWGEM/Dilepton/Utils/ElectronModule.h index 6b4bbfb1a3f..4360d107555 100644 --- a/PWGEM/Dilepton/Utils/ElectronModule.h +++ b/PWGEM/Dilepton/Utils/ElectronModule.h @@ -271,14 +271,15 @@ struct cfgDFeT : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeT"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; + o2::framework::Configurable maxChi2PCA{"maxChi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable maxMassLH{"maxMassLH", 5.5, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "tpcNSigmaKa", "signedMassLH", "logChi2PCA", "cpa", "cpaXY", "decayLength3DinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -288,14 +289,15 @@ struct cfgDFeV0 : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeV0"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; + o2::framework::Configurable maxChi2PCA{"maxChi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable maxMassLH{"maxMassLH", 5.5, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "logChi2PCA", "cpa", "cpaXY", "decayLength3DinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -305,14 +307,15 @@ struct cfgDFeC : o2::framework::ConfigurableGroup { std::string prefix = "cfgDFeC"; o2::framework::Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; o2::framework::Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; - o2::framework::Configurable maxDCA2legs{"maxDCA2legs", 1.0, "max distance between 2 legs in cm"}; + o2::framework::Configurable maxChi2PCA{"maxChi2PCA", 1.0, "max chi2 at PCA"}; + o2::framework::Configurable maxMassLH{"maxMassLH", 5.5, "max massLH in GeV/c2"}; // set hb mass. SVs whose mass is above this mass cannot be HF hadrons. // configuration for PID ML o2::framework::Configurable useML{"useML", false, "Flag to use PID ML"}; o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.4, 0.8, 1.0, 2.0, 4, 20}, "Bin limits for ML application"}; // o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "ML cuts per bin"}; - o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "dcaLH", "cpa", "cpaXY", "decayLength3DinSigma", "decayLengthXYinSigma"}, "Names of ML model input features"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"ptH", "impPar3DHinSigma", "massLH", "logChi2PCA", "cpa", "cpaXY", "decayLength3DinSigma"}, "Names of ML model input features"}; o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "ptL", "Names of ML model binning feature"}; o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -1632,13 +1635,13 @@ class ElectronModule products.electronPFTable(pfb); // perform SCT from here - std::vector bdtScorePrompt; + std::vector bdtScoreBkg; std::vector bdtScorePromptHc; std::vector bdtScoreNonpromptHc; std::vector bdtScoreHb; std::vector hadronType; - bdtScorePrompt.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); + bdtScoreBkg.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); bdtScorePromptHc.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); bdtScoreNonpromptHc.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); bdtScoreHb.reserve(hadronIds.size() + k0sIds.size() + lambdaIds.size() + antilambdaIds.size()); @@ -1663,7 +1666,7 @@ class ElectronModule registry.fill(HIST("SCT/eT/hCosPA"), eTpair.cospa); registry.fill(HIST("SCT/eT/hDCA2legs"), eTpair.dca2legs); registry.fill(HIST("SCT/eT/hMass"), eTpair.mass); - if (eTpair.isOK && fConfigDFeT.useML) { + if (eTpair.isOK && fConfigDFeT.useML && eTpair.chi2PCA < fConfigDFeT.maxChi2PCA && eTpair.mass < fConfigDFeT.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eTpair, hadronParCov, mDcaInfoCov); candidate.ptL = trackParCov.getPt(); @@ -1682,7 +1685,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeT.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); @@ -1716,7 +1719,7 @@ class ElectronModule registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); - if (eV0pair.isOK && fConfigDFeV0.useML) { + if (eV0pair.isOK && fConfigDFeV0.useML && eV0pair.chi2PCA < fConfigDFeV0.maxChi2PCA && eV0pair.mass < fConfigDFeV0.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); @@ -1733,7 +1736,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); @@ -1768,7 +1771,7 @@ class ElectronModule registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); - if (eV0pair.isOK && fConfigDFeV0.useML) { + if (eV0pair.isOK && fConfigDFeV0.useML && eV0pair.chi2PCA < fConfigDFeV0.maxChi2PCA && eV0pair.mass < fConfigDFeV0.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); @@ -1785,7 +1788,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); @@ -1820,7 +1823,7 @@ class ElectronModule registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); - if (eCpair.isOK && fConfigDFeC.useML) { + if (eCpair.isOK && fConfigDFeC.useML && eCpair.chi2PCA < fConfigDFeC.maxChi2PCA && eCpair.mass < fConfigDFeC.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); @@ -1837,7 +1840,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(0)); @@ -1872,7 +1875,7 @@ class ElectronModule registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); - if (eCpair.isOK && fConfigDFeC.useML) { + if (eCpair.isOK && fConfigDFeC.useML && eCpair.chi2PCA < fConfigDFeC.maxChi2PCA && eCpair.mass < fConfigDFeC.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); @@ -1889,7 +1892,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(0)); @@ -1924,7 +1927,7 @@ class ElectronModule registry.fill(HIST("SCT/eV0/hCosPA"), eV0pair.cospa); registry.fill(HIST("SCT/eV0/hDCA2legs"), eV0pair.dca2legs); registry.fill(HIST("SCT/eV0/hMass"), eV0pair.mass); - if (eV0pair.isOK && fConfigDFeV0.useML) { + if (eV0pair.isOK && fConfigDFeV0.useML && eV0pair.chi2PCA < fConfigDFeV0.maxChi2PCA && eV0pair.mass < fConfigDFeV0.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eV0pair, v0ParCov, impactParameterV0); candidate.ptL = trackParCov.getPt(); @@ -1941,7 +1944,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeV0.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(vecProb[3] * 255.f)); @@ -1976,7 +1979,7 @@ class ElectronModule registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); - if (eCpair.isOK && fConfigDFeC.useML) { + if (eCpair.isOK && fConfigDFeC.useML && eCpair.chi2PCA < fConfigDFeC.maxChi2PCA && eCpair.mass < fConfigDFeC.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); @@ -1993,7 +1996,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(0)); @@ -2028,7 +2031,7 @@ class ElectronModule registry.fill(HIST("SCT/eC/hCosPA"), eCpair.cospa); registry.fill(HIST("SCT/eC/hDCA2legs"), eCpair.dca2legs); registry.fill(HIST("SCT/eC/hMass"), eCpair.mass); - if (eCpair.isOK && fConfigDFeC.useML) { + if (eCpair.isOK && fConfigDFeC.useML && eCpair.chi2PCA < fConfigDFeC.maxChi2PCA && eCpair.mass < fConfigDFeC.maxMassLH) { o2::analysis::pwgem::dilepton::sct::candidate candidate; fillCandidate(candidate, eCpair, cascadeParCov, impactParameterCasc); candidate.ptL = trackParCov.getPt(); @@ -2045,7 +2048,7 @@ class ElectronModule } auto vecProb = mlResponseSCTeC.getModelOutput(inputFeatures, pbin); - bdtScorePrompt.emplace_back(static_cast(vecProb[0] * 255.f)); + bdtScoreBkg.emplace_back(static_cast(vecProb[0] * 255.f)); bdtScorePromptHc.emplace_back(static_cast(vecProb[1] * 255.f)); bdtScoreNonpromptHc.emplace_back(static_cast(vecProb[2] * 255.f)); bdtScoreHb.emplace_back(static_cast(0)); @@ -2054,14 +2057,14 @@ class ElectronModule } // end of Omega- loop } - products.sctTable(bdtScorePrompt, bdtScorePromptHc, bdtScoreNonpromptHc, bdtScoreHb, hadronType); + products.sctTable(/*bdtScoreBkg,*/ bdtScorePromptHc, bdtScoreNonpromptHc, bdtScoreHb, hadronType); - bdtScorePrompt.clear(); + bdtScoreBkg.clear(); bdtScorePromptHc.clear(); bdtScoreNonpromptHc.clear(); bdtScoreHb.clear(); hadronType.clear(); - bdtScorePrompt.shrink_to_fit(); + bdtScoreBkg.shrink_to_fit(); bdtScorePromptHc.shrink_to_fit(); bdtScoreNonpromptHc.shrink_to_fit(); bdtScoreHb.shrink_to_fit(); From b2e8ca08f6aeab8ba26fa25b6a49cac08610d197 Mon Sep 17 00:00:00 2001 From: losiash <57404687+losiash@users.noreply.github.com> Date: Sat, 30 May 2026 18:00:21 +0200 Subject: [PATCH 358/449] [PWGCF] Add configurable qn selector for pp ESE task (#16467) --- PWGCF/Flow/Tasks/flowFlucGfwPp.cxx | 114 ++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 25 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx index 14de3f9093e..b481ac7068b 100644 --- a/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx +++ b/PWGCF/Flow/Tasks/flowFlucGfwPp.cxx @@ -116,6 +116,9 @@ struct FlowFlucGfwPp { static constexpr int kMinTracksPerEtaSideForGapCorrelation = 2; static constexpr int kMinTracksPerEtaRegionForThreeSubevents = 2; + static constexpr int EllipticQVectorHarmonic = 2; + static constexpr int TriangularQVectorHarmonic = 3; + O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgIsMC, bool, false, "Is MC event") O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FV0A, 4:NTPV, 5:NGlobals, 6:MFT") @@ -165,7 +168,10 @@ struct FlowFlucGfwPp { O2_DEFINE_CONFIGURABLE(cfgNumQnBins, int, 10, "Number of qn bins"); O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 100, "Maximum of centrality or multiplicity"); O2_DEFINE_CONFIGURABLE(cfgEvtSelCent, bool, true, "Choose event selector as centrality(true) or multicplity(false)"); - O2_DEFINE_CONFIGURABLE(cfgUseNegativeEtaHalfForq2, bool, true, "If true, use -eta half for q2 selection; otherwise use +eta half"); + O2_DEFINE_CONFIGURABLE(cfgUseNegativeEtaHalfForq2, bool, true, "If true, use -eta half for qn selection; otherwise use +eta half"); + O2_DEFINE_CONFIGURABLE(cfgQnSelectionHarmonic, int, 2, "Harmonic n used to build the reduced q_n vector for event shape selection, use 2 for q2 and 3 for q3"); + O2_DEFINE_CONFIGURABLE(cfgQnHistMax, float, 6., "Upper range for q_n calibration histograms"); + O2_DEFINE_CONFIGURABLE(cfgBypassQnSelection, bool, false, "Bypass q_n event shape selection and fill one integral q-bin"); O2_DEFINE_CONFIGURABLE(cfgMinPtOnTPC, float, 0.2, "minimum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"); O2_DEFINE_CONFIGURABLE(cfgMaxPtOnTPC, float, 5., "maximum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"); O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8, "Maximum pseudorapidiy for charged track"); @@ -304,6 +310,11 @@ struct FlowFlucGfwPp { return "ese"; } + int getNQnOutputBins() + { + return static_cast(cfgBypassQnSelection) ? 1 : static_cast(cfgNumQnBins); + } + // region indices for consistency flag int posRegionIndex = -1; int negRegionIndex = -1; @@ -447,6 +458,17 @@ struct FlowFlucGfwPp { int ptbins = o2::analysis::gfwflowflucpp::ptbinning.size() - 1; fSecondAxis = (cfgTimeDependent) ? new TAxis(timeAxis.binEdges.size() - 1, &(timeAxis.binEdges[0])) : new TAxis(ptbins, &o2::analysis::gfwflowflucpp::ptbinning[0]); + if (static_cast(cfgBypassQnSelection)) { + LOGF(info, "Bypassing q_n event shape selection, all accepted events will be filled into the integral bin ese_0"); + if (static_cast(cfgNumQnBins) != 1) { + LOGF(warning, "cfgBypassQnSelection is on, cfgNumQnBins=%d will be ignored and only one output q-bin will be made", static_cast(cfgNumQnBins)); + } + } else { + LOGF(info, "Event-shape selector uses q_%d from the %s eta half", + static_cast(cfgQnSelectionHarmonic), + static_cast(cfgUseNegativeEtaHalfForq2) ? "negative" : "positive"); + } + if (cfgQvecQA && (doprocessData || doprocessq2)) { // qVectorsTable-equivalent TPC-track QA for the in-task raw TPC Q-vector loop. AxisSpec qVecAxisPt = {40, 0.0, 4.0}; @@ -461,11 +483,24 @@ struct FlowFlucGfwPp { } if (doprocessq2) { - registry.add("mq2/eventcounter", "", HistType::kTH1F, {{10, 0, 10}}); - registry.add("mq2/h2_cent_q2_etapos", ";Centrality;#it{q}_{2}^{#eta pos};", HistType::kTH2D, {{100, 0, 100}, {600, 0, 6}}); - registry.add("mq2/h2_cent_q2_etaneg", ";Centrality;#it{q}_{2}^{#eta neg};", HistType::kTH2D, {{100, 0, 100}, {600, 0, 6}}); - registry.add("mq2/h2_mult_q2_etapos", ";Multiplicity;#it{q}_{2}^{#eta pos};", HistType::kTH2D, {{150, 0, 150}, {600, 0, 6}}); - registry.add("mq2/h2_mult_q2_etaneg", ";Multiplicity;#it{q}_{2}^{#eta neg};", HistType::kTH2D, {{150, 0, 150}, {600, 0, 6}}); + const int qnHarmonic = static_cast(cfgQnSelectionHarmonic); + const double qnHistMax = static_cast(cfgQnHistMax); + + if (qnHarmonic == EllipticQVectorHarmonic) { + registry.add("mq2/eventcounter", "", HistType::kTH1F, {{10, 0, 10}}); + registry.add("mq2/h2_cent_q2_etapos", ";Centrality;#it{q}_{2}^{#eta pos};", HistType::kTH2D, {{100, 0, 100}, {600, 0, qnHistMax}}); + registry.add("mq2/h2_cent_q2_etaneg", ";Centrality;#it{q}_{2}^{#eta neg};", HistType::kTH2D, {{100, 0, 100}, {600, 0, qnHistMax}}); + registry.add("mq2/h2_mult_q2_etapos", ";Multiplicity;#it{q}_{2}^{#eta pos};", HistType::kTH2D, {{150, 0, 150}, {600, 0, qnHistMax}}); + registry.add("mq2/h2_mult_q2_etaneg", ";Multiplicity;#it{q}_{2}^{#eta neg};", HistType::kTH2D, {{150, 0, 150}, {600, 0, qnHistMax}}); + } + + if (qnHarmonic == TriangularQVectorHarmonic) { + registry.add("mq3/eventcounter", "", HistType::kTH1F, {{10, 0, 10}}); + registry.add("mq3/h2_cent_q3_etapos", ";Centrality;#it{q}_{3}^{#eta pos};", HistType::kTH2D, {{100, 0, 100}, {600, 0, qnHistMax}}); + registry.add("mq3/h2_cent_q3_etaneg", ";Centrality;#it{q}_{3}^{#eta neg};", HistType::kTH2D, {{100, 0, 100}, {600, 0, qnHistMax}}); + registry.add("mq3/h2_mult_q3_etapos", ";Multiplicity;#it{q}_{3}^{#eta pos};", HistType::kTH2D, {{150, 0, 150}, {600, 0, qnHistMax}}); + registry.add("mq3/h2_mult_q3_etaneg", ";Multiplicity;#it{q}_{3}^{#eta neg};", HistType::kTH2D, {{150, 0, 150}, {600, 0, qnHistMax}}); + } } if (doprocessData) { @@ -857,8 +892,9 @@ struct FlowFlucGfwPp { void addConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) { const auto shapeSel = getShapeSel(); + const int nQnOutputBins = getNQnOutputBins(); for (auto it = configs.begin(); it != configs.end(); ++it) { - for (int jese = 0; jese < cfgNumQnBins; ++jese) { + for (int jese = 0; jese < nQnOutputBins; ++jese) { std::string name = Form("%s_%d_%s", shapeSel.c_str(), jese, it->Head.c_str()); std::string title = it->Head + std::string("_ese"); oba->Add(new TNamed(name.c_str(), title.c_str())); @@ -1340,6 +1376,34 @@ struct FlowFlucGfwPp { return static_cast(diff) / 3600000.0; } + void fillQnEventCounter(float count) + { + const int qnHarmonic = static_cast(cfgQnSelectionHarmonic); + + if (qnHarmonic == EllipticQVectorHarmonic) { + registry.fill(HIST("mq2/eventcounter"), count); + } else if (qnHarmonic == TriangularQVectorHarmonic) { + registry.fill(HIST("mq3/eventcounter"), count); + } + } + + void fillQnCalibrationHistograms(float centrality, float multiplicity, float qnPos, float qnNeg) + { + const int qnHarmonic = static_cast(cfgQnSelectionHarmonic); + + if (qnHarmonic == EllipticQVectorHarmonic) { + registry.fill(HIST("mq2/h2_cent_q2_etapos"), centrality, qnPos); + registry.fill(HIST("mq2/h2_cent_q2_etaneg"), centrality, qnNeg); + registry.fill(HIST("mq2/h2_mult_q2_etapos"), multiplicity, qnPos); + registry.fill(HIST("mq2/h2_mult_q2_etaneg"), multiplicity, qnNeg); + } else if (qnHarmonic == TriangularQVectorHarmonic) { + registry.fill(HIST("mq3/h2_cent_q3_etapos"), centrality, qnPos); + registry.fill(HIST("mq3/h2_cent_q3_etaneg"), centrality, qnNeg); + registry.fill(HIST("mq3/h2_mult_q3_etapos"), multiplicity, qnPos); + registry.fill(HIST("mq3/h2_mult_q3_etaneg"), multiplicity, qnNeg); + } + } + void processData(soa::Filtered(collision, xaxis); - const auto qvecTPC = calcQVec(2, tracks, collision); - float qn = computeqnVec(qvecTPC, cfgUseNegativeEtaHalfForq2); - if (qn < 0) - return; + int qPtmp = 0; + if (!static_cast(cfgBypassQnSelection)) { + const auto qvecTPC = calcQVec(static_cast(cfgQnSelectionHarmonic), tracks, collision); + float qn = computeqnVec(qvecTPC, cfgUseNegativeEtaHalfForq2); + if (qn < 0) + return; - int qPtmp = myqnBin(cfgEvtSelCent ? xaxis.centrality : xaxis.multiplicity, - cfgCentMax, qn, qnBinSeparator, cfgNumQnBins); - if (qPtmp < 0) - return; + qPtmp = myqnBin(cfgEvtSelCent ? xaxis.centrality : xaxis.multiplicity, + cfgCentMax, qn, qnBinSeparator, cfgNumQnBins); + if (qPtmp < 0) + return; + } processCollision(collision, tracks, xaxis, run, qPtmp); } @@ -1423,18 +1490,18 @@ struct FlowFlucGfwPp { void processq2(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { float count{0.5}; - registry.fill(HIST("mq2/eventcounter"), count++); + fillQnEventCounter(count++); if (!collision.sel8()) { return; } - registry.fill(HIST("mq2/eventcounter"), count++); + fillQnEventCounter(count++); if (cfgDoOccupancySel) { int occupancy = collision.trackOccupancyInTimeRange(); if (occupancy < 0 || occupancy > cfgOccupancySelection) { return; } } - registry.fill(HIST("mq2/eventcounter"), count++); + fillQnEventCounter(count++); const XAxis xaxis{getCentrality(collision), collision.multNTracksPV(), -1.0}; if (!eventSelected(collision, xaxis.multiplicity, xaxis.centrality, -1)) @@ -1442,7 +1509,7 @@ struct FlowFlucGfwPp { const auto centr = xaxis.centrality; const auto multi = xaxis.multiplicity; - const auto qvecTPC = calcQVec(2, tracks, collision); + const auto qvecTPC = calcQVec(static_cast(cfgQnSelectionHarmonic), tracks, collision); const auto qvecPos = computeqnVec(qvecTPC, false); const auto qvecNeg = computeqnVec(qvecTPC, true); @@ -1450,13 +1517,10 @@ struct FlowFlucGfwPp { return; } - registry.fill(HIST("mq2/eventcounter"), count++); - registry.fill(HIST("mq2/h2_cent_q2_etapos"), centr, qvecPos); - registry.fill(HIST("mq2/h2_cent_q2_etaneg"), centr, qvecNeg); - registry.fill(HIST("mq2/h2_mult_q2_etapos"), multi, qvecPos); - registry.fill(HIST("mq2/h2_mult_q2_etaneg"), multi, qvecNeg); + fillQnEventCounter(count++); + fillQnCalibrationHistograms(centr, multi, qvecPos, qvecNeg); } - PROCESS_SWITCH(FlowFlucGfwPp, processq2, "Process analysis for filling q-vectors", true); + PROCESS_SWITCH(FlowFlucGfwPp, processq2, "Process analysis for filling q_n-vector calibration histograms", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 55f9e3cce046ffc6ec9d4b7792766fc8c6726f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Sat, 30 May 2026 20:58:53 +0200 Subject: [PATCH 359/449] [PWGHF] add more deuteron candidate preselection flags (#16470) --- PWGHF/D2H/Tasks/taskCd.cxx | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskCd.cxx b/PWGHF/D2H/Tasks/taskCd.cxx index d4ca3b0fbf6..a7997f5c189 100644 --- a/PWGHF/D2H/Tasks/taskCd.cxx +++ b/PWGHF/D2H/Tasks/taskCd.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file taskCd.cxx -/// \brief Cd± → d± K∓ π± analysis task +/// \brief cd± → d± K∓ π± analysis task /// \author Biao Zhang , Heidelberg Universiity #include "PWGHF/Core/CentralityEstimation.h" @@ -175,6 +175,10 @@ struct HfTaskCd { Configurable fillTHn{"fillTHn", false, "fill THn"}; Configurable fillCandLiteTree{"fillCandLiteTree", false, "Flag to fill candiates lite tree"}; Configurable fillCandFullTree{"fillCandFullTree", false, "Flag to fill candiates full tree"}; + Configurable cfgUseTofPidForDeuteron{"cfgUseTofPidForDeuteron", false, "Use TOF PID for deuteron candidates"}; + Configurable cfgCutOnDeuteronDcaOrdering{"cfgCutOnDeuteronDcaOrdering", false, "Require deuteron DCA to be smaller than kaon and pion DCAs"}; + Configurable cfgMinDeuteronDcaPreselection{"cfgMinDeuteronDcaPreselection", 0.004, "Minimum deuteron DCA for preselection (cm)"}; + Configurable cfgMaxDeuteronTofPidPreselection{"cfgMaxDeuteronTofPidPreselection", 5, "Maximum |nSigma TOF| for deuteron preselection"}; SliceCache cache; @@ -406,6 +410,7 @@ struct HfTaskCd { float nSigmaItsDe = 0.f; float nSigmaTofDe = 0.f, nSigmaTofKa = 0.f, nSigmaTofPi = 0.f; + float dcaDeuteron = 0.f, dcaKaon = 0.f, dcaPion = 0.f; // int itsNClusterSizeDe = 0; float tpcSignalsDe = 0.f; @@ -420,8 +425,8 @@ struct HfTaskCd { nSigmaTpcKa = candidate.nSigTpcKa1(); nSigmaTofKa = candidate.nSigTofKa1(); - const bool selDeKPi = (candidate.isSelCdToDeKPi() >= 1); - const bool selPiKDe = (candidate.isSelCdToPiKDe() >= 1); + const bool selDeKPi = (candidate.isSelCdToDeKPi() >= selectionFlagCd); + const bool selPiKDe = (candidate.isSelCdToPiKDe() >= selectionFlagCd); auto prong0 = candidate.template prong0_as(); auto prong1 = candidate.template prong1_as(); @@ -446,6 +451,10 @@ struct HfTaskCd { tpcSignalsDe = prong0.tpcSignal(); tpcSignalsPi = prong2.tpcSignal(); itsSignalsDe = itsSignal(prong0); + + dcaDeuteron = candidate.impactParameter0(); + dcaKaon = candidate.impactParameter1(); + dcaPion = candidate.impactParameter2(); } else if (selPiKDe) { candFlag = -1; pSignedDe = prong2.tpcInnerParam() * prong2.sign(); @@ -460,6 +469,10 @@ struct HfTaskCd { tpcSignalsDe = prong2.tpcSignal(); tpcSignalsPi = prong0.tpcSignal(); itsSignalsDe = itsSignal(prong2); + + dcaDeuteron = candidate.impactParameter2(); + dcaKaon = candidate.impactParameter1(); + dcaPion = candidate.impactParameter0(); } // PID QA @@ -476,6 +489,15 @@ struct HfTaskCd { registry.fill(HIST("Data/hNsigmaTPCKaVsP"), prong1.tpcInnerParam() * prong1.sign(), nSigmaTpcKa); registry.fill(HIST("Data/hNsigmaTOFKaVsP"), prong1.tpcInnerParam() * prong1.sign(), nSigmaTofKa); + if (cfgUseTofPidForDeuteron && std::abs(nSigmaTofDe) > cfgMaxDeuteronTofPidPreselection) { + continue; + } + if (std::abs(dcaDeuteron) < cfgMinDeuteronDcaPreselection) { + continue; + } + if (cfgCutOnDeuteronDcaOrdering && (std::abs(dcaDeuteron) > std::abs(dcaKaon) || std::abs(dcaDeuteron) > std::abs(dcaPion))) { + continue; + } if (fillCandLiteTree) { rowCandCdLite( From ed60376011254760a60ec5a94e9ce4a01651d767 Mon Sep 17 00:00:00 2001 From: bhattdurgesh921-sys Date: Sun, 31 May 2026 01:12:33 +0530 Subject: [PATCH 360/449] [PWGLF] added pt dependent cuts and configurables for qa plots . (#16469) --- PWGLF/Tasks/Resonances/CMakeLists.txt | 4 +- PWGLF/Tasks/Resonances/deltaAnalysis.cxx | 1116 ++++++++++++++++++++++ PWGLF/Tasks/Resonances/deltaanalysis.cxx | 613 ------------ 3 files changed, 1118 insertions(+), 615 deletions(-) create mode 100644 PWGLF/Tasks/Resonances/deltaAnalysis.cxx delete mode 100644 PWGLF/Tasks/Resonances/deltaanalysis.cxx diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 1dd8a1015d8..74c48c0872a 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -94,8 +94,8 @@ o2physics_add_dpl_workflow(lambda1520spherocityanalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(delta-analysis - SOURCES deltaanalysis.cxx +o2physics_add_dpl_workflow(deltaanalysis + SOURCES deltaAnalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/deltaAnalysis.cxx b/PWGLF/Tasks/Resonances/deltaAnalysis.cxx new file mode 100644 index 00000000000..c2cc29ac62d --- /dev/null +++ b/PWGLF/Tasks/Resonances/deltaAnalysis.cxx @@ -0,0 +1,1116 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file deltaanalysis.cxx +/// \brief Delta(1232) resonance analysis via proton-pion invariant mass reconstruction with advance PID and background rejection cuts +/// \author Durgesh Bhatt + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +namespace +{ +constexpr float massProton = o2::constants::physics::MassProton; +constexpr float massPion = o2::constants::physics::MassPionCharged; +} // namespace +namespace delta_analysis +{ +static constexpr int PdgProton{2212}; +static constexpr int PdgPion{211}; +static constexpr int PdgDeltaPlusPlus{2224}; +static constexpr int PdgDeltaZero{2114}; + +enum CentEstimator : int { + kFT0M = 0, + kFT0A = 1, + kFT0C = 2, + kFV0A = 3, + kNTPV = 4 +}; +} // namespace delta_analysis + +struct DeltaAnalysis { + + SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // FIX name/configurable: single space between type and name; member name == JSON key; lowerCamelCase + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted |z-vertex| range [cm]"}; + Configurable applyOccupancyInTimeRangeCut{"applyOccupancyInTimeRangeCut", false, "Apply occupancy-in-time-range cut"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", 0, "Minimum track occupancy in time range"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 9999, "Maximum track occupancy in time range"}; + + Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 0, "Centrality estimator: 0=FT0M 1=FT0A 2=FT0C 3=FV0A 4=NTPV"}; + Configurable cfgCentMin{"cfgCentMin", 0.f, "Minimum centrality percentile"}; + Configurable cfgCentMax{"cfgCentMax", 100.f, "Maximum centrality percentile"}; + + Configurable cfgCutPt{"cfgCutPt", 0.2f, "Minimum pT of daughter track [GeV/c]"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Maximum |eta| of daughter track"}; + // CHANGED: replaced single symmetric cfgCutY with independent cfgMinY / cfgMaxY + Configurable cfgMinY{"cfgMinY", -0.5f, "Minimum rapidity of reconstructed Delta"}; + Configurable cfgMaxY{"cfgMaxY", 0.5f, "Maximum rapidity of reconstructed Delta"}; + + Configurable cfgMinITSClusters{"cfgMinITSClusters", 5, "Minimum ITS clusters"}; + Configurable cfgMinTPCClusters{"cfgMinTPCClusters", 70, "Minimum TPC clusters found"}; + Configurable numberOfInvMassBins{"numberOfInvMassBins", 120, "Number of bins along the invariant mass axis"}; + Configurable cfgMinTPCCrossedRows{"cfgMinTPCCrossedRows", 70, "Minimum TPC crossed pad rows"}; + Configurable cfgMinCrossedRowsOverFindable{"cfgMinCrossedRowsOverFindable", 0.8f, "Minimum ratio crossedRows/findableClusters"}; + Configurable cfgMaxTPCSharedClusters{"cfgMaxTPCSharedClusters", 0, "Maximum TPC shared clusters"}; + Configurable cfgMaxTPCChi2NCl{"cfgMaxTPCChi2NCl", 4.0f, "Maximum TPC chi2/NCl"}; + Configurable cfgMaxITSChi2NCl{"cfgMaxITSChi2NCl", 36.0f, "Maximum ITS chi2/NCl"}; + Configurable requirePrimaryTrack{"requirePrimaryTrack", true, "Require isPrimaryTrack flag"}; + Configurable requireGlobalTrackNoDCA{"requireGlobalTrackNoDCA", true, "Require isGlobalTrackWoDCA flag"}; + Configurable requirePVContributor{"requirePVContributor", true, "Require PV-contributor flag"}; + + Configurable cfgCutDCAz{"cfgCutDCAz", 0.1f, "Maximum |DCAz| for all tracks [cm]"}; + Configurable> protonDCAPtBinEdges{"protonDCAPtBinEdges", {0.0f, 0.5f, 1.0f, 2.0f, 1000.f}, "Proton pT bin edges for DCAxy cut [GeV/c]"}; + Configurable> protonMaxDCAxyPerPtBin{"protonMaxDCAxyPerPtBin", {0.10f, 0.08f, 0.05f, 0.05f}, "Max |DCAxy| for proton per pT bin [cm]"}; + Configurable> pionDCAPtBinEdges{"pionDCAPtBinEdges", {0.0f, 0.5f, 1.0f, 2.0f, 1000.f}, "Pion pT bin edges for DCAxy cut [GeV/c]"}; + Configurable> pionMaxDCAxyPerPtBin{"pionMaxDCAxyPerPtBin", {0.20f, 0.15f, 0.10f, 0.08f}, "Max |DCAxy| for pion per pT bin [cm]"}; + + Configurable useTPCOnlyPID{"useTPCOnlyPID", false, "Use TPC-only PID (ignore TOF even if present)"}; + Configurable requireTOFForProton{"requireTOFForProton", false, "Require TOF signal for proton candidates"}; + Configurable requireTOFForPion{"requireTOFForPion", false, "Require TOF signal for pion candidates"}; + + Configurable minProtonMomentum{"minProtonMomentum", 0.f, "Minimum proton momentum for TOF PID [GeV/c]"}; + Configurable minTPCNSigmaProton{"minTPCNSigmaProton", -6.0f, "Minimum (lower bound) TPC nSigma for proton"}; + Configurable minTOFNSigmaProton{"minTOFNSigmaProton", -6.0f, "Minimum (lower bound) TOF nSigma for proton"}; + Configurable minCombinedNSigmaProton{"minCombinedNSigmaProton", -6.0f, "Minimum combined nSigma for proton (asymmetric mode)"}; + Configurable maxTPCNSigmaProton{"maxTPCNSigmaProton", 3.0, "Maximum |TPC nSigma| for proton"}; + Configurable combinedNSigmaCutProton{"combinedNSigmaCutProton", 3.0, "Circular TPC+TOF combined nSigma cut for proton. Negative = asymmetric mode."}; + Configurable> protonTPCPIDMomentumBins{"protonTPCPIDMomentumBins", {0.f, 0.5f, 0.7f, 0.8f}, "Proton TPC PID momentum bin edges [GeV/c]"}; + Configurable> protonTPCNSigmaCutPerBin{"protonTPCNSigmaCutPerBin", {5.f, 3.5f, 2.5f}, "Maximum TPC nSigma for proton per momentum bin"}; + Configurable> protonTOFPIDMomentumBins{"protonTOFPIDMomentumBins", {0.f, 999.f}, "Proton TOF PID momentum bin edges [GeV/c]"}; + Configurable> protonTOFNSigmaCutPerBin{"protonTOFNSigmaCutPerBin", {3.0f}, "Maximum TOF nSigma for proton per momentum bin"}; + + Configurable minPionMomentum{"minPionMomentum", 0.f, "Minimum pion momentum for TOF PID [GeV/c]"}; + Configurable minTPCNSigmaPion{"minTPCNSigmaPion", -6.0f, "Minimum (lower bound) TPC nSigma for pion"}; + Configurable minTOFNSigmaPion{"minTOFNSigmaPion", -6.0f, "Minimum (lower bound) TOF nSigma for pion"}; + Configurable minCombinedNSigmaPion{"minCombinedNSigmaPion", -6.0f, "Minimum combined nSigma for pion (asymmetric mode)"}; + Configurable maxTPCNSigmaPion{"maxTPCNSigmaPion", 3.0, "Maximum |TPC nSigma| for pion"}; + Configurable combinedNSigmaCutPion{"combinedNSigmaCutPion", 3.0, "Circular TPC+TOF combined nSigma cut for pion. Negative = asymmetric mode."}; + Configurable> pionTPCPIDMomentumBins{"pionTPCPIDMomentumBins", {0.f, 0.25f, 0.4f, 0.5f}, "Pion TPC PID momentum bin edges [GeV/c]"}; + Configurable> pionTPCNSigmaCutPerBin{"pionTPCNSigmaCutPerBin", {5.f, 3.5f, 2.5f}, "Maximum TPC nSigma for pion per momentum bin"}; + Configurable> pionTOFPIDMomentumBins{"pionTOFPIDMomentumBins", {0.f, 999.f}, "Pion TOF PID momentum bin edges [GeV/c]"}; + Configurable> pionTOFNSigmaCutPerBin{"pionTOFNSigmaCutPerBin", {3.0f}, "Maximum TOF nSigma for pion per momentum bin"}; + + Configurable tpcNSigmaVetoThreshold{"tpcNSigmaVetoThreshold", 3.0f, "Reject track if TPC nSigma of a competing species is below this value"}; + Configurable tofNSigmaVetoThreshold{"tofNSigmaVetoThreshold", 3.0f, "Reject track if TOF nSigma of a competing species is below this value"}; + + Configurable applyDeepAngleCut{"applyDeepAngleCut", false, "Apply minimum opening-angle cut (removes split-track background)"}; + Configurable deepAngleCutValue{"deepAngleCutValue", 0.04, "Minimum opening angle between proton and pion [rad]"}; + + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per signal event"}; + + Configurable enableRotationalBackground{"enableRotationalBackground", false, "Compute rotational background by rotating pion phi near PI"}; + Configurable numberOfRotations{"numberOfRotations", 10, "Number of pion-phi rotations for background"}; + Configurable rotationAngleWindow{"rotationAngleWindow", 6.f, "Pion rotated by angles within PI +/- PI/rotationAngleWindow"}; + + ConfigurableAxis cfgPtAxis{"cfgPtAxis", {VARIABLE_WIDTH, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4.0, 5.0, 7.0, 10.0}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis cfgCentAxis{"cfgCentAxis", {VARIABLE_WIDTH, 0.f, 10.f, 20.f, 30.f, 40.f, 50.f, 60.f, 70.f, 80.f, 90.f, 100.f}, "Centrality (%)"}; + ConfigurableAxis cfgVtxAxis{"cfgVtxAxis", {VARIABLE_WIDTH, -12.f, -10.f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 12.f}, "Vertex z [cm]"}; + ConfigurableAxis cfgRapAxis{"cfgRapAxis", {20, -1.0, 1.0}, "Rapidity y"}; + + std::vector mProtonTPCMomBins{}; + std::vector mProtonTPCNSigCuts{}; + std::vector mProtonTOFMomBins{}; + std::vector mProtonTOFNSigCuts{}; + std::vector mPionTPCMomBins{}; + std::vector mPionTPCNSigCuts{}; + std::vector mPionTOFMomBins{}; + std::vector mPionTOFNSigCuts{}; + std::vector mProtonDCAPtEdges{}; + std::vector mProtonMaxDCAxy{}; + std::vector mPionDCAPtEdges{}; + std::vector mPionMaxDCAxy{}; + + void init(InitContext const&) + { + auto chkSz = [](auto const& cuts, auto const& bins, const char* label) { + const auto& cutsVec = cuts.value; + const auto& binsVec = bins.value; + if (cutsVec.size() != binsVec.size() - 1) { + LOG(fatal) << "PID/DCA bin-size mismatch for: " << label + << " (cuts=" << cutsVec.size() + << ", bins=" << binsVec.size() << ")"; + } + }; + chkSz(protonTPCNSigmaCutPerBin, protonTPCPIDMomentumBins, "proton TPC PID"); + chkSz(protonTOFNSigmaCutPerBin, protonTOFPIDMomentumBins, "proton TOF PID"); + chkSz(pionTPCNSigmaCutPerBin, pionTPCPIDMomentumBins, "pion TPC PID"); + chkSz(pionTOFNSigmaCutPerBin, pionTOFPIDMomentumBins, "pion TOF PID"); + chkSz(protonMaxDCAxyPerPtBin, protonDCAPtBinEdges, "proton DCA"); + chkSz(pionMaxDCAxyPerPtBin, pionDCAPtBinEdges, "pion DCA"); + + mProtonTPCMomBins = protonTPCPIDMomentumBins.value; + mProtonTPCNSigCuts = protonTPCNSigmaCutPerBin.value; + mProtonTOFMomBins = protonTOFPIDMomentumBins.value; + mProtonTOFNSigCuts = protonTOFNSigmaCutPerBin.value; + mPionTPCMomBins = pionTPCPIDMomentumBins.value; + mPionTPCNSigCuts = pionTPCNSigmaCutPerBin.value; + mPionTOFMomBins = pionTOFPIDMomentumBins.value; + mPionTOFNSigCuts = pionTOFNSigmaCutPerBin.value; + mProtonDCAPtEdges = protonDCAPtBinEdges.value; + mProtonMaxDCAxy = protonMaxDCAxyPerPtBin.value; + mPionDCAPtEdges = pionDCAPtBinEdges.value; + mPionMaxDCAxy = pionMaxDCAxyPerPtBin.value; + + const AxisSpec ptAxis{200, 0., 10., "p_{T} (GeV/c)"}; + const AxisSpec massAxis{numberOfInvMassBins, 0.8, 1.8, "M_{inv} (GeV/#it{c}^{2})"}; + const AxisSpec centAxis{cfgCentAxis, "Centrality (%)"}; + const AxisSpec vtxAxis{cfgVtxAxis, "Vertex z [cm]"}; + const AxisSpec rapAxis{cfgRapAxis, "Rapidity y"}; + const AxisSpec nSigmaTPCaxis{100, -10., 10., "n#sigma^{TPC}"}; + const AxisSpec nSigmaTOFaxis{100, -10., 10., "n#sigma^{TOF}"}; + const AxisSpec momentumAxis{200, 0., 10., "p (GeV/#it{c})"}; + const AxisSpec ptForPIDAxis{200, 0., 10., "p_{T} (GeV/#it{c})"}; + const AxisSpec dcaXYaxis{200, -0.2f, 0.2f, "DCA_{xy} (cm)"}; + const AxisSpec dcaZaxis{200, -1.2f, 1.2f, "DCA_{z} (cm)"}; + const AxisSpec tpcClusAxis{200, 0, 200, "N_{clusters}^{TPC}"}; + const AxisSpec tpcRowsAxis{200, 0, 200, "Crossed rows^{TPC}"}; + const AxisSpec occupancyAxis{200, 0, 10000, "Track occupancy [-40, 100] ns"}; + const AxisSpec etaAxis{100, -1.0, 1.0, "#eta"}; + const AxisSpec openAngleAxis{100, 0., o2::constants::math::PI, "Opening angle (rad)"}; + + histos.add("Event/hVtxZ", "Vertex z; z (cm)", kTH1F, {{400, -20., 20.}}); + histos.add("Event/hNcontributor", "PV contributors; N", kTH1F, {{2001, -0.5f, 2000.5f}}); + histos.add("Event/hCentrality", "Centrality", kTH1F, {centAxis}); + histos.add("Event/hOccupancy", "Occupancy in time range", kTH1F, {occupancyAxis}); + + histos.add("CentQA/hCentralityVsVtxZ", "Centrality vs vertex z", kTH2F, {vtxAxis, centAxis}); + histos.add("CentQA/hCentralityVsOccupancy", "Centrality vs occupancy", kTH2F, {occupancyAxis, centAxis}); + histos.add("CentQA/hEventCountVsCentrality", "Event count vs centrality", kTH1F, {centAxis}); + + histos.add("OccupancyQA/hOccupancyVsCentralityBefore", "Occupancy vs centrality (before cut)", kTH2F, {centAxis, occupancyAxis}); + histos.add("OccupancyQA/hOccupancyVsVtxZBefore", "Occupancy vs vertex z (before cut)", kTH2F, {vtxAxis, occupancyAxis}); + histos.add("OccupancyQA/hOccupancyVsCentralityAfter", "Occupancy vs centrality (after cut)", kTH2F, {centAxis, occupancyAxis}); + histos.add("OccupancyQA/hOccupancyVsVtxZAfter", "Occupancy vs vertex z (after cut)", kTH2F, {vtxAxis, occupancyAxis}); + + histos.add("QAbefore/Proton/tpcNSigmaVsMomentum", "TPC n#sigma proton vs p (before cuts)", kTH2F, {momentumAxis, nSigmaTPCaxis}); + histos.add("QAbefore/Proton/tofNSigmaVsMomentum", "TOF n#sigma proton vs p (before cuts)", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAbefore/Proton/tofNSigmaVsTPCNSigma", "TOF vs TPC n#sigma proton (before cuts)", kTH2F, {nSigmaTPCaxis, nSigmaTOFaxis}); + histos.add("QAbefore/Pion/tpcNSigmaVsMomentum", "TPC n#sigma pion vs p (before cuts)", kTH2F, {momentumAxis, nSigmaTPCaxis}); + histos.add("QAbefore/Pion/tofNSigmaVsMomentum", "TOF n#sigma pion vs p (before cuts)", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAbefore/Pion/tofNSigmaVsTPCNSigma", "TOF vs TPC n#sigma pion (before cuts)", kTH2F, {nSigmaTPCaxis, nSigmaTOFaxis}); + + histos.add("QAafter/Proton/dcaXYvsPt", "Proton DCA_{xy} vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, dcaXYaxis}); + histos.add("QAafter/Proton/dcaZvsPt", "Proton DCA_{z} vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, dcaZaxis}); + histos.add("QAafter/Proton/tpcNSigmaVsMomentum", "Proton TPC n#sigma vs p (after cuts)", kTH2F, {momentumAxis, nSigmaTPCaxis}); + histos.add("QAafter/Proton/tpcNSigmaVsPt", "Proton TPC n#sigma vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Proton/tpcNSigmaVsCentrality", "Proton TPC n#sigma vs centrality", kTH2F, {centAxis, nSigmaTPCaxis}); + histos.add("QAafter/Proton/tofNSigmaVsMomentum", "Proton TOF n#sigma vs p (after cuts)", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAafter/Proton/tofNSigmaVsPt", "Proton TOF n#sigma vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, nSigmaTOFaxis}); + histos.add("QAafter/Proton/tofNSigmaVsCentrality", "Proton TOF n#sigma vs centrality", kTH2F, {centAxis, nSigmaTOFaxis}); + histos.add("QAafter/Proton/tofNSigmaVsTPCNSigma", "Proton TOF vs TPC n#sigma (after cuts)", kTH2F, {nSigmaTPCaxis, nSigmaTOFaxis}); + histos.add("QAafter/Proton/tpcNSigmaPionContamVsPt", "Proton track: TPC n#sigma pion contamination", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Proton/tpcNSigmaKaonContamVsPt", "Proton track: TPC n#sigma kaon contamination", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Proton/tofNSigmaPionContamVsMomentum", "Proton track: TOF n#sigma pion contamination", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAafter/Proton/tpcCrossedRowsVsPt", "Proton TPC crossed rows vs p_{T}", kTH2F, {ptForPIDAxis, tpcRowsAxis}); + histos.add("QAafter/Proton/tpcClustersFoundVsPt", "Proton TPC clusters found vs p_{T}", kTH2F, {ptForPIDAxis, tpcClusAxis}); + histos.add("QAafter/Proton/dcaXYdist", "Proton DCA_{xy} distribution (fine bins)", kTH1F, {dcaXYaxis}); + histos.add("QAafter/Proton/dcaZdist", "Proton DCA_{z} distribution (fine bins)", kTH1F, {dcaZaxis}); + + histos.add("QAafter/Pion/dcaXYvsPt", "Pion DCA_{xy} vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, dcaXYaxis}); + histos.add("QAafter/Pion/dcaZvsPt", "Pion DCA_{z} vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, dcaZaxis}); + histos.add("QAafter/Pion/tpcNSigmaVsMomentum", "Pion TPC n#sigma vs p (after cuts)", kTH2F, {momentumAxis, nSigmaTPCaxis}); + histos.add("QAafter/Pion/tpcNSigmaVsPt", "Pion TPC n#sigma vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Pion/tpcNSigmaVsCentrality", "Pion TPC n#sigma vs centrality", kTH2F, {centAxis, nSigmaTPCaxis}); + histos.add("QAafter/Pion/tofNSigmaVsMomentum", "Pion TOF n#sigma vs p (after cuts)", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAafter/Pion/tofNSigmaVsPt", "Pion TOF n#sigma vs p_{T} (after cuts)", kTH2F, {ptForPIDAxis, nSigmaTOFaxis}); + histos.add("QAafter/Pion/tofNSigmaVsCentrality", "Pion TOF n#sigma vs centrality", kTH2F, {centAxis, nSigmaTOFaxis}); + histos.add("QAafter/Pion/tofNSigmaVsTPCNSigma", "Pion TOF vs TPC n#sigma (after cuts)", kTH2F, {nSigmaTPCaxis, nSigmaTOFaxis}); + histos.add("QAafter/Pion/tpcNSigmaProtonContamVsPt", "Pion track: TPC n#sigma proton contamination", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Pion/tpcNSigmaKaonContamVsPt", "Pion track: TPC n#sigma kaon contamination", kTH2F, {ptForPIDAxis, nSigmaTPCaxis}); + histos.add("QAafter/Pion/tofNSigmaProtonContamVsMomentum", "Pion track: TOF n#sigma proton contamination", kTH2F, {momentumAxis, nSigmaTOFaxis}); + histos.add("QAafter/Pion/tpcCrossedRowsVsPt", "Pion TPC crossed rows vs p_{T}", kTH2F, {ptForPIDAxis, tpcRowsAxis}); + histos.add("QAafter/Pion/tpcClustersFoundVsPt", "Pion TPC clusters found vs p_{T}", kTH2F, {ptForPIDAxis, tpcClusAxis}); + histos.add("QAafter/Pion/dcaXYdist", "Pion DCA_{xy} distribution (fine bins)", kTH1F, {dcaXYaxis}); + histos.add("QAafter/Pion/dcaZdist", "Pion DCA_{z} distribution (fine bins)", kTH1F, {dcaZaxis}); + + histos.add("QAChecks/Pair/hOpeningAngleBefore", "Opening angle (before cuts)", kTH1F, {openAngleAxis}); + histos.add("QAChecks/Pair/hOpeningAngleAfter", "Opening angle (after cuts)", kTH1F, {openAngleAxis}); + + histos.add("Analysis/hDeltaPlusPlusInvMass", "#Delta^{++} (#rightarrow p + #pi^{+}) invariant mass", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaPlusPlusInvMass", "#bar{#Delta}^{++} (#rightarrow #bar{p} + #pi^{-}) invariant mass", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaZeroInvMass", "#Delta^{0} (#rightarrow p + #pi^{-}) invariant mass", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaZeroInvMass", "#bar{#Delta}^{0} (#rightarrow #bar{p} + #pi^{+}) invariant mass", kTH2F, {ptAxis, massAxis}); + + if (enableRotationalBackground) { + histos.add("Analysis/hDeltaPlusPlusInvMassRot", "#Delta^{++} invariant mass - rotational background", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaPlusPlusInvMassRot", "#bar{#Delta}^{++} invariant mass - rotational background", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaZeroInvMassRot", "#Delta^{0} invariant mass - rotational background", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaZeroInvMassRot", "#bar{#Delta}^{0} invariant mass - rotational background", kTH2F, {ptAxis, massAxis}); + } + + if (doprocessMixedEvent) { + histos.add("Analysis/hDeltaPlusPlusInvMassEM", "#Delta^{++} invariant mass - event mixing", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaPlusPlusInvMassEM", "#bar{#Delta}^{++} invariant mass - event mixing", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaZeroInvMassEM", "#Delta^{0} invariant mass - event mixing", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaZeroInvMassEM", "#bar{#Delta}^{0} invariant mass - event mixing", kTH2F, {ptAxis, massAxis}); + } + + histos.add("THnSparse/hDeltaPlusPlus", "THnSparse #Delta^{++} same-event", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaPlusPlus", "THnSparse #bar{#Delta}^{++} same-event", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaZero", "THnSparse #Delta^{0} same-event", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaZero", "THnSparse #bar{#Delta}^{0} same-event", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + + if (enableRotationalBackground) { + histos.add("THnSparse/hDeltaPlusPlusRot", "THnSparse #Delta^{++} rotational background", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaPlusPlusRot", "THnSparse #bar{#Delta}^{++} rotational background", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaZeroRot", "THnSparse #Delta^{0} rotational background", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaZeroRot", "THnSparse #bar{#Delta}^{0} rotational background", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + } + + if (doprocessMixedEvent) { + histos.add("THnSparse/hDeltaPlusPlusEM", "THnSparse #Delta^{++} event mixing", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaPlusPlusEM", "THnSparse #bar{#Delta}^{++} event mixing", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaZeroEM", "THnSparse #Delta^{0} event mixing", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaZeroEM", "THnSparse #bar{#Delta}^{0} event mixing", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + } + + if (doprocessMC) { + histos.add("THnSparse/hDeltaPlusPlusMC", "THnSparse #Delta^{++} MC reconstructed", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaPlusPlusMC", "THnSparse #bar{#Delta}^{++} MC reconstructed", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaZeroMC", "THnSparse #Delta^{0} MC reconstructed", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaZeroMC", "THnSparse #bar{#Delta}^{0} MC reconstructed", kTHnSparseF, {massAxis, ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaPlusPlusGen", "THnSparse #Delta^{++} generated", kTHnSparseF, {ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaPlusPlusGen", "THnSparse #bar{#Delta}^{++} generated", kTHnSparseF, {ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hDeltaZeroGen", "THnSparse #Delta^{0} generated", kTHnSparseF, {ptAxis, centAxis, rapAxis}); + histos.add("THnSparse/hAntiDeltaZeroGen", "THnSparse #bar{#Delta}^{0} generated", kTHnSparseF, {ptAxis, centAxis, rapAxis}); + + histos.add("Analysis/hDeltaPlusPlusInvMassMC", "#Delta^{++} invariant mass (MC truth-matched)", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaPlusPlusInvMassMC", "#bar{#Delta}^{++} invariant mass (MC truth-matched)", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaZeroInvMassMC", "#Delta^{0} invariant mass (MC truth-matched)", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaZeroInvMassMC", "#bar{#Delta}^{0} invariant mass (MC truth-matched)", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaPlusPlusInvMassGen", "#Delta^{++} invariant mass - generated", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaPlusPlusInvMassGen", "#bar{#Delta}^{++} invariant mass - generated", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hDeltaZeroInvMassGen", "#Delta^{0} invariant mass - generated", kTH2F, {ptAxis, massAxis}); + histos.add("Analysis/hAntiDeltaZeroInvMassGen", "#bar{#Delta}^{0} invariant mass - generated", kTH2F, {ptAxis, massAxis}); + + histos.add("QAChecks/hRecProtonDeltaPlusPlus", "Rec proton from #Delta^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecProtonAntiDeltaPlusPlus", "Rec proton from #bar{#Delta}^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecProtonDeltaZero", "Rec proton from #Delta^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecProtonAntiDeltaZero", "Rec proton from #bar{#Delta}^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecPionDeltaPlusPlus", "Rec pion from #Delta^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecPionAntiDeltaPlusPlus", "Rec pion from #bar{#Delta}^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecPionDeltaZero", "Rec pion from #Delta^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hRecPionAntiDeltaZero", "Rec pion from #bar{#Delta}^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenProtonDeltaPlusPlus", "Gen proton from #Delta^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenProtonAntiDeltaPlusPlus", "Gen proton from #bar{#Delta}^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenProtonDeltaZero", "Gen proton from #Delta^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenProtonAntiDeltaZero", "Gen proton from #bar{#Delta}^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenPionDeltaPlusPlus", "Gen pion from #Delta^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenPionAntiDeltaPlusPlus", "Gen pion from #bar{#Delta}^{++}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenPionDeltaZero", "Gen pion from #Delta^{0}", kTH1F, {ptAxis}); + histos.add("QAChecks/hGenPionAntiDeltaZero", "Gen pion from #bar{#Delta}^{0}", kTH1F, {ptAxis}); + } + } // end init() + + template + float getCentrality(CollisionType const& collision) + { + switch (cfgCentralityEstimator) { + case delta_analysis::kFT0M: + return collision.centFT0M(); + case delta_analysis::kFT0A: + return collision.centFT0A(); + case delta_analysis::kFT0C: + return collision.centFT0C(); + case delta_analysis::kFV0A: + return collision.centFV0A(); + case delta_analysis::kNTPV: + return collision.centNTPV(); + default: + return collision.centFT0M(); + } + } + + template + bool passesEventSelection(CollisionType const& collision) + { + if (!collision.sel8()) + return false; + if (std::abs(collision.posZ()) > cfgCutVertex) + return false; + if (applyOccupancyInTimeRangeCut) { + const int occ = collision.trackOccupancyInTimeRange(); + if (occ < cfgOccupancyMin || occ > cfgOccupancyMax) + return false; + } + const float cent = getCentrality(collision); + if (cent < cfgCentMin || cent > cfgCentMax) + return false; + return true; + } + + template + bool passesBasicTrackSelection(TrackType const& track) + { + if (track.itsNCls() < cfgMinITSClusters) + return false; + if (track.tpcNClsShared() > cfgMaxTPCSharedClusters) + return false; + if (track.tpcNClsFound() < cfgMinTPCClusters) + return false; + if (track.tpcNClsCrossedRows() < cfgMinTPCCrossedRows) + return false; + if (track.tpcNClsCrossedRows() < cfgMinCrossedRowsOverFindable * track.tpcNClsFindable()) + return false; + if (track.tpcChi2NCl() > cfgMaxTPCChi2NCl) + return false; + if (track.itsChi2NCl() > cfgMaxITSChi2NCl) + return false; + if (requirePrimaryTrack && !track.isPrimaryTrack()) + return false; + if (requireGlobalTrackNoDCA && !track.isGlobalTrackWoDCA()) + return false; + if (requirePVContributor && !track.isPVContributor()) + return false; + return true; + } + + template + bool passesProtonDCASelection(TrackType const& track) + { + const int nBins = static_cast(mProtonDCAPtEdges.size()) - 1; + const float pt = track.pt(); + bool passed = false; + for (int i = 0; i < nBins; ++i) { + if (pt >= mProtonDCAPtEdges[i] && pt < mProtonDCAPtEdges[i + 1] && + std::abs(track.dcaXY()) < mProtonMaxDCAxy[i]) { + passed = true; + break; + } + } + return passed && (std::abs(track.dcaZ()) < cfgCutDCAz); + } + + template + bool passesPionDCASelection(TrackType const& track) + { + const int nBins = static_cast(mPionDCAPtEdges.size()) - 1; + const float pt = track.pt(); + bool passed = false; + for (int i = 0; i < nBins; ++i) { + if (pt >= mPionDCAPtEdges[i] && pt < mPionDCAPtEdges[i + 1] && + std::abs(track.dcaXY()) < mPionMaxDCAxy[i]) { + passed = true; + break; + } + } + return passed && (std::abs(track.dcaZ()) < cfgCutDCAz); + } + + template + bool passesProtonPID(TrackType const& track, float totalMomentum) + { + bool tpcPassed{false}, tofPassed{false}; + const int nTPCBins = static_cast(mProtonTPCMomBins.size()); + const int nTOFBins = static_cast(mProtonTOFMomBins.size()); + const float tpcNSigPi = std::abs(track.tpcNSigmaPi()); + const float tpcNSigPr = std::abs(track.tpcNSigmaPr()); + const float tofNSigPi = std::abs(track.tofNSigmaPi()); + const float tofNSigPr = std::abs(track.tofNSigmaPr()); + const float combinedNSigPr = tpcNSigPr * tpcNSigPr + tofNSigPr * tofNSigPr; + const float combinedNSigPi = tpcNSigPi * tpcNSigPi + tofNSigPi * tofNSigPi; + const float circularCutSq = static_cast(combinedNSigmaCutProton * combinedNSigmaCutProton); + + const float circularVetoCutSq = tpcNSigmaVetoThreshold * tpcNSigmaVetoThreshold + tofNSigmaVetoThreshold * tofNSigmaVetoThreshold; + + if (!useTPCOnlyPID && track.hasTOF()) { + if (combinedNSigmaCutProton < 0 && totalMomentum >= minProtonMomentum) { + if (track.tofNSigmaPr() < minTOFNSigmaProton) + return false; + for (int i = 0; i < nTOFBins - 1; ++i) { + if (totalMomentum >= mProtonTOFMomBins[i] && totalMomentum < mProtonTOFMomBins[i + 1] && + tofNSigPr < mProtonTOFNSigCuts[i] && tofNSigPi > tofNSigmaVetoThreshold) { + tofPassed = true; + break; + } + } + if (track.tpcNSigmaPr() < minCombinedNSigmaProton) + return false; + if (tpcNSigPr < static_cast(maxTPCNSigmaProton) && tpcNSigPi > tpcNSigmaVetoThreshold) + tpcPassed = true; + } else if (combinedNSigmaCutProton > 0 && totalMomentum >= minProtonMomentum) { + if (combinedNSigPr < circularCutSq && combinedNSigPi > circularVetoCutSq) { + tpcPassed = true; + tofPassed = true; + } + } + if (totalMomentum < minProtonMomentum && tpcNSigPr < static_cast(maxTPCNSigmaProton)) { + tpcPassed = true; + tofPassed = true; + } + } else { + tofPassed = true; + if (track.tpcNSigmaPr() < minTPCNSigmaProton) + return false; + for (int i = 0; i < nTPCBins - 1; ++i) { + if (totalMomentum >= mProtonTPCMomBins[i] && totalMomentum < mProtonTPCMomBins[i + 1] && + tpcNSigPr < mProtonTPCNSigCuts[i] && tpcNSigPi > tpcNSigmaVetoThreshold) { + tpcPassed = true; + break; + } + } + } + return tpcPassed && tofPassed; + } + + template + bool passesPionPID(TrackType const& track, float totalMomentum) + { + bool tpcPassed{false}, tofPassed{false}; + const int nTPCBins = static_cast(mPionTPCMomBins.size()); + const int nTOFBins = static_cast(mPionTOFMomBins.size()); + const float tpcNSigPi = std::abs(track.tpcNSigmaPi()); + const float tpcNSigPr = std::abs(track.tpcNSigmaPr()); + const float tofNSigPi = std::abs(track.tofNSigmaPi()); + const float tofNSigPr = std::abs(track.tofNSigmaPr()); + const float combinedNSigPi = tpcNSigPi * tpcNSigPi + tofNSigPi * tofNSigPi; + const float combinedNSigPr = tpcNSigPr * tpcNSigPr + tofNSigPr * tofNSigPr; + const float circularCutSq = static_cast(combinedNSigmaCutPion * combinedNSigmaCutPion); + const float circularVetoCutSq = tpcNSigmaVetoThreshold * tpcNSigmaVetoThreshold + tofNSigmaVetoThreshold * tofNSigmaVetoThreshold; + + if (!useTPCOnlyPID && track.hasTOF()) { + if (combinedNSigmaCutPion < 0 && totalMomentum >= minPionMomentum) { + if (track.tofNSigmaPi() < minTOFNSigmaPion) + return false; + for (int i = 0; i < nTOFBins - 1; ++i) { + if (totalMomentum >= mPionTOFMomBins[i] && totalMomentum < mPionTOFMomBins[i + 1] && + tofNSigPi < mPionTOFNSigCuts[i] && tofNSigPr > tofNSigmaVetoThreshold) { + tofPassed = true; + break; + } + } + if (track.tpcNSigmaPi() < minCombinedNSigmaPion) + return false; + if (tpcNSigPi < static_cast(maxTPCNSigmaPion) && tpcNSigPr > tpcNSigmaVetoThreshold) + tpcPassed = true; + } else if (combinedNSigmaCutPion > 0 && totalMomentum >= minPionMomentum) { + if (combinedNSigPi < circularCutSq && combinedNSigPr > circularVetoCutSq) { + tpcPassed = true; + tofPassed = true; + } + } + if (totalMomentum < minPionMomentum && tpcNSigPi < static_cast(maxTPCNSigmaPion)) { + tpcPassed = true; + tofPassed = true; + } + } else { + tofPassed = true; + if (track.tpcNSigmaPi() < minTPCNSigmaPion) + return false; + for (int i = 0; i < nTPCBins - 1; ++i) { + if (totalMomentum >= mPionTPCMomBins[i] && totalMomentum < mPionTPCMomBins[i + 1] && + tpcNSigPi < mPionTPCNSigCuts[i] && tpcNSigPr > tpcNSigmaVetoThreshold) { + tpcPassed = true; + break; + } + } + } + return tpcPassed && tofPassed; + } + + template + void fillQAProton(TrackType const& track, float totalMomentum, float centralityPercent) + { + const float pt = track.pt(); + const float tpcNSigPr = track.tpcNSigmaPr(); + histos.fill(HIST("QAafter/Proton/dcaXYvsPt"), pt, track.dcaXY()); + histos.fill(HIST("QAafter/Proton/dcaZvsPt"), pt, track.dcaZ()); + histos.fill(HIST("QAafter/Proton/dcaXYdist"), track.dcaXY()); + histos.fill(HIST("QAafter/Proton/dcaZdist"), track.dcaZ()); + histos.fill(HIST("QAafter/Proton/tpcNSigmaVsMomentum"), totalMomentum, tpcNSigPr); + histos.fill(HIST("QAafter/Proton/tpcNSigmaVsPt"), pt, tpcNSigPr); + histos.fill(HIST("QAafter/Proton/tpcNSigmaVsCentrality"), centralityPercent, tpcNSigPr); + histos.fill(HIST("QAafter/Proton/tpcNSigmaPionContamVsPt"), pt, track.tpcNSigmaPi()); + histos.fill(HIST("QAafter/Proton/tpcNSigmaKaonContamVsPt"), pt, track.tpcNSigmaKa()); + histos.fill(HIST("QAafter/Proton/tpcCrossedRowsVsPt"), pt, track.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Proton/tpcClustersFoundVsPt"), pt, track.tpcNClsFound()); + if (!useTPCOnlyPID && track.hasTOF()) { + const float tofNSigPr = track.tofNSigmaPr(); + histos.fill(HIST("QAafter/Proton/tofNSigmaVsMomentum"), totalMomentum, tofNSigPr); + histos.fill(HIST("QAafter/Proton/tofNSigmaVsPt"), pt, tofNSigPr); + histos.fill(HIST("QAafter/Proton/tofNSigmaVsCentrality"), centralityPercent, tofNSigPr); + histos.fill(HIST("QAafter/Proton/tofNSigmaVsTPCNSigma"), tpcNSigPr, tofNSigPr); + histos.fill(HIST("QAafter/Proton/tofNSigmaPionContamVsMomentum"), totalMomentum, track.tofNSigmaPi()); + } + } + + template + void fillQAPion(TrackType const& track, float totalMomentum, float centralityPercent) + { + const float pt = track.pt(); + const float tpcNSigPi = track.tpcNSigmaPi(); + histos.fill(HIST("QAafter/Pion/dcaXYvsPt"), pt, track.dcaXY()); + histos.fill(HIST("QAafter/Pion/dcaZvsPt"), pt, track.dcaZ()); + histos.fill(HIST("QAafter/Pion/dcaXYdist"), track.dcaXY()); + histos.fill(HIST("QAafter/Pion/dcaZdist"), track.dcaZ()); + histos.fill(HIST("QAafter/Pion/tpcNSigmaVsMomentum"), totalMomentum, tpcNSigPi); + histos.fill(HIST("QAafter/Pion/tpcNSigmaVsPt"), pt, tpcNSigPi); + histos.fill(HIST("QAafter/Pion/tpcNSigmaVsCentrality"), centralityPercent, tpcNSigPi); + histos.fill(HIST("QAafter/Pion/tpcNSigmaProtonContamVsPt"), pt, track.tpcNSigmaPr()); + histos.fill(HIST("QAafter/Pion/tpcNSigmaKaonContamVsPt"), pt, track.tpcNSigmaKa()); + histos.fill(HIST("QAafter/Pion/tpcCrossedRowsVsPt"), pt, track.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Pion/tpcClustersFoundVsPt"), pt, track.tpcNClsFound()); + if (!useTPCOnlyPID && track.hasTOF()) { + const float tofNSigPi = track.tofNSigmaPi(); + histos.fill(HIST("QAafter/Pion/tofNSigmaVsMomentum"), totalMomentum, tofNSigPi); + histos.fill(HIST("QAafter/Pion/tofNSigmaVsPt"), pt, tofNSigPi); + histos.fill(HIST("QAafter/Pion/tofNSigmaVsCentrality"), centralityPercent, tofNSigPi); + histos.fill(HIST("QAafter/Pion/tofNSigmaVsTPCNSigma"), tpcNSigPi, tofNSigPi); + histos.fill(HIST("QAafter/Pion/tofNSigmaProtonContamVsMomentum"), totalMomentum, track.tofNSigmaPr()); + } + } + + void fillDeltaHistogramSameEvent(int protonSign, int pionSign, float pairPt, float pairMass, float centrality, float rapidity) + { + if (protonSign > 0) { + if (pionSign > 0) { + histos.fill(HIST("Analysis/hDeltaPlusPlusInvMass"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaPlusPlus"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hDeltaZeroInvMass"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaZero"), pairMass, pairPt, centrality, rapidity); + } + } else { + if (pionSign < 0) { + histos.fill(HIST("Analysis/hAntiDeltaPlusPlusInvMass"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaPlusPlus"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hAntiDeltaZeroInvMass"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaZero"), pairMass, pairPt, centrality, rapidity); + } + } + } + + void fillDeltaHistogramMixedEvent(int protonSign, int pionSign, float pairPt, float pairMass, float centrality, float rapidity) + { + if (protonSign > 0) { + if (pionSign > 0) { + histos.fill(HIST("Analysis/hDeltaPlusPlusInvMassEM"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaPlusPlusEM"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hDeltaZeroInvMassEM"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaZeroEM"), pairMass, pairPt, centrality, rapidity); + } + } else { + if (pionSign < 0) { + histos.fill(HIST("Analysis/hAntiDeltaPlusPlusInvMassEM"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaPlusPlusEM"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hAntiDeltaZeroInvMassEM"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaZeroEM"), pairMass, pairPt, centrality, rapidity); + } + } + } + + void fillDeltaHistogramMC(int protonSign, int pionSign, float pairPt, float pairMass, float centrality, float rapidity) + { + if (protonSign > 0) { + if (pionSign > 0) { + histos.fill(HIST("Analysis/hDeltaPlusPlusInvMassMC"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaPlusPlusMC"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hDeltaZeroInvMassMC"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hDeltaZeroMC"), pairMass, pairPt, centrality, rapidity); + } + } else { + if (pionSign < 0) { + histos.fill(HIST("Analysis/hAntiDeltaPlusPlusInvMassMC"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaPlusPlusMC"), pairMass, pairPt, centrality, rapidity); + } else { + histos.fill(HIST("Analysis/hAntiDeltaZeroInvMassMC"), pairPt, pairMass); + histos.fill(HIST("THnSparse/hAntiDeltaZeroMC"), pairMass, pairPt, centrality, rapidity); + } + } + } + + void fillRotationalBackground(int protonSign, int pionSign, float pxProton, float pyProton, float pzProton, float pionPhi, float pionPt, float pzPion, float centrality) + { + if (numberOfRotations <= 0) + return; + const float weight = 1.f / static_cast(numberOfRotations); + const float rotWindowHalf = o2::constants::math::PI / static_cast(rotationAngleWindow); + + for (int iRot = 0; iRot < numberOfRotations; ++iRot) { + float rotAngle; + if (numberOfRotations == 1) { + rotAngle = o2::constants::math::PI; + } else { + rotAngle = (o2::constants::math::PI - rotWindowHalf) + + static_cast(iRot) * (2.f * rotWindowHalf / static_cast(numberOfRotations - 1)); + } + const float newPhi = RecoDecay::constrainAngle(pionPhi + rotAngle, 0.f); + const float pxPionRot = pionPt * std::cos(newPhi); + const float pyPionRot = pionPt * std::sin(newPhi); + const std::array, 2> rotMomenta = { + std::array{pxProton, pyProton, pzProton}, + std::array{pxPionRot, pyPionRot, pzPion}}; + const float rotMass = RecoDecay::m(rotMomenta, std::array{massProton, massPion}); + const float rotPt = RecoDecay::pt(std::array{pxProton + pxPionRot, pyProton + pyPionRot}); + const float rotY = RecoDecay::y( + std::array{pxProton + pxPionRot, pyProton + pyPionRot, pzProton + pzPion}, rotMass); + if (rotY < cfgMinY || rotY > cfgMaxY) + continue; + + if (protonSign > 0) { + if (pionSign > 0) { + histos.fill(HIST("Analysis/hDeltaPlusPlusInvMassRot"), rotPt, rotMass, weight); + histos.fill(HIST("THnSparse/hDeltaPlusPlusRot"), rotMass, rotPt, centrality, rotY, weight); + } else { + histos.fill(HIST("Analysis/hDeltaZeroInvMassRot"), rotPt, rotMass, weight); + histos.fill(HIST("THnSparse/hDeltaZeroRot"), rotMass, rotPt, centrality, rotY, weight); + } + } else { + if (pionSign < 0) { + histos.fill(HIST("Analysis/hAntiDeltaPlusPlusInvMassRot"), rotPt, rotMass, weight); + histos.fill(HIST("THnSparse/hAntiDeltaPlusPlusRot"), rotMass, rotPt, centrality, rotY, weight); + } else { + histos.fill(HIST("Analysis/hAntiDeltaZeroInvMassRot"), rotPt, rotMass, weight); + histos.fill(HIST("THnSparse/hAntiDeltaZeroRot"), rotMass, rotPt, centrality, rotY, weight); + } + } + } + } + + void fillPairQABefore(float pxPr, float pyPr, float pzPr, float pxPi, float pyPi, float pzPi, float momPr, float momPi) + { + const float cosAngle = std::clamp((pxPr * pxPi + pyPr * pyPi + pzPr * pzPi) / (momPr * momPi), -1.f, 1.f); + histos.fill(HIST("QAChecks/Pair/hOpeningAngleBefore"), std::acos(cosAngle)); + } + + void fillPairQAAfter(float pxPr, float pyPr, float pzPr, float pxPi, float pyPi, float pzPi, float momPr, float momPi) + { + const float cosAngle = std::clamp((pxPr * pxPi + pyPr * pyPi + pzPr * pzPi) / (momPr * momPi), -1.f, 1.f); + histos.fill(HIST("QAChecks/Pair/hOpeningAngleAfter"), std::acos(cosAngle)); + } + + struct TrackCandidate { + float px, py, pz, pt, eta, phi, dcaXY, dcaZ; + float mom; + int sign; + bool hasTOF; + float tpcNSigmaPr, tpcNSigmaPi; + uint64_t globalIndex; + }; + + template + void buildCandidatePools(TrackCollection const& tracks, std::vector& protons, std::vector& pions) + { + protons.clear(); + pions.clear(); + for (auto const& track : tracks) { + if (!passesBasicTrackSelection(track)) + continue; + const float mom = RecoDecay::p(track.px(), track.py(), track.pz()); + const bool isProton = passesProtonPID(track, mom) && passesProtonDCASelection(track) && + !(requireTOFForProton && !track.hasTOF()); + const bool isPion = passesPionPID(track, mom) && passesPionDCASelection(track) && + !(requireTOFForPion && !track.hasTOF()); + if (!isProton && !isPion) + continue; + TrackCandidate cand; + cand.px = track.px(); + cand.py = track.py(); + cand.pz = track.pz(); + cand.pt = track.pt(); + cand.eta = track.eta(); + cand.phi = track.phi(); + cand.dcaXY = track.dcaXY(); + cand.dcaZ = track.dcaZ(); + cand.mom = mom; + cand.sign = track.sign(); + cand.hasTOF = track.hasTOF(); + cand.tpcNSigmaPr = track.tpcNSigmaPr(); + cand.tpcNSigmaPi = track.tpcNSigmaPi(); + cand.globalIndex = track.globalIndex(); + if (isProton) + protons.push_back(cand); + if (isPion) + pions.push_back(cand); + } + } + + template + void fillInvariantMassHistogramsFromPools( + std::vector const& protonPool, + std::vector const& pionPool, + float centrality, + bool fillPairQA = false) + { + for (auto const& protonCand : protonPool) { + for (auto const& pionCand : pionPool) { + + if constexpr (!isMixed) { + if (protonCand.globalIndex == pionCand.globalIndex) + continue; + } + + const float pxPr = protonCand.px, pyPr = protonCand.py, pzPr = protonCand.pz; + const float pxPi = pionCand.px, pyPi = pionCand.py, pzPi = pionCand.pz; + + if constexpr (!isMixed) { + if (fillPairQA) + fillPairQABefore(pxPr, pyPr, pzPr, pxPi, pyPi, pzPi, protonCand.mom, pionCand.mom); + } + + if (applyDeepAngleCut) { + const float cosAngle = std::clamp( + (pxPr * pxPi + pyPr * pyPi + pzPr * pzPi) / (protonCand.mom * pionCand.mom), -1.f, 1.f); + if (std::acos(cosAngle) < static_cast(deepAngleCutValue)) + continue; + } + + const std::array, 2> bothMomenta = { + std::array{pxPr, pyPr, pzPr}, + std::array{pxPi, pyPi, pzPi}}; + const float pairMass = RecoDecay::m(bothMomenta, std::array{massProton, massPion}); + const float pairPt = RecoDecay::pt(std::array{pxPr + pxPi, pyPr + pyPi}); + const float pairY = RecoDecay::y(std::array{pxPr + pxPi, pyPr + pyPi, pzPr + pzPi}, pairMass); + + if (pairY < cfgMinY || pairY > cfgMaxY) + continue; + + if constexpr (!isMixed) { + if (fillPairQA) + fillPairQAAfter(pxPr, pyPr, pzPr, pxPi, pyPi, pzPi, protonCand.mom, pionCand.mom); + } + + if constexpr (isMixed) { + fillDeltaHistogramMixedEvent(protonCand.sign, pionCand.sign, pairPt, pairMass, centrality, pairY); + } else { + fillDeltaHistogramSameEvent(protonCand.sign, pionCand.sign, pairPt, pairMass, centrality, pairY); + if (enableRotationalBackground) + fillRotationalBackground(protonCand.sign, pionCand.sign, + pxPr, pyPr, pzPr, pionCand.phi, pionCand.pt, pzPi, centrality); + } + } + } + } + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPt); + + using EventCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; + using TrackCandidatesMC = soa::Filtered>; + + Preslice perCol = aod::track::collisionId; + Preslice perColMC = aod::track::collisionId; + + // ── Event-mixing binning policies (one per centrality estimator) ──────────── + using BinningTypeFT0M = ColumnBinningPolicy; + using BinningTypeFT0A = ColumnBinningPolicy; + using BinningTypeFT0C = ColumnBinningPolicy; + using BinningTypeFV0A = ColumnBinningPolicy; + using BinningTypeNTPV = ColumnBinningPolicy; + + BinningTypeFT0M binningFT0M{{cfgVtxAxis, cfgCentAxis}, true}; + BinningTypeFT0A binningFT0A{{cfgVtxAxis, cfgCentAxis}, true}; + BinningTypeFT0C binningFT0C{{cfgVtxAxis, cfgCentAxis}, true}; + BinningTypeFV0A binningFV0A{{cfgVtxAxis, cfgCentAxis}, true}; + BinningTypeNTPV binningNTPV{{cfgVtxAxis, cfgCentAxis}, true}; + + SameKindPair pairFT0M{binningFT0M, cfgNoMixedEvents, -1, &cache}; + SameKindPair pairFT0A{binningFT0A, cfgNoMixedEvents, -1, &cache}; + SameKindPair pairFT0C{binningFT0C, cfgNoMixedEvents, -1, &cache}; + SameKindPair pairFV0A{binningFV0A, cfgNoMixedEvents, -1, &cache}; + SameKindPair pairNTPV{binningNTPV, cfgNoMixedEvents, -1, &cache}; + + std::vector mProtonPool{}; + std::vector mPionPool{}; + + void processSameEvent(EventCandidates const& collisions, + TrackCandidates const& tracks, + aod::BCs const&) + { + for (auto const& collision : collisions) { + if (!passesEventSelection(collision)) + continue; + const float centrality = getCentrality(collision); + const int occupancy = collision.trackOccupancyInTimeRange(); + + histos.fill(HIST("OccupancyQA/hOccupancyVsCentralityBefore"), centrality, occupancy); + histos.fill(HIST("OccupancyQA/hOccupancyVsVtxZBefore"), collision.posZ(), occupancy); + histos.fill(HIST("Event/hNcontributor"), collision.numContrib()); + histos.fill(HIST("Event/hVtxZ"), collision.posZ()); + histos.fill(HIST("Event/hCentrality"), centrality); + histos.fill(HIST("Event/hOccupancy"), occupancy); + histos.fill(HIST("CentQA/hCentralityVsVtxZ"), collision.posZ(), centrality); + histos.fill(HIST("CentQA/hCentralityVsOccupancy"), occupancy, centrality); + histos.fill(HIST("CentQA/hEventCountVsCentrality"), centrality); + histos.fill(HIST("OccupancyQA/hOccupancyVsCentralityAfter"), centrality, occupancy); + histos.fill(HIST("OccupancyQA/hOccupancyVsVtxZAfter"), collision.posZ(), occupancy); + + const uint64_t collIdx = collision.globalIndex(); + auto perColTracks = tracks.sliceBy(perCol, collIdx); + perColTracks.bindExternalIndices(&tracks); + + for (auto const& track : perColTracks) { + const float mom = RecoDecay::p(track.px(), track.py(), track.pz()); + histos.fill(HIST("QAbefore/Proton/tpcNSigmaVsMomentum"), mom, track.tpcNSigmaPr()); + if (track.hasTOF()) { + histos.fill(HIST("QAbefore/Proton/tofNSigmaVsMomentum"), mom, track.tofNSigmaPr()); + histos.fill(HIST("QAbefore/Proton/tofNSigmaVsTPCNSigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + } + histos.fill(HIST("QAbefore/Pion/tpcNSigmaVsMomentum"), mom, track.tpcNSigmaPi()); + if (track.hasTOF()) { + histos.fill(HIST("QAbefore/Pion/tofNSigmaVsMomentum"), mom, track.tofNSigmaPi()); + histos.fill(HIST("QAbefore/Pion/tofNSigmaVsTPCNSigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + } + if (!passesBasicTrackSelection(track)) + continue; + if (passesProtonPID(track, mom) && passesProtonDCASelection(track)) + fillQAProton(track, mom, centrality); + if (passesPionPID(track, mom) && passesPionDCASelection(track)) + fillQAPion(track, mom, centrality); + } + buildCandidatePools(perColTracks, mProtonPool, mPionPool); + fillInvariantMassHistogramsFromPools(mProtonPool, mPionPool, centrality, true); + } + } + PROCESS_SWITCH(DeltaAnalysis, processSameEvent, "Process same event", true); + + // ── Shared mixed-event logic ───────────────────────────────────────────── + template + void runMixedEvent(PairType& mixingPair) + { + for (auto const& [c1, tracks1, c2, tracks2] : mixingPair) { + if (!passesEventSelection(c1) || !passesEventSelection(c2)) + continue; + const float centrality = getCentrality(c1); + std::vector protonPool1, pionPool1, protonPool2, pionPool2; + buildCandidatePools(tracks1, protonPool1, pionPool1); + buildCandidatePools(tracks2, protonPool2, pionPool2); + fillInvariantMassHistogramsFromPools(protonPool1, pionPool2, centrality); + fillInvariantMassHistogramsFromPools(protonPool2, pionPool1, centrality); + } + } + + void processMixedEvent(EventCandidates const&, TrackCandidates const&) + { + switch (cfgCentralityEstimator) { + case delta_analysis::kFT0M: + runMixedEvent(pairFT0M); + break; + case delta_analysis::kFT0A: + runMixedEvent(pairFT0A); + break; + case delta_analysis::kFT0C: + runMixedEvent(pairFT0C); + break; + case delta_analysis::kFV0A: + runMixedEvent(pairFV0A); + break; + case delta_analysis::kNTPV: + runMixedEvent(pairNTPV); + break; + default: + runMixedEvent(pairFT0M); + break; + } + } + PROCESS_SWITCH(DeltaAnalysis, processMixedEvent, "Process mixed event", true); + + void processMC(soa::Join const& collisions, aod::BCs const&, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles) + { + constexpr float kGenCentrality = 1.f; + + for (auto const& collision : collisions) { + if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) + continue; + const float centrality = getCentrality(collision); + histos.fill(HIST("Event/hNcontributor"), collision.numContrib()); + histos.fill(HIST("Event/hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto perColTracks = tracks.sliceBy(perColMC, collIdx); + perColTracks.bindExternalIndices(&tracks); + + for (auto const& t0 : perColTracks) { + if (!passesBasicTrackSelection(t0) || !t0.has_mcParticle()) + continue; + const auto mcTrack = t0.mcParticle(); + const float mom = RecoDecay::p(t0.px(), t0.py(), t0.pz()); + if (std::abs(mcTrack.pdgCode()) == delta_analysis::PdgProton && passesProtonPID(t0, mom)) { + for (const auto& mother : mcTrack.mothers_as()) { + if (std::abs(mother.pdgCode()) == delta_analysis::PdgDeltaPlusPlus) { + if (t0.sign() < 0) + histos.fill(HIST("QAChecks/hRecProtonAntiDeltaPlusPlus"), t0.pt()); + else + histos.fill(HIST("QAChecks/hRecProtonDeltaPlusPlus"), t0.pt()); + } else if (std::abs(mother.pdgCode()) == delta_analysis::PdgDeltaZero) { + if (t0.sign() < 0) + histos.fill(HIST("QAChecks/hRecProtonAntiDeltaZero"), t0.pt()); + else + histos.fill(HIST("QAChecks/hRecProtonDeltaZero"), t0.pt()); + } + } + } + if (std::abs(mcTrack.pdgCode()) == delta_analysis::PdgPion && passesPionPID(t0, mom)) { + for (const auto& mother : mcTrack.mothers_as()) { + if (std::abs(mother.pdgCode()) == delta_analysis::PdgDeltaPlusPlus) { + if (t0.sign() < 0) + histos.fill(HIST("QAChecks/hRecPionAntiDeltaPlusPlus"), t0.pt()); + else + histos.fill(HIST("QAChecks/hRecPionDeltaPlusPlus"), t0.pt()); + } else if (std::abs(mother.pdgCode()) == delta_analysis::PdgDeltaZero) { + if (t0.sign() < 0) + histos.fill(HIST("QAChecks/hRecPionAntiDeltaZero"), t0.pt()); + else + histos.fill(HIST("QAChecks/hRecPionDeltaZero"), t0.pt()); + } + } + } + } + + for (auto const& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(perColTracks, perColTracks))) { + if (t0.globalIndex() == t1.globalIndex()) + continue; + if (!passesBasicTrackSelection(t0) || !passesBasicTrackSelection(t1)) + continue; + const float momT0 = RecoDecay::p(t0.px(), t0.py(), t0.pz()); + const float momT1 = RecoDecay::p(t1.px(), t1.py(), t1.pz()); + if (!passesProtonPID(t0, momT0) || !passesPionPID(t1, momT1)) + continue; + if (!passesProtonDCASelection(t0) || !passesPionDCASelection(t1)) + continue; + if (!t0.has_mcParticle() || !t1.has_mcParticle()) + continue; + const auto mcProton = t0.mcParticle(); + const auto mcPion = t1.mcParticle(); + if (std::abs(mcProton.pdgCode()) != delta_analysis::PdgProton) + continue; + if (std::abs(mcPion.pdgCode()) != delta_analysis::PdgPion) + continue; + bool foundMother = false; + for (const auto& motherPr : mcProton.mothers_as()) { + for (const auto& motherPi : mcPion.mothers_as()) { + if (motherPr != motherPi) + continue; + if (std::abs(motherPr.pdgCode()) != delta_analysis::PdgDeltaPlusPlus && + std::abs(motherPr.pdgCode()) != delta_analysis::PdgDeltaZero) + continue; + foundMother = true; + break; + } + if (foundMother) + break; + } + if (!foundMother) + continue; + const std::array, 2> momenta = { + std::array{t0.px(), t0.py(), t0.pz()}, + std::array{t1.px(), t1.py(), t1.pz()}}; + const float pairMass = RecoDecay::m(momenta, std::array{massProton, massPion}); + const float pairPt = RecoDecay::pt(std::array{t0.px() + t1.px(), t0.py() + t1.py()}); + const float pairY = RecoDecay::y(std::array{t0.px() + t1.px(), t0.py() + t1.py(), t0.pz() + t1.pz()}, pairMass); + if (pairY < cfgMinY || pairY > cfgMaxY) + continue; + fillDeltaHistogramMC(t0.sign(), t1.sign(), pairPt, pairMass, centrality, pairY); + } + } + + for (auto const& mcParticle : mcParticles) { + const int pdg = mcParticle.pdgCode(); + if (std::abs(pdg) != delta_analysis::PdgDeltaPlusPlus && + std::abs(pdg) != delta_analysis::PdgDeltaZero) + continue; + if (mcParticle.y() < cfgMinY || mcParticle.y() > cfgMaxY) + continue; + const auto daughters = mcParticle.daughters_as(); + bool hasPr = false, hasPi = false; + float ptPr = -999.f, ptPi = -999.f; + double eTotal = 0.; + for (const auto& d : daughters) { + if (std::abs(d.pdgCode()) == delta_analysis::PdgProton) { + hasPr = true; + ptPr = d.pt(); + eTotal += d.e(); + } else if (std::abs(d.pdgCode()) == delta_analysis::PdgPion) { + hasPi = true; + ptPi = d.pt(); + eTotal += d.e(); + } + } + if (!hasPr || !hasPi) + continue; + const float pSq = mcParticle.p() * mcParticle.p(); + const float genMass = std::sqrt(std::max(0., eTotal * eTotal - static_cast(pSq))); + const float genPt = mcParticle.pt(); + const float genY = mcParticle.y(); + if (pdg == delta_analysis::PdgDeltaPlusPlus) { + histos.fill(HIST("Analysis/hDeltaPlusPlusInvMassGen"), genPt, genMass); + histos.fill(HIST("THnSparse/hDeltaPlusPlusGen"), genPt, kGenCentrality, genY); + histos.fill(HIST("QAChecks/hGenProtonDeltaPlusPlus"), ptPr); + histos.fill(HIST("QAChecks/hGenPionDeltaPlusPlus"), ptPi); + } else if (pdg == -delta_analysis::PdgDeltaPlusPlus) { + histos.fill(HIST("Analysis/hAntiDeltaPlusPlusInvMassGen"), genPt, genMass); + histos.fill(HIST("THnSparse/hAntiDeltaPlusPlusGen"), genPt, kGenCentrality, genY); + histos.fill(HIST("QAChecks/hGenProtonAntiDeltaPlusPlus"), ptPr); + histos.fill(HIST("QAChecks/hGenPionAntiDeltaPlusPlus"), ptPi); + } else if (pdg == delta_analysis::PdgDeltaZero) { + histos.fill(HIST("Analysis/hDeltaZeroInvMassGen"), genPt, genMass); + histos.fill(HIST("THnSparse/hDeltaZeroGen"), genPt, kGenCentrality, genY); + histos.fill(HIST("QAChecks/hGenProtonDeltaZero"), ptPr); + histos.fill(HIST("QAChecks/hGenPionDeltaZero"), ptPi); + } else if (pdg == -delta_analysis::PdgDeltaZero) { + histos.fill(HIST("Analysis/hAntiDeltaZeroInvMassGen"), genPt, genMass); + histos.fill(HIST("THnSparse/hAntiDeltaZeroGen"), genPt, kGenCentrality, genY); + histos.fill(HIST("QAChecks/hGenProtonAntiDeltaZero"), ptPr); + histos.fill(HIST("QAChecks/hGenPionAntiDeltaZero"), ptPi); + } + } + } + PROCESS_SWITCH(DeltaAnalysis, processMC, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // FIX name/o2-task: TaskName is redundant when it equals the derived device name + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/deltaanalysis.cxx b/PWGLF/Tasks/Resonances/deltaanalysis.cxx deleted file mode 100644 index a121980f67e..00000000000 --- a/PWGLF/Tasks/Resonances/deltaanalysis.cxx +++ /dev/null @@ -1,613 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -// Analysis task for delta analysis - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -namespace -{ -constexpr float pionMass = o2::constants::physics::MassPionCharged; -constexpr float protonMass = o2::constants::physics::MassProton; -constexpr int deltaPlusPlusPDG = 2224; -constexpr int deltaZeroPDG = 2114; -constexpr int protonPDG = 2212; -constexpr int pionPDG = 211; -} // namespace - -struct deltaAnalysis { - - SliceCache cache; - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - // events - Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - // track - Configurable cfgCutPt{"cfgCutPt", 0.2, "Pt cut on daughter track"}; - Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; - Configurable cfgCutY{"cfgCutY", 0.5, "Y cut on reconstructed delta"}; - Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; - Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; - Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; - Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; - Configurable cfgCutPtProtonTPC{"cfgCutPtProtonTPC", 0.8, "Pt cut of proton in TPC"}; - Configurable cfgCutPtPionTPC{"cfgCutPtPionTPC", 0.8, "Pt cut of pion in TPC"}; - - // Histogram axes - AxisSpec nSigmaTPCaxis = {100, -5., 5., "n#sigma_{TPC}"}; - AxisSpec nSigmaTOFaxis = {100, -5., 5., "n#sigma_{TOF}"}; - ConfigurableAxis cfgPtAxis{"cfgPtAxis", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4.}, "#it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis cfgMassAxis{"cfgDeltaPlusPlusAxis", {75, 1.05, 1.8}, ""}; - - void init(o2::framework::InitContext&) - { - // Define axes - AxisSpec deltaPlusPlusAxis{cfgMassAxis, "m(p + #pi^{+}) (GeV/#it{c}^{2})"}; - AxisSpec antiDeltaPlusPlusAxis{cfgMassAxis, "m(#bar{p} + #pi^{-}) (GeV/#it{c}^{2})"}; - AxisSpec deltaZeroAxis{cfgMassAxis, "m(p + #pi^{-}) (GeV/#it{c}^{2})"}; - AxisSpec antiDeltaZeroAxis{cfgMassAxis, "m(#bar{p} + #pi^{+}) (GeV/#it{c}^{2})"}; - AxisSpec ptAxis{cfgPtAxis, "#it{p}_{T} (GeV/#it{c})"}; - - // Collision - histos.add("hCentrality", "Centrality distribution", kTH1F, {{2001, -0.5, 2000.5}}); - histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hNcontributor", "Number of primary vertex contributors; n", kTH1F, {{2001, -0.5f, 2000.5f}}); - - // Single track - histos.add("hPiPlusDCAxy", "DCA_{xy} distribution for #pi^{+}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPiPlusDCAz", "DCA_{z} distribution for #pi^{+}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPiPlusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{+}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPiPlusNsigmaTPCvsPt_TPC_only", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{+}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPiPlusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #pi^{+}", kTH2F, {ptAxis, nSigmaTOFaxis}); - - histos.add("hPiMinusDCAxy", "DCA_{xy} distribution for #pi^{-}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPiMinusDCAz", "DCA_{z} distribution for #pi^{-}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPiMinusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{-}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPiMinusNsigmaTPCvsPt_TPC_only", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{-}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPiMinusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #pi^{-}", kTH2F, {ptAxis, nSigmaTOFaxis}); - - histos.add("hPrPlusDCAxy", "DCA_{xy} distribution for p; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPrPlusDCAz", "DCA_{z} distribution for p; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPrPlusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for p", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPrPlusNsigmaTPCvsPt_TPC_only", "n#sigma_{TPC} distribution vs #it{p}_{T} for p", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPrPlusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for p", kTH2F, {ptAxis, nSigmaTOFaxis}); - - histos.add("hPrMinusDCAxy", "DCA_{xy} distribution for #bar{p}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPrMinusDCAz", "DCA_{z} distribution for #bar{p}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hPrMinusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #bar{p}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPrMinusNsigmaTPCvsPt_TPC_only", "n#sigma_{TPC} distribution vs #it{p}_{T} for #bar{p}", kTH2F, {ptAxis, nSigmaTPCaxis}); - histos.add("hPrMinusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #bar{p}", kTH2F, {ptAxis, nSigmaTOFaxis}); - - // Deltas - histos.add("hDeltaPlusPlusInvMass", "Invariant mass distribution for #Delta^{++}", kTH2F, {ptAxis, deltaPlusPlusAxis}); - histos.add("hAntiDeltaPlusPlusInvMass", "Invariant mass distribution for #bar{#Delta^{++}}", kTH2F, {ptAxis, antiDeltaPlusPlusAxis}); - - histos.add("hDeltaZeroInvMass", "Invariant mass distribution for #Delta^{0}", kTH2F, {ptAxis, deltaZeroAxis}); - histos.add("hAntiDeltaZeroInvMass", "Invariant mass distribution for #bar{#Delta^{0}}", kTH2F, {ptAxis, antiDeltaZeroAxis}); - - if (doprocessMixedEvent) { - // Deltas - Event mixing - histos.add("hDeltaPlusPlusInvMassEM", "Invariant mass distribution for #Delta^{++} - event mixing", kTH2F, {ptAxis, deltaPlusPlusAxis}); - histos.add("hAntiDeltaPlusPlusInvMassEM", "Invariant mass distribution for #bar{#Delta^{++}} - event mixing", kTH2F, {ptAxis, antiDeltaPlusPlusAxis}); - - histos.add("hDeltaZeroInvMassEM", "Invariant mass distribution for #Delta^{0} - event mixing", kTH2F, {ptAxis, deltaZeroAxis}); - histos.add("hAntiDeltaZeroInvMassEM", "Invariant mass distribution for #bar{#Delta^{0}} - event mixing", kTH2F, {ptAxis, antiDeltaZeroAxis}); - } - - if (doprocessMC) { - // generated quantities - histos.add("hDeltaPlusPlusInvMassGen", "Invariant mass distribution for #Delta^{++} - generated", kTH2F, {ptAxis, deltaPlusPlusAxis}); - histos.add("hAntiDeltaPlusPlusInvMassGen", "Invariant mass distribution for #bar{#Delta^{++}} - generated", kTH2F, {ptAxis, antiDeltaPlusPlusAxis}); - - histos.add("hDeltaZeroInvMassGen", "Invariant mass distribution for #Delta^{0} - generated", kTH2F, {ptAxis, deltaZeroAxis}); - histos.add("hAntiDeltaZeroInvMassGen", "Invariant mass distribution for #bar{#Delta^{0}} - generated", kTH2F, {ptAxis, antiDeltaZeroAxis}); - - histos.add("hRecProtonAntiDeltaPlusPlus", "Proton from #bar{#Delta^{++}}", kTH1F, {ptAxis}); - histos.add("hRecProtonDeltaPlusPlus", "Proton from #Delta^{++}", kTH1F, {ptAxis}); - histos.add("hRecProtonAntiDeltaZero", "Proton from #bar{#Delta^{0}}", kTH1F, {ptAxis}); - histos.add("hRecProtonDeltaZero", "Proton from #Delta^{0}", kTH1F, {ptAxis}); - histos.add("hRecPionAntiDeltaPlusPlus", "Pion from #bar{#Delta^{++}}", kTH1F, {ptAxis}); - histos.add("hRecPionDeltaPlusPlus", "Pion from #Delta^{++}", kTH1F, {ptAxis}); - histos.add("hRecPionAntiDeltaZero", "Pion from #bar{#Delta^{0}}", kTH1F, {ptAxis}); - histos.add("hRecPionDeltaZero", "Pion from #Delta^{0}", kTH1F, {ptAxis}); - - histos.add("hGenProtonAntiDeltaPlusPlus", "Proton from #bar{#Delta^{++}}", kTH1F, {ptAxis}); - histos.add("hGenProtonDeltaPlusPlus", "Proton from #Delta^{++}", kTH1F, {ptAxis}); - histos.add("hGenProtonAntiDeltaZero", "Proton from #bar{#Delta^{0}}", kTH1F, {ptAxis}); - histos.add("hGenProtonDeltaZero", "Proton from #Delta^{0}", kTH1F, {ptAxis}); - histos.add("hGenPionAntiDeltaPlusPlus", "Pion from #bar{#Delta^{++}}", kTH1F, {ptAxis}); - histos.add("hGenPionDeltaPlusPlus", "Pion from #Delta^{++}", kTH1F, {ptAxis}); - histos.add("hGenPionAntiDeltaZero", "Pion from #bar{#Delta^{0}}", kTH1F, {ptAxis}); - histos.add("hGenPionDeltaZero", "Pion from #Delta^{0}", kTH1F, {ptAxis}); - } - } - - template - bool selectionTrack(const T& track) - { - // if (!track.isGlobalTrack()) { - // return false; - // } - if (track.itsNCls() < 5) { - return false; - } - if (track.tpcNClsShared() > 0) { - return false; - } - if (track.tpcNClsFound() < 70) { - return false; - } - if (track.tpcNClsCrossedRows() < 70) { - return false; - } - if (track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable()) { - return false; - } - if (track.tpcChi2NCl() > 4.f) { - return false; - } - if (track.itsChi2NCl() > 36.f) { - return false; - } - return true; - } - - template - bool selectionPIDPion(const T& track) - { - if (track.hasTOF()) { - if (std::abs(track.tofNSigmaPi()) < nsigmaCutTOF && std::abs(track.tpcNSigmaPi()) < nsigmaCutTPC) { - if (track.sign() > 0) { - histos.fill(HIST("hPiPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiPlusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPi()); - histos.fill(HIST("hPiPlusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPiPlusDCAz"), track.dcaZ()); - } else { - histos.fill(HIST("hPiMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiMinusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPi()); - histos.fill(HIST("hPiMinusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPiMinusDCAz"), track.dcaZ()); - } - return true; - } - } else if (std::abs(track.tpcNSigmaPi()) < nsigmaCutTPC) { - if (track.sign() > 0) { - histos.fill(HIST("hPiPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiPlusNsigmaTPCvsPt_TPC_only"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiPlusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPiPlusDCAz"), track.dcaZ()); - } else { - histos.fill(HIST("hPiMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiMinusNsigmaTPCvsPt_TPC_only"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("hPiMinusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPiMinusDCAz"), track.dcaZ()); - } - if (track.pt() < cfgCutPtPionTPC) { - return true; - } - } - return false; - } - - template - bool selectionPIDProton(const T& track) - { - if (track.hasTOF()) { - if (std::abs(track.tofNSigmaPr()) < nsigmaCutTOF && std::abs(track.tpcNSigmaPr()) < nsigmaCutTPC) { - if (track.sign() > 0) { - histos.fill(HIST("hPrPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrPlusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPr()); - histos.fill(HIST("hPrPlusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPrPlusDCAz"), track.dcaZ()); - } else { - histos.fill(HIST("hPrMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrMinusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPr()); - histos.fill(HIST("hPrMinusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPrMinusDCAz"), track.dcaZ()); - } - return true; - } - } else if (std::abs(track.tpcNSigmaPr()) < nsigmaCutTPC) { - if (track.sign() > 0) { - histos.fill(HIST("hPrPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrPlusNsigmaTPCvsPt_TPC_only"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrPlusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPrPlusDCAz"), track.dcaZ()); - } else { - histos.fill(HIST("hPrMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrMinusNsigmaTPCvsPt_TPC_only"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("hPrMinusDCAxy"), track.dcaXY()); - histos.fill(HIST("hPrMinusDCAz"), track.dcaZ()); - } - if (track.pt() < cfgCutPtProtonTPC) { - return true; - } - } - return false; - } - - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPt); - Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); - - using EventCandidates = soa::Filtered>; - - using TrackCandidates = soa::Filtered>; - - using TrackCandidatesMC = soa::Filtered>; - - Preslice perCol = aod::track::collisionId; - Preslice perColMC = aod::track::collisionId; - - // Binning for event mixing - ConfigurableAxis cfgCentAxis{"cfgCentAxis", {VARIABLE_WIDTH, 0., 0.01, 0.1, 1.0, 5.0, 10., 15., 20., 30., 40., 50., 70., 100.0, 105.}, "Binning of the centrality axis"}; - ConfigurableAxis cfgVtxAxis{"cfgVtxAxis", {VARIABLE_WIDTH, -20, -15, -10, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 10, 15, 20}, "Mixing bins - z-vertex"}; - - using BinningType = ColumnBinningPolicy; - - BinningType binningOnPositions{{cfgVtxAxis}, true}; - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; - - void processSameEvent(EventCandidates const& collisions, TrackCandidates const& tracks, aod::BCs const&) - { - for (auto& collision : collisions) { - if (!collision.sel8()) { - continue; - } - histos.fill(HIST("hNcontributor"), collision.numContrib()); - histos.fill(HIST("hVtxZ"), collision.posZ()); - - const uint64_t collIdx = collision.globalIndex(); - auto perColTracks = tracks.sliceBy(perCol, collIdx); - perColTracks.bindExternalIndices(&tracks); - - for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(perColTracks, perColTracks))) { - - if (t0.globalIndex() == t1.globalIndex()) { - continue; - } - if (!selectionTrack(t0) || !selectionTrack(t1)) { - continue; - } - if (selectionPIDProton(t0)) { - - TLorentzVector proton; - proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); - - if (selectionPIDPion(t1)) { - - TLorentzVector pion; - pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); - - TLorentzVector delta = proton + pion; - - if (abs(delta.Rapidity()) > cfgCutY) { - continue; - } - - if (t0.sign() < 0) { - if (t1.sign() < 0) { - histos.fill(HIST("hAntiDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hAntiDeltaZeroInvMass"), delta.Pt(), delta.M()); - } - } else { - if (t1.sign() < 0) { - histos.fill(HIST("hDeltaZeroInvMass"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); - } - } - } - } - } - } - } - PROCESS_SWITCH(deltaAnalysis, processSameEvent, "Process same event", false); - - void processMixedEvent(EventCandidates const& /*collisions*/, TrackCandidates const& /*tracks*/) - { - for (auto& [c1, tracks1, c2, tracks2] : pair) { - if (!c1.sel8()) { - continue; - } - if (!c2.sel8()) { - continue; - } - - for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - - if (!selectionTrack(t0) || !selectionTrack(t1)) { - continue; - } - - if (selectionPIDProton(t0)) { - - TLorentzVector proton; - proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); - - if (selectionPIDPion(t1)) { - - TLorentzVector pion; - pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); - - TLorentzVector delta = proton + pion; - - if (abs(delta.Rapidity()) > cfgCutY) { - continue; - } - - if (t0.sign() < 0) { - if (t1.sign() < 0) { - histos.fill(HIST("hAntiDeltaPlusPlusInvMassEM"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hAntiDeltaZeroInvMassEM"), delta.Pt(), delta.M()); - } - } else { - if (t1.sign() < 0) { - histos.fill(HIST("hDeltaZeroInvMassEM"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hDeltaPlusPlusInvMassEM"), delta.Pt(), delta.M()); - } - } - } - } - } - } - } - PROCESS_SWITCH(deltaAnalysis, processMixedEvent, "Process Mixed event", false); - - void processMC(soa::Join const& collisions, aod::BCs const&, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles) - { - - for (auto& collision : collisions) { - - if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { - continue; - } - - histos.fill(HIST("hCentrality"), 1); - histos.fill(HIST("hNcontributor"), collision.numContrib()); - histos.fill(HIST("hVtxZ"), collision.posZ()); - - const uint64_t collIdx = collision.globalIndex(); - auto perColTracks = tracks.sliceBy(perColMC, collIdx); - perColTracks.bindExternalIndices(&tracks); - - for (auto& t0 : perColTracks) { - - if (!selectionTrack(t0)) { - continue; - } - if (!t0.has_mcParticle()) { - continue; - } - - const auto mcTrack = t0.mcParticle(); - - if (std::abs(mcTrack.pdgCode()) == protonPDG) { - if (selectionPIDProton(t0)) { - for (auto& motherTrackProton : mcTrack.mothers_as()) { - if (std::abs(motherTrackProton.pdgCode()) == deltaPlusPlusPDG) { - if (t0.sign() < 0) { - histos.fill(HIST("hRecProtonAntiDeltaPlusPlus"), t0.pt()); - } else { - histos.fill(HIST("hRecProtonDeltaPlusPlus"), t0.pt()); - } - } else if (std::abs(motherTrackProton.pdgCode()) == deltaZeroPDG) { - if (t0.sign() < 0) { - histos.fill(HIST("hRecProtonAntiDeltaZero"), t0.pt()); - } else { - histos.fill(HIST("hRecProtonDeltaZero"), t0.pt()); - } - } - } - } - } else if (std::abs(mcTrack.pdgCode()) == pionPDG) { - if (selectionPIDPion(t0)) { - for (auto& motherTrackPion : mcTrack.mothers_as()) { - if (std::abs(motherTrackPion.pdgCode()) == deltaPlusPlusPDG) { - if (t0.sign() < 0) { - histos.fill(HIST("hRecPionAntiDeltaPlusPlus"), t0.pt()); - } else { - histos.fill(HIST("hRecPionDeltaPlusPlus"), t0.pt()); - } - } else if (std::abs(motherTrackPion.pdgCode()) == deltaZeroPDG) { - if (t0.sign() < 0) { - histos.fill(HIST("hRecPionDeltaZero"), t0.pt()); - } else { - histos.fill(HIST("hRecPionAntiDeltaZero"), t0.pt()); - } - } - } - } - } - } - - for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(perColTracks, perColTracks))) { - - if (t0.globalIndex() == t1.globalIndex()) { - continue; - } - if (!selectionTrack(t0) || !selectionTrack(t1)) { - continue; - } - if (selectionPIDProton(t0)) { - - if (!t0.has_mcParticle()) { - continue; - } - TLorentzVector proton; - proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); - - if (selectionPIDPion(t1)) { - - if (!t1.has_mcParticle()) { - continue; - } - TLorentzVector pion; - pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); - - // select real protons and pion - const auto mcTrackProton = t0.mcParticle(); - const auto mcTrackPion = t1.mcParticle(); - - if (std::abs(mcTrackProton.pdgCode()) != protonPDG) { - continue; - } - - if (std::abs(mcTrackPion.pdgCode()) != pionPDG) { - continue; - } - - bool found_mother = false; - - for (auto& motherTrackProton : mcTrackProton.mothers_as()) { - for (auto& motherTrackPion : mcTrackPion.mothers_as()) { - if (motherTrackProton != motherTrackPion) { - continue; - } - if (std::abs(motherTrackProton.pdgCode()) != deltaPlusPlusPDG && std::abs(motherTrackProton.pdgCode()) != deltaZeroPDG) { - continue; - } - found_mother = true; - break; - } - if (found_mother) { - break; - } - } - - if (!found_mother) { - continue; - } - - TLorentzVector delta = proton + pion; - - if (abs(delta.Rapidity()) > cfgCutY) { - continue; - } - - if (t0.sign() < 0) { - if (t1.sign() < 0) { - histos.fill(HIST("hAntiDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hAntiDeltaZeroInvMass"), delta.Pt(), delta.M()); - } - } else { - if (t1.sign() < 0) { - histos.fill(HIST("hDeltaZeroInvMass"), delta.Pt(), delta.M()); - } else { - histos.fill(HIST("hDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); - } - } - } - } - } - } - - for (auto& mcParticle : mcParticles) { - - int pdg = mcParticle.pdgCode(); - if (std::abs(pdg) != deltaPlusPlusPDG && std::abs(pdg) != deltaZeroPDG) { - continue; - } - - if (std::abs(mcParticle.y()) > cfgCutY) { - continue; - } - - // if (!mcParticle.isPhysicalPrimary()) { - // continue; - // } - - auto daughters = mcParticle.daughters_as(); - bool daughtPr = false; - bool daughtPi = false; - float ptPr = -999.; - float ptPi = -999.; - double eDelta = 0.; - for (auto daught : daughters) { - if (std::abs(daught.pdgCode()) == protonPDG) { - daughtPr = true; - ptPr = daught.pt(); - eDelta += daught.e(); - } else if (std::abs(daught.pdgCode()) == pionPDG) { - daughtPi = true; - ptPi = daught.pt(); - eDelta += daught.e(); - } - } - - if (!daughtPr || !daughtPi) { - continue; - } - - float gen_mass = TMath::Sqrt(eDelta * eDelta - mcParticle.p() * mcParticle.p()); - - if (pdg > 0) { - if (std::abs(pdg) == deltaPlusPlusPDG) { - histos.fill(HIST("hDeltaPlusPlusInvMassGen"), mcParticle.pt(), gen_mass); - histos.fill(HIST("hGenProtonDeltaPlusPlus"), ptPr); - histos.fill(HIST("hGenPionDeltaPlusPlus"), ptPi); - } else if (std::abs(pdg) == deltaZeroPDG) { - histos.fill(HIST("hDeltaZeroInvMassGen"), mcParticle.pt(), gen_mass); - histos.fill(HIST("hGenProtonDeltaZero"), ptPr); - histos.fill(HIST("hGenPionDeltaZero"), ptPi); - } - } else { - if (std::abs(pdg) == deltaPlusPlusPDG) { - histos.fill(HIST("hAntiDeltaPlusPlusInvMassGen"), mcParticle.pt(), gen_mass); - histos.fill(HIST("hGenProtonAntiDeltaPlusPlus"), ptPr); - histos.fill(HIST("hGenPionAntiDeltaPlusPlus"), ptPi); - } else if (std::abs(pdg) == deltaZeroPDG) { - histos.fill(HIST("hAntiDeltaZeroInvMassGen"), mcParticle.pt(), gen_mass); - histos.fill(HIST("hGenProtonAntiDeltaZero"), ptPr); - histos.fill(HIST("hGenPionAntiDeltaZero"), ptPi); - } - } - } - } - PROCESS_SWITCH(deltaAnalysis, processMC, "Process MC", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"deltaAnalysis"})}; -} From ab918c2cec3cf8ebc4217bbadfb1a405837767d7 Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Sat, 30 May 2026 22:43:12 +0200 Subject: [PATCH 361/449] [PWGHF] taskFlow.cxx : add possibility to run container variations, comment some code to free members in the struct (#16456) --- PWGHF/HFC/Tasks/taskFlow.cxx | 1143 ++++++++++++++++++++++------------ 1 file changed, 744 insertions(+), 399 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index f41fd055852..979c580aa3a 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -204,10 +204,21 @@ struct HfTaskFlow { Configurable centralityBinsForMc{"centralityBinsForMc", false, "falsce = OFF, true = ON for data like multiplicity/centrality bins for MC steps"}; Configurable doEtaDependentFlow{"doEtaDependentFlow", false, "Flag to know if eta dependent flow should be done"}; Configurable doHeavyFlavor{"doHeavyFlavor", false, "Flag to know we in the heavy flavor case or not"}; + Configurable doMonteCarlo{"doMonteCarlo", false, "Flag to know if Monte Carlo should be done"}; Configurable doReferenceFlow{"doReferenceFlow", false, "Flag to know if reference flow should be done"}; + Configurable doVariationContainers{"doVariationContainers", false, "Flag to know if variation containers should be filled"}; + Configurable etaMcParticlesTriggerMax{"etaMcParticlesTriggerMax", 0.8f, "Maximum value for the eta of MC particles when used in cut function"}; + Configurable etaMcParticlesTriggerMin{"etaMcParticlesTriggerMin", -0.8f, "Minimum value for the eta of MC particles when used in cut function"}; + Configurable etaMcParticlesAssocMax{"etaMcParticlesAssocMax", -2.4f, "Maximum value for the eta of MC particles when used in cut function"}; + Configurable etaMcParticlesAssocMin{"etaMcParticlesAssocMin", -3.6f, "Minimum value for the eta of MC particles when used in cut function"}; + Configurable ptMcParticlesTriggerMax{"ptMcParticlesTriggerMax", 3.0f, "Maximum value for the pT of MC particles when used in cut function"}; + Configurable ptMcParticlesTriggerMin{"ptMcParticlesTriggerMin", 0.2f, "Minimum value for the pT of MC particles when used in cut function"}; + Configurable ptMcParticlesAssocMax{"ptMcParticlesAssocMax", 100.0f, "Maximum value for the pT of MC particles when used in cut function"}; + Configurable ptMcParticlesAssocMin{"ptMcParticlesAssocMin", 0.f, "Minimum value for the pT of MC particles when used in cut function"}; Configurable isReadoutCenter{"isReadoutCenter", false, "Enable Readout Center"}; Configurable nMixedEvents{"nMixedEvents", 5, "Number of mixed events per event"}; Configurable nSamples{"nSamples", 10, "number of different samples for correlations"}; + Configurable nameCorrelationContainer{"nameCorrelationContainer", "", "Add the possibility to the rename the correlation container as configurable"}; } configTask; // configurables for collisions @@ -295,8 +306,6 @@ struct HfTaskFlow { Configurable cfgCorrLevel{"cfgCorrLevel", 1, "calibration step: 0 = no corr, 1 = gain corr"}; } configFit; - TF1* fPtDepDCAxy = nullptr; - SliceCache cache; Service pdg{}; Service ccdb{}; @@ -320,6 +329,12 @@ struct HfTaskFlow { using FilteredMftTracks = soa::Filtered; + // ========================= + // using declarations : MC + // ========================= + + using SmallGroupMcCollisions = soa::SmallGroups>; + // ========================= // Filters & partitions : DATA // ========================= @@ -366,10 +381,17 @@ struct HfTaskFlow { Preslice perColLcs = aod::track::collisionId; Preslice perColMftTracks = o2::aod::fwdtrack::collisionId; Preslice perColTracks = aod::track::collisionId; + Preslice perMcColMcParticles = aod::mcparticle::mcCollisionId; PresliceUnsorted> perColReassociated2dTracks = o2::aod::fwdtrack::collisionId; PresliceUnsorted> perColReassociated3dTracks = o2::aod::fwdtrack::collisionId; + // ========================= + // Preslice : MC + // ========================= + + PresliceUnsorted collisionPerMcCollision = aod::mccollisionlabel::mcCollisionId; + // configurables for containers // TODO: flow of HF will need to be done vs. invariant mass, in the signal and side-band regions // either 1) add invariant mass axis or 2) define several containers for different inv. mass regions @@ -406,13 +428,15 @@ struct HfTaskFlow { // Correlation containers used for data OutputObj sameEvent{"sameEvent"}; OutputObj mixedEvent{"mixedEvent"}; + OutputObj sameEventTpcMft{"sameEvent_TPC_MFT"}; + OutputObj mixedEventTpcMft{"mixedEvent_TPC_MFT"}; + OutputObj sameEventTpcFt0a{"sameEvent_TPC_FT0A"}; + OutputObj mixedEventTpcFt0a{"mixedEvent_TPC_FT0A"}; + OutputObj sameEventMftFt0a{"sameEvent_MFT_FT0A"}; + OutputObj mixedEventMftFt0a{"mixedEvent_MFT_FT0A"}; OutputObj sameEventHf{"sameEventHf"}; OutputObj mixedEventHf{"mixedEventHf"}; - // Correlation containers used for Monte-Carlo - OutputObj sameEventHfMc{"sameEventHfMc"}; - OutputObj mixedEventHfMc{"mixedEventHfMc"}; - template void addHistograms() { @@ -551,12 +575,18 @@ struct HfTaskFlow { {configAxis.axisMultiplicity, "multiplicity"}, {configAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, {configAxis.axisVertex, "z-vtx (cm)"}}; - std::vector const corrAxisEta = {{configAxis.axisDeltaEta, "#Delta#eta"}, - {configAxis.axisEtaAssociated, "#eta_{associated}"}, + std::vector const corrAxisEta = {{configAxis.axisSamples, "sampling"}, + {configAxis.axisVertex, "z-vtx (cm)"}, {configAxis.axisEtaTrigger, "#eta_{trigger}"}, - {configAxis.axisMultiplicity, "multiplicity"}, + {configAxis.axisEtaAssociated, "#eta_{associated}"}, {configAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, - {configAxis.axisVertex, "z-vtx (cm)"}}; + {configAxis.axisDeltaEta, "#Delta#eta"}}; + std::vector const corrAxisVariations = {{configAxis.axisSamples, "sampling"}, + {configAxis.axisVertex, "z-vtx (cm)"}, + {configAxis.axisPtTrigger, "p_{T} (GeV/c)"}, + {configAxis.axisMultiplicity, "multiplicity"}, + {configAxis.axisDeltaPhi, "#Delta#varphi (rad)"}, + {configAxis.axisDeltaEta, "#Delta#eta"}}; std::vector const effAxis = {{configAxis.axisEtaEfficiency, "#eta"}, {configAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, {configAxis.axisVertexEfficiency, "z-vtx (cm)"}}; @@ -603,12 +633,18 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else if (configTask.doEtaDependentFlow) { + registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); + sameEventTpcMft.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisEta, effAxis, {})); + mixedEventTpcMft.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisEta, effAxis, {})); } else { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + sameEventTpcMft.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisVariations, effAxis, {})); + mixedEventTpcMft.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisVariations, effAxis, {})); } } @@ -632,49 +668,49 @@ struct HfTaskFlow { // Initialization of histograms and CorrelationContainers for TpcFv0a cases // ========================= - if (doprocessSameTpcFv0aChCh) { - addHistograms(); + // if (doprocessSameTpcFv0aChCh) { + // addHistograms(); - if (!configTask.doEtaDependentFlow) { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); - } else { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); - } - } + // if (!configTask.doEtaDependentFlow) { + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + // } else { + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + // } + // } - if (doprocessSameTpcFv0aD0Ch) { - addHistograms(); + // if (doprocessSameTpcFv0aD0Ch) { + // addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); - } + // sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + // mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); + // } - if (doprocessSameTpcFv0aLcCh) { - addHistograms(); + // if (doprocessSameTpcFv0aLcCh) { + // addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); - } + // sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + // mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); + // } // ========================= // Initialization of histograms and CorrelationContainers for MftFv0a cases // ========================= - // if (doprocessSameMftFv0aChCh || doprocessSameMftFv0aChChReassociated || doprocessSameMftFv0aReassociated3d || doprocessSameMftFv0aChChNonAmbiguous) { - if (doprocessSameMftFv0aChCh || doprocessSameMftFv0aChChReassociated || doprocessSameMftFv0aChChNonAmbiguous) { - addHistograms(); - addMftHistograms(); + // // if (doprocessSameMftFv0aChCh || doprocessSameMftFv0aChChReassociated || doprocessSameMftFv0aReassociated3d || doprocessSameMftFv0aChChNonAmbiguous) { + // if (doprocessSameMftFv0aChCh || doprocessSameMftFv0aChChReassociated || doprocessSameMftFv0aChChNonAmbiguous) { + // addHistograms(); + // addMftHistograms(); - if (!configTask.doEtaDependentFlow) { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); - } else { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); - } - } + // if (!configTask.doEtaDependentFlow) { + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + // } else { + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + // } + // } // ========================= // Initialization of histograms and CorrelationContainers for TpcFt0a cases @@ -685,12 +721,18 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else if (configTask.doEtaDependentFlow) { + registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); + sameEventTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisEta, effAxis, {})); + mixedEventTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisEta, effAxis, {})); } else { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + sameEventTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisVariations, effAxis, {})); + mixedEventTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisVariations, effAxis, {})); } } @@ -722,12 +764,18 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + registry.add("Trig_hist_MFT_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + } else if (configTask.doEtaDependentFlow) { + registry.add("Trig_hist_MFT_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); + sameEventMftFt0a.setObject(new CorrelationContainer("sameEvent_MFT_FT0A", "sameEvent_MFT_FT0A", corrAxisEta, effAxis, {})); + mixedEventMftFt0a.setObject(new CorrelationContainer("mixedEvent_MFT_FT0A", "mixedEvent_MFT_FT0A", corrAxisEta, effAxis, {})); } else { - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + registry.add("Trig_hist_MFT_FT0A", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + sameEventMftFt0a.setObject(new CorrelationContainer("sameEvent_MFT_FT0A", "sameEvent_MFT_FT0A", corrAxisVariations, effAxis, {})); + mixedEventMftFt0a.setObject(new CorrelationContainer("mixedEvent_MFT_FT0A", "mixedEvent_MFT_FT0A", corrAxisVariations, effAxis, {})); } } @@ -740,12 +788,18 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); - } else { + } else if (configTask.doEtaDependentFlow) { + registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } else { + registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisVariations, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisVariations, effAxis, {})); } } @@ -776,15 +830,42 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); - } else { + } else if (configTask.doEtaDependentFlow) { + registry.add("Trig_hist_FT0A_FT0C ", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + } else { + registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisVariations, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisVariations, effAxis, {})); } } + // ========================= + // Initialization of histograms and CorrelationContainers for McGen cases + // ========================= + + // if (doprocessSameMcGen) { + + // if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + // registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + // } else if (configTask.doEtaDependentFlow){ + // registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisEtaTrigger}}}); + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisEta, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisEta, effAxis, {})); + // } else { + // registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{configAxis.axisSamples, configAxis.axisVertex, configAxis.axisPtTrigger}}}); + // sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisVariations, effAxis, {})); + // mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisVariations, effAxis, {})); + // } + // } + } // End of init() function // ========================= @@ -904,29 +985,29 @@ struct HfTaskFlow { return RecoDecay::phi(chPos.X() + (*offsetFT0)[i].getX(), chPos.Y() + (*offsetFT0)[i].getY()); } - double getPhiFV0(unsigned int chno) const - { - int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; - bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); - float offsetX{}, offsetY{}; - if (isChnoInLeft) { - offsetX = (*offsetFV0)[0].getX(); - offsetY = (*offsetFV0)[0].getY(); - } else { - offsetX = (*offsetFV0)[1].getX(); - offsetY = (*offsetFV0)[1].getY(); - } + // double getPhiFV0(unsigned int chno) const + // { + // int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + // bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + // float offsetX{}, offsetY{}; + // if (isChnoInLeft) { + // offsetX = (*offsetFV0)[0].getX(); + // offsetY = (*offsetFV0)[0].getY(); + // } else { + // offsetX = (*offsetFV0)[1].getX(); + // offsetY = (*offsetFV0)[1].getY(); + // } - o2::fv0::Point3Dsimple chPos{}; - chPos = fv0Det->getReadoutCenter(chno); + // o2::fv0::Point3Dsimple chPos{}; + // chPos = fv0Det->getReadoutCenter(chno); - // if (configTask.isReadoutCenter) - // chPos = fv0Det->getReadoutCenter(chno); - // else - // chPos = fv0Det->getCellCenter(chno); + // // if (configTask.isReadoutCenter) + // // chPos = fv0Det->getReadoutCenter(chno); + // // else + // // chPos = fv0Det->getCellCenter(chno); - return RecoDecay::phi(chPos.x + offsetX, chPos.y + offsetY); - } + // return RecoDecay::phi(chPos.x + offsetX, chPos.y + offsetY); + // } double getEtaFT0(uint chno, int i) { @@ -943,35 +1024,35 @@ struct HfTaskFlow { return -std::log(std::tan(0.5 * theta)); } - double getEtaFV0(unsigned int chno) const - { - int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; - bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); - float offsetX{}, offsetY{}, offsetZ{}; - if (isChnoInLeft) { - offsetX = (*offsetFV0)[0].getX(); - offsetY = (*offsetFV0)[0].getY(); - offsetZ = (*offsetFV0)[0].getZ(); - } else { - offsetX = (*offsetFV0)[1].getX(); - offsetY = (*offsetFV0)[1].getY(); - offsetZ = (*offsetFV0)[1].getZ(); - } - - o2::fv0::Point3Dsimple chPos{}; - chPos = fv0Det->getReadoutCenter(chno); - // if (configTask.isReadoutCenter) - // chPos = fv0Det->getReadoutCenter(chno); - // else - // chPos = fv0Det->getCellCenter(chno); - - auto x = chPos.x + offsetX; - auto y = chPos.y + offsetY; - auto z = chPos.z + offsetZ; - auto r = std::sqrt(x * x + y * y); - auto theta = std::atan2(r, z); - return -std::log(std::tan(0.5 * theta)); - } + // double getEtaFV0(unsigned int chno) const + // { + // int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + // bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + // float offsetX{}, offsetY{}, offsetZ{}; + // if (isChnoInLeft) { + // offsetX = (*offsetFV0)[0].getX(); + // offsetY = (*offsetFV0)[0].getY(); + // offsetZ = (*offsetFV0)[0].getZ(); + // } else { + // offsetX = (*offsetFV0)[1].getX(); + // offsetY = (*offsetFV0)[1].getY(); + // offsetZ = (*offsetFV0)[1].getZ(); + // } + + // o2::fv0::Point3Dsimple chPos{}; + // chPos = fv0Det->getReadoutCenter(chno); + // // if (configTask.isReadoutCenter) + // // chPos = fv0Det->getReadoutCenter(chno); + // // else + // // chPos = fv0Det->getCellCenter(chno); + + // auto x = chPos.x + offsetX; + // auto y = chPos.y + offsetY; + // auto z = chPos.z + offsetZ; + // auto r = std::sqrt(x * x + y * y); + // auto theta = std::atan2(r, z); + // return -std::log(std::tan(0.5 * theta)); + // } template void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, int fitType, float& amplitude) @@ -1259,7 +1340,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1294,12 +1375,16 @@ struct HfTaskFlow { } // fill single-track distributions - if (!fillingHFcontainer) { // if not HF-h case - if (!configTask.doEtaDependentFlow) { // if not eta-differential flow, fill vs pt, otherwise fill vs eta - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); - } else { - target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + if (!fillingHFcontainer) { // if not HF-h case + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + + if (configTask.doEtaDependentFlow) { + registry.fill(HIST("Trig_hist_TPC_MFT"), sampleIndex, posZ, track1.eta(), triggerWeight); // think about event weight in near future } + if (configTask.doVariationContainers) { + registry.fill(HIST("Trig_hist_TPC_MFT"), sampleIndex, posZ, track1.pt(), triggerWeight); + } + } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1426,11 +1511,14 @@ struct HfTaskFlow { if (!fillingHFcontainer) { // fill pair correlations - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); + } else if (configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, sampleIndex, posZ, eta2, eta1, deltaPhi, eta1 - eta2, + triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, posZ, pt1, multiplicity, deltaPhi, eta1 - eta2, triggerWeight * associatedWeight); } } else { @@ -1474,7 +1562,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1506,11 +1594,15 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - if (!configTask.doEtaDependentFlow) { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); - } else { - target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + + if (configTask.doEtaDependentFlow) { + registry.fill(HIST("Trig_hist_TPC_MFT"), sampleIndex, posZ, track1.eta(), triggerWeight); // think about event weight in near future + } + if (configTask.doVariationContainers) { + registry.fill(HIST("Trig_hist_TPC_MFT"), sampleIndex, posZ, track1.pt(), triggerWeight); } + } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1621,11 +1713,14 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); if (!fillingHFcontainer) { - if (!configTask.doEtaDependentFlow) { + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); + } else if (configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, sampleIndex, posZ, eta2, eta1, deltaPhi, eta1 - eta2, + triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, posZ, pt1, multiplicity, deltaPhi, eta1 - eta2, triggerWeight * associatedWeight); } } else { @@ -1658,7 +1753,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1705,11 +1800,23 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - if (!configTask.doEtaDependentFlow) { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); - } else { - target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + + if (configTask.doEtaDependentFlow) { + if (fitType == isFT0A) { + registry.fill(HIST("Trig_hist_TPC_FT0A"), sampleIndex, posZ, track1.eta(), triggerWeight); // think about event weight in near future + } else { + registry.fill(HIST("Trig_hist_TPC_FT0C"), sampleIndex, posZ, track1.eta(), triggerWeight); // think about event weight in near future + } } + if (configTask.doVariationContainers) { + if (fitType == isFT0A) { + registry.fill(HIST("Trig_hist_TPC_FT0A"), sampleIndex, posZ, track1.pt(), triggerWeight); // think about event weight in near future + } else { + registry.fill(HIST("Trig_hist_TPC_FT0C"), sampleIndex, posZ, track1.pt(), triggerWeight); // think about event weight in near future + } + } + } else { target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } @@ -1760,45 +1867,45 @@ struct HfTaskFlow { } } // end of if condition to fill QA plots for trigger particle - // ASSOCIATED PARTICLE IF USING FV0 - if constexpr (std::is_same_v) { - for (std::size_t indexChannel = 0; indexChannel < tracks2.channel().size(); indexChannel++) { - - auto channelId = tracks2.channel()[indexChannel]; - auto phi2 = getPhiFV0(channelId); - auto eta2 = getEtaFV0(channelId); - float deltaPhi = phi1 - phi2; - deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - - if (!fillingHFcontainer) { - if (!configTask.doEtaDependentFlow) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); - } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); - } - } else { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, - triggerWeight * associatedWeight); - } - - // FILL QA PLOTS for associated particle - if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { - if constexpr (!std::is_same_v) { // If not FilteredMftTracks as trigger -> TPC-FV0a correlations - if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-FV0a D0-h - fillAssociatedQa(multiplicity, eta2, phi2); - } else if constexpr (std::is_same_v) { // IF LC CASE -> TPC-FV0a Lc-h - fillAssociatedQa(multiplicity, eta2, phi2); - } else if constexpr (std::is_same_v) { // IF NEITHER D0 NOR LC -> ch. part. - ch. part - fillAssociatedQa(multiplicity, eta2, phi2); - } - } else { // If FilteredMftTracks as trigger -> MFT-FV0a (non reassoc/ambiguous) correlations - fillAssociatedQa(multiplicity, eta2, phi2); - } - } // end of if condition to fill QA plots for associated particle - } // end of loop over FV0 channel indices - } // end of if condition for FV0s + // // ASSOCIATED PARTICLE IF USING FV0 + // if constexpr (std::is_same_v) { + // for (std::size_t indexChannel = 0; indexChannel < tracks2.channel().size(); indexChannel++) { + + // auto channelId = tracks2.channel()[indexChannel]; + // auto phi2 = getPhiFV0(channelId); + // auto eta2 = getEtaFV0(channelId); + // float deltaPhi = phi1 - phi2; + // deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) + + // if (!fillingHFcontainer) { + // if (!configTask.doEtaDependentFlow) { + // target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + // triggerWeight * associatedWeight); + // } else { + // target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + // triggerWeight * associatedWeight); + // } + // } else { + // target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, + // triggerWeight * associatedWeight); + // } + + // // FILL QA PLOTS for associated particle + // if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { + // if constexpr (!std::is_same_v) { // If not FilteredMftTracks as trigger -> TPC-FV0a correlations + // if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-FV0a D0-h + // fillAssociatedQa(multiplicity, eta2, phi2); + // } else if constexpr (std::is_same_v) { // IF LC CASE -> TPC-FV0a Lc-h + // fillAssociatedQa(multiplicity, eta2, phi2); + // } else if constexpr (std::is_same_v) { // IF NEITHER D0 NOR LC -> ch. part. - ch. part + // fillAssociatedQa(multiplicity, eta2, phi2); + // } + // } else { // If FilteredMftTracks as trigger -> MFT-FV0a (non reassoc/ambiguous) correlations + // fillAssociatedQa(multiplicity, eta2, phi2); + // } + // } // end of if condition to fill QA plots for associated particle + // } // end of loop over FV0 channel indices + // } // end of if condition for FV0s // ASSOCIATED PARTICLE IF USING FT0 if constexpr (std::is_same_v) { @@ -1824,11 +1931,14 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - if (!configTask.doEtaDependentFlow) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + target->getPairHist()->Fill(step, eta1 - eta2, 0.5, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else if (configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, sampleIndex, posZ, eta2, eta1, deltaPhi, eta1 - eta2, amplitude * triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, posZ, pt1, multiplicity, deltaPhi, eta1 - eta2, amplitude * triggerWeight * associatedWeight); } } else { @@ -1880,7 +1990,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1927,6 +2037,13 @@ struct HfTaskFlow { target->getTriggerHist()->Fill(step, eta1, multiplicity, posZ, triggerWeight); } + if (configTask.doEtaDependentFlow) { + registry.fill(HIST("Trig_hist_MFT_FT0A"), sampleIndex, posZ, eta1, triggerWeight); // think about event weight in near future + } + if (configTask.doVariationContainers) { + registry.fill(HIST("Trig_hist_MFT_FT0A"), sampleIndex, posZ, pt1, triggerWeight); + } + // FILL QA PLOTS for trigger particle if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { if constexpr (std::is_same_v) { @@ -1938,31 +2055,31 @@ struct HfTaskFlow { } } // end of if condition to fill QA plots for trigger particle - // ASSOCIATED PARTICLE FOR FV0s - if constexpr (std::is_same_v) { - for (std::size_t indexChannel = 0; indexChannel < tracks2.channel().size(); indexChannel++) { + // // ASSOCIATED PARTICLE FOR FV0s + // if constexpr (std::is_same_v) { + // for (std::size_t indexChannel = 0; indexChannel < tracks2.channel().size(); indexChannel++) { - auto channelId = tracks2.channel()[indexChannel]; - auto phi2 = getPhiFV0(channelId); - auto eta2 = getEtaFV0(channelId); + // auto channelId = tracks2.channel()[indexChannel]; + // auto phi2 = getPhiFV0(channelId); + // auto eta2 = getEtaFV0(channelId); - float deltaPhi = phi1 - phi2; - deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) + // float deltaPhi = phi1 - phi2; + // deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - if (!configTask.doEtaDependentFlow) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); - } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); - } + // if (!configTask.doEtaDependentFlow) { + // target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + // triggerWeight * associatedWeight); + // } else { + // target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + // triggerWeight * associatedWeight); + // } - // FILL QA PLOTS for associated particle - if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { - fillAssociatedQa(multiplicity, eta2, phi2); - } // end of if condition to fill QA plots for associated particle - } // end of loop over FV0 channel indices - } // end of if condition for FV0s + // // FILL QA PLOTS for associated particle + // if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { + // fillAssociatedQa(multiplicity, eta2, phi2); + // } // end of if condition to fill QA plots for associated particle + // } // end of loop over FV0 channel indices + // } // end of if condition for FV0s // ASSOCIATED PARTICLE FOR FT0s if constexpr (std::is_same_v) { @@ -1987,11 +2104,14 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - if (!configTask.doEtaDependentFlow) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + target->getPairHist()->Fill(step, eta1 - eta2, 0.5, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else if (configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, sampleIndex, posZ, eta2, eta1, deltaPhi, eta1 - eta2, amplitude * triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, eta2, eta1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, posZ, pt1, multiplicity, deltaPhi, eta1 - eta2, amplitude * triggerWeight * associatedWeight); } @@ -2014,7 +2134,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE FROM FT0A for (std::size_t indexChannelA = 0; indexChannelA < ft0as.channelA().size(); indexChannelA++) { @@ -2025,14 +2145,17 @@ struct HfTaskFlow { auto phiA = getPhiFT0(channelIdA, isFT0A); auto etaA = getEtaFT0(channelIdA, isFT0A); - if (!configTask.doEtaDependentFlow) { - target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, amplitude * triggerWeight); - } else { - target->getTriggerHist()->Fill(step, etaA, multiplicity, posZ, amplitude * triggerWeight); + target->getTriggerHist()->Fill(step, 0.5, multiplicity, posZ, amplitude * triggerWeight); + + if (configTask.doEtaDependentFlow) { + registry.fill(HIST("Trig_hist_FT0A_FT0C"), sampleIndex, posZ, etaA, triggerWeight); // think about event weight in near future + } + if (configTask.doVariationContainers) { + registry.fill(HIST("Trig_hist_FT0A_FT0C"), sampleIndex, posZ, 0.5, triggerWeight); } if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { - fillTriggerQa(multiplicity, etaA, phiA, 0.f); + fillTriggerQa(multiplicity, etaA, phiA, 0.5); } // end of fill trigger QA // ASSOCIATED PARTICLE FROM FT0C @@ -2045,11 +2168,14 @@ struct HfTaskFlow { auto etaC = getEtaFT0(channelIdC, isFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); - if (!configTask.doEtaDependentFlow) { - target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + target->getPairHist()->Fill(step, etaA - etaC, 0.5, 0.5, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); + } else if (configTask.doEtaDependentFlow) { + target->getPairHist()->Fill(step, sampleIndex, posZ, etaC, etaA, deltaPhi, etaA - etaC, amplitude * triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, etaA - etaC, etaC, etaA, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, posZ, 0.5, multiplicity, deltaPhi, etaA - etaC, amplitude * triggerWeight * associatedWeight); } @@ -2060,6 +2186,68 @@ struct HfTaskFlow { } // end of trigger loop } // end of fillCorrelationsFt0aFt0c + // template + // void fillCorrelationsMonteCarlo(TTarget target, CorrelationContainer::CFStep step, + // TTracksTrig const& tracks1, TTracksAssoc const& tracks2, + // float multiplicity, float posZ, bool sameEvent) + // { + // auto triggerWeight = 1; + // auto associatedWeight = 1; + // auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + + // for (auto const& track1 : tracks1) { + + // if (track1.eta() < configTask.etaMcParticlesTriggerMin || track1.eta() > configTask.etaMcParticlesTriggerMax) { + // continue; + // } + // if (track1.pt() < configTask.ptMcParticlesTriggerMin || track1.pt() > configTask.ptMcParticlesTriggerMax) { + // continue; + // } + // if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track1.isPhysicalPrimary()) { + // continue; + // } + + // target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, triggerWeight); + // if (configTask.doEtaDependentFlow) { + // registry.fill(HIST("Trig_hist"), sampleIndex, posZ, track1.eta(), triggerWeight); + // } else { + // registry.fill(HIST("Trig_hist"), sampleIndex, posZ, track1.pt(), triggerWeight); + // } + + // for (auto const& track2 : tracks2) { + + // if (track1.globalIndex() == track2.globalIndex()) { + // continue; + // } + // if (track2.eta() < configTask.etaMcParticlesAssocMin || track2.eta() > configTask.etaMcParticlesAssocMax) { + // continue; + // } + // if (track2.pt() < configTask.ptMcParticlesAssocMin || track2.pt() > configTask.ptMcParticlesAssocMax) { + // continue; + // } + // if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track2.isPhysicalPrimary()) { + // continue; + // } + + // float deltaPhi = RecoDecay::constrainAngle(track2.phi() - track1.phi(), -PIHalf); + // float deltaEta = track2.eta() - track1.eta(); + + // if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + // target->getPairHist()->Fill(step, deltaEta, track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, + // triggerWeight * associatedWeight); + // } else if (configTask.doEtaDependentFlow) { + // target->getPairHist()->Fill(step, sampleIndex, posZ, track2.eta(), track1.eta(), deltaPhi, deltaEta, + // triggerWeight * associatedWeight); + // } else { + // target->getPairHist()->Fill(step, sampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta, + // triggerWeight * associatedWeight); + // } + // } // end of loop over track2 + + // } // end of loop over track1 + // } + // =============================================================================================================================================================================== // mixCollisions for RECONSTRUCTED events // =============================================================================================================================================================================== @@ -2397,8 +2585,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, mftTracks, multiplicity, collision.posZ(), true, getMagneticField(bc.timestamp())); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, mftTracks, multiplicity, collision.posZ(), true, getMagneticField(bc.timestamp())); + } else { + sameEventTpcMft->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(sameEventTpcMft, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, mftTracks, multiplicity, collision.posZ(), true, getMagneticField(bc.timestamp())); + } } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChCh, "DATA : Process same-event correlations for TPC-MFT h-h case", false); @@ -2420,8 +2613,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + } else { + sameEventTpcMft->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEventTpcMft, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + } } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChChReassociated, "DATA : Process same-event correlations for TPC-MFT h-h case reassociated", false); @@ -2445,8 +2643,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + } else { + sameEventTpcMft->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEventTpcMft, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + } } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChChReassociated3d, "DATA : Process same-event correlations for TPC-MFT h-h case 3d reassociated", false); @@ -2468,8 +2671,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + } else { + sameEventTpcMft->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEventTpcMft, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + } } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChChNonAmbiguous, "DATA : Process same-event correlations for TPC-MFT h-h case with non-ambiguous tracks", false); @@ -2583,130 +2791,130 @@ struct HfTaskFlow { // DATA : process same event correlations: TPC-FV0A Ch. Part. - Ch. Part // ===================================== - void processSameTpcFv0aChCh(FilteredCollisionsWSelMult::iterator const& collision, - FilteredTracksWDcaSel const& tracks, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } - - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - - registry.fill(HIST("Data/hNTracks"), tracks.size()); - const auto multiplicity = getMultiplicityEstimator(collision, true); - - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } - - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aChCh, "DATA : Process same-event correlations for TPC-FV0-A h-h case", false); - - // ===================================== - // DATA : process same event correlations: TPC-FV0A D0 - Ch. Part - // ===================================== - - void processSameTpcFv0aD0Ch(FilteredCollisionsWSelMult::iterator const& collision, - HfCandidatesSelD0 const& candidates, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } - - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - const auto multiplicity = getMultiplicityEstimator(collision, true); - - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } - - sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aD0Ch, "DATA : Process same-event correlations for TPC-FV0-A D0-h case", false); - - // ===================================== - // DATA : process same event correlations: TPC-FV0A Lc - Ch. Part - // ===================================== - - void processSameTpcFv0aLcCh(FilteredCollisionsWSelMult::iterator const& collision, - HfCandidatesSelLc const& candidates, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } - - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - const auto multiplicity = getMultiplicityEstimator(collision, true); - - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } - - sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aLcCh, "DATA : Process same-event correlations for TPC-FV0-A Lc-h case", false); - - // ===================================== - // DATA : process same event correlations: MFT-FV0A Ch. Part. - Ch. Part - // ===================================== - - void processSameMftFv0aChCh(FilteredCollisionsWSelMult::iterator const& collision, - FilteredMftTracks const& mftTracks, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } - - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - const auto multiplicity = getMultiplicityEstimator(collision, true); - - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } - - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, mftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChCh, "DATA : Process same-event correlations for MFT-FV0-A h-h case", false); - - void processSameMftFv0aChChReassociated(FilteredCollisionsWSelMult::iterator const& collision, - soa::SmallGroups const& reassociatedMftTracks, - FilteredMftTracks const&, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } - - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - const auto multiplicity = getMultiplicityEstimator(collision, true); - - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } - - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, false, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChChReassociated, "DATA : Process same-event correlations for MFT-FV0a h-h case reassociated", false); + // void processSameTpcFv0aChCh(FilteredCollisionsWSelMult::iterator const& collision, + // FilteredTracksWDcaSel const& tracks, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } + + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + + // registry.fill(HIST("Data/hNTracks"), tracks.size()); + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } + + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aChCh, "DATA : Process same-event correlations for TPC-FV0-A h-h case", false); + + // // ===================================== + // // DATA : process same event correlations: TPC-FV0A D0 - Ch. Part + // // ===================================== + + // void processSameTpcFv0aD0Ch(FilteredCollisionsWSelMult::iterator const& collision, + // HfCandidatesSelD0 const& candidates, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } + + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } + + // sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFIT(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aD0Ch, "DATA : Process same-event correlations for TPC-FV0-A D0-h case", false); + + // // ===================================== + // // DATA : process same event correlations: TPC-FV0A Lc - Ch. Part + // // ===================================== + + // void processSameTpcFv0aLcCh(FilteredCollisionsWSelMult::iterator const& collision, + // HfCandidatesSelLc const& candidates, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } + + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } + + // sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFIT(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameTpcFv0aLcCh, "DATA : Process same-event correlations for TPC-FV0-A Lc-h case", false); + + // // ===================================== + // // DATA : process same event correlations: MFT-FV0A Ch. Part. - Ch. Part + // // ===================================== + + // void processSameMftFv0aChCh(FilteredCollisionsWSelMult::iterator const& collision, + // FilteredMftTracks const& mftTracks, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } + + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } + + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, mftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChCh, "DATA : Process same-event correlations for MFT-FV0-A h-h case", false); + + // void processSameMftFv0aChChReassociated(FilteredCollisionsWSelMult::iterator const& collision, + // soa::SmallGroups const& reassociatedMftTracks, + // FilteredMftTracks const&, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } + + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } + + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, false, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChChReassociated, "DATA : Process same-event correlations for MFT-FV0a h-h case reassociated", false); /* void processSameMftFv0aChChReassociated3d(FilteredCollisionsWSelMult::iterator const& collision, @@ -2733,28 +2941,28 @@ struct HfTaskFlow { PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChChReassociated3d, "DATA : Process same-event correlations for MFT-FV0a h-h case 3d reassociated", false); */ - void processSameMftFv0aChChNonAmbiguous(FilteredCollisionsWSelMult::iterator const& collision, - soa::SmallGroups const& reassociatedMftTracks, - FilteredMftTracks const&, - aod::FV0As const& fv0as) - { - if (!(isAcceptedCollision(collision, true))) { - return; - } + // void processSameMftFv0aChChNonAmbiguous(FilteredCollisionsWSelMult::iterator const& collision, + // soa::SmallGroups const& reassociatedMftTracks, + // FilteredMftTracks const&, + // aod::FV0As const& fv0as) + // { + // if (!(isAcceptedCollision(collision, true))) { + // return; + // } - if (collision.has_foundFV0()) { - const auto& fv0 = collision.foundFV0(); - const auto multiplicity = getMultiplicityEstimator(collision, true); + // if (collision.has_foundFV0()) { + // const auto& fv0 = collision.foundFV0(); + // const auto multiplicity = getMultiplicityEstimator(collision, true); - if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { - return; - } + // if (multiplicity < configCollision.minMultiplicity || multiplicity > configCollision.maxMultiplicity) { + // return; + // } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, true, isFV0A); - } - } - PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChChNonAmbiguous, "DATA : Process same-event correlations for MFT-FV0a h-h non-ambiguous case", false); + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, fv0, fv0as, multiplicity, collision.posZ(), true, true, isFV0A); + // } + // } + // PROCESS_SWITCH(HfTaskFlow, processSameMftFv0aChChNonAmbiguous, "DATA : Process same-event correlations for MFT-FV0a h-h non-ambiguous case", false); // ===================================== // DATA : process same event correlations: TPC-FT0A Ch. Part. - Ch. Part @@ -2781,8 +2989,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + } else { + sameEventTpcFt0a->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFIT(sameEventTpcFt0a, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + } } } PROCESS_SWITCH(HfTaskFlow, processSameTpcFt0aChCh, "DATA : Process same-event correlations for TPC-FT0-A h-h case", false); @@ -2871,8 +3084,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, mftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFIT(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, mftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + } else { + sameEventMftFt0a->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFIT(sameEventMftFt0a, CorrelationContainer::CFStep::kCFStepReconstructed, mftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, isFT0A); + } } } PROCESS_SWITCH(HfTaskFlow, processSameMftFt0aChCh, "DATA : Process same-event correlations for MFT-FT0-A h-h case", false); @@ -2898,8 +3116,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + } else { + sameEventMftFt0a->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEventMftFt0a, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + } } } PROCESS_SWITCH(HfTaskFlow, processSameMftFt0aChChReassociated, "DATA : Process same-event correlations for MFT-FT0-A h-h case reassociated", false); @@ -2925,8 +3148,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + } else { + sameEventMftFt0a->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEventMftFt0a, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, false, isFT0A); + } } } PROCESS_SWITCH(HfTaskFlow, processSameMftFt0aChChReassociated3d, "DATA : Process same-event correlations for MFT-FT0-A h-h case reassociated 3d", false); @@ -2952,8 +3180,13 @@ struct HfTaskFlow { return; } - sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, true, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, true, isFT0A); + } else { + sameEventMftFt0a->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsFITReassociatedMftTracks(sameEventMftFt0a, CorrelationContainer::CFStep::kCFStepReconstructed, reassociatedMftTracks, ft0, ft0as, multiplicity, collision.posZ(), true, true, isFT0A); + } } } PROCESS_SWITCH(HfTaskFlow, processSameMftFt0aChChNonAmbiguous, "DATA : Process same-event correlations for MFT-FT0-A h-h case non ambiguous", false); @@ -3078,6 +3311,33 @@ struct HfTaskFlow { } PROCESS_SWITCH(HfTaskFlow, processSameFt0aFt0cChCh, "DATA : Process same-event correlations for FT0A-FT0C h-h case", false); + // =================================================================================================================================================================================================================================================================== + // MONTE-CARLO + // =================================================================================================================================================================================================================================================================== + + // void processSameMcGen(aod::McCollisions::iterator const& mcCollision, + // aod::McParticles const& mcParticles, + // SmallGroupMcCollisions const& collisions) + // { + // if (!(abs(mcCollision.posZ()) <= configCollision.zVertexMax)) { + // return; + // } + // if ( (mcParticles.size() < configCollision.minMultiplicity) || (mcParticles.size() > configCollision.maxMultiplicity) ) { + // return; + // } + + // sameEvent->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + // fillCorrelationsMonteCarlo(sameEvent, CorrelationContainer::CFStep::kCFStepAll, mcParticles, mcParticles, mcParticles.size(), mcCollision.posZ(), true); + + // if (collisions.size() == 0) { + // return; + // } + + // sameEvent->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + // fillCorrelationsMonteCarlo(sameEvent, CorrelationContainer::CFStep::kCFStepTrackedOnlyPrim, mcParticles, mcParticles, mcParticles.size(), mcCollision.posZ(), true); + // } + // PROCESS_SWITCH(HfTaskFlow, processSameMcGen, "MC Gen : Process same-event correlations", false); + // =================================================================================================================================================================================================================================================================== // =================================================================================================================================================================================================================================================================== // MIXED EVENT PROCESS FUNCTIONS @@ -3135,7 +3395,11 @@ struct HfTaskFlow { FilteredMftTracks const& mftTracks, aod::BCsWithTimestamps const& bcs) { - mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, mixedEvent, bcs); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, mixedEvent, bcs); + } else { + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, mixedEventTpcMft, bcs); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChCh, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -3144,7 +3408,11 @@ struct HfTaskFlow { FilteredMftTracks const& mftTracks, aod::BCsWithTimestamps const& bcs) { - mixCollisionsBis(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, perColTracks, perColMftTracks, mixedEvent, bcs); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsBis(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, perColTracks, perColMftTracks, mixedEvent, bcs); + } else { + mixCollisionsBis(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, perColTracks, perColMftTracks, mixedEventTpcMft, bcs); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChChBis, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -3153,7 +3421,11 @@ struct HfTaskFlow { FilteredMftTracks const& /*mftTracks*/, soa::SmallGroups const& reassociated2dMftTracks) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEvent, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEvent, false); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEventTpcMft, false); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChChReassociated2d, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -3162,7 +3434,11 @@ struct HfTaskFlow { FilteredMftTracks const& /*mftTracks*/, soa::SmallGroups const& reassociated3dMftTracks) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated3dMftTracks, perColTracks, perColReassociated3dTracks, mixedEvent, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated3dMftTracks, perColTracks, perColReassociated3dTracks, mixedEvent, false); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated3dMftTracks, perColTracks, perColReassociated3dTracks, mixedEventTpcMft, false); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChChReassociated3d, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -3171,7 +3447,11 @@ struct HfTaskFlow { FilteredMftTracks const& /*mftTracks*/, soa::SmallGroups const& reassociated2dMftTracks) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEvent, true); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEvent, true); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociated2dMftTracks, perColTracks, perColReassociated2dTracks, mixedEventTpcMft, true); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChChNonAmbiguous, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -3206,49 +3486,49 @@ struct HfTaskFlow { // DATA : process mixed event correlations: TPC-FV0-A ch part. - ch. part. case // ===================================== - void processMixedTpcFv0aChCh(FilteredCollisionsWSelMult const& collisions, - FilteredTracksWDcaSel const& tracks, - aod::FV0As const& fv0as) - { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, tracks, fv0as, perColTracks, mixedEvent, isFV0A); - } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aChCh, "DATA : Process mixed-event correlations for TPC-FV0-A h-h case", false); + // void processMixedTpcFv0aChCh(FilteredCollisionsWSelMult const& collisions, + // FilteredTracksWDcaSel const& tracks, + // aod::FV0As const& fv0as) + // { + // mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, tracks, fv0as, perColTracks, mixedEvent, isFV0A); + // } + // PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aChCh, "DATA : Process mixed-event correlations for TPC-FV0-A h-h case", false); // ===================================== // DATA : process mixed event correlations: TPC-FV0-A D0 - ch. part. case // ===================================== - void processMixedTpcFv0aD0Ch(FilteredCollisionsWSelMult const& collisions, - HfCandidatesSelD0 const& candidates, - aod::FV0As const& fv0as) - { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, candidates, fv0as, perColD0s, mixedEventHf, isFV0A); - } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aD0Ch, "DATA : Process mixed-event correlations for TPC-FV0-A D0-h case", false); + // void processMixedTpcFv0aD0Ch(FilteredCollisionsWSelMult const& collisions, + // HfCandidatesSelD0 const& candidates, + // aod::FV0As const& fv0as) + // { + // mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, candidates, fv0as, perColD0s, mixedEventHf, isFV0A); + // } + // PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aD0Ch, "DATA : Process mixed-event correlations for TPC-FV0-A D0-h case", false); // ===================================== // DATA : process mixed event correlations: TPC-FV0-A Lc - ch. part. case // ===================================== - void processMixedTpcFv0aLcCh(FilteredCollisionsWSelMult const& collisions, - HfCandidatesSelLc const& candidates, - aod::FV0As const& fv0as) - { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, candidates, fv0as, perColLcs, mixedEventHf, isFV0A); - } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aLcCh, "DATA : Process mixed-event correlations for TPC-FV0-A Lc-h case", false); + // void processMixedTpcFv0aLcCh(FilteredCollisionsWSelMult const& collisions, + // HfCandidatesSelLc const& candidates, + // aod::FV0As const& fv0as) + // { + // mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, candidates, fv0as, perColLcs, mixedEventHf, isFV0A); + // } + // PROCESS_SWITCH(HfTaskFlow, processMixedTpcFv0aLcCh, "DATA : Process mixed-event correlations for TPC-FV0-A Lc-h case", false); // ===================================== // DATA : process mixed event correlations: TPC-FV0-A ch part. - ch. part. case // ===================================== - void processMixedMftFv0aChCh(FilteredCollisionsWSelMult const& collisions, - FilteredMftTracks const& mftTracks, - aod::FV0As const& fv0as) - { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, mftTracks, fv0as, perColMftTracks, mixedEvent, isFV0A); - } - PROCESS_SWITCH(HfTaskFlow, processMixedMftFv0aChCh, "DATA : Process mixed-event correlations for Mft-FV0-A h-h case", false); + // void processMixedMftFv0aChCh(FilteredCollisionsWSelMult const& collisions, + // FilteredMftTracks const& mftTracks, + // aod::FV0As const& fv0as) + // { + // mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, mftTracks, fv0as, perColMftTracks, mixedEvent, isFV0A); + // } + // PROCESS_SWITCH(HfTaskFlow, processMixedMftFv0aChCh, "DATA : Process mixed-event correlations for Mft-FV0-A h-h case", false); // ===================================== // DATA : process mixed event correlations: TPC-FT0-A ch part. - ch. part. case @@ -3258,7 +3538,11 @@ struct HfTaskFlow { FilteredTracksWDcaSel const& tracks, aod::FT0s const& ft0s) { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, tracks, ft0s, perColTracks, mixedEvent, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, tracks, ft0s, perColTracks, mixedEvent, isFT0A); + } else { + mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, tracks, ft0s, perColTracks, mixedEventTpcFt0a, isFT0A); + } } PROCESS_SWITCH(HfTaskFlow, processMixedTpcFt0aChCh, "DATA : Process mixed-event correlations for TPC-FT0-A h-h case", false); @@ -3294,7 +3578,11 @@ struct HfTaskFlow { FilteredMftTracks const& mftTracks, aod::FT0s const& ft0s) { - mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, mftTracks, ft0s, perColMftTracks, mixedEvent, isFT0A); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, mftTracks, ft0s, perColMftTracks, mixedEvent, isFT0A); + } else { + mixCollisionsFIT(collisions, CorrelationContainer::kCFStepReconstructed, mftTracks, ft0s, perColMftTracks, mixedEventMftFt0a, isFT0A); + } } PROCESS_SWITCH(HfTaskFlow, processMixedMftFt0aChCh, "DATA : Process mixed-event correlations for MFT-FT0-A h-h case", false); @@ -3303,7 +3591,11 @@ struct HfTaskFlow { soa::SmallGroups const& reassociated2dMftTracks, aod::FT0s const& ft0s) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEvent, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEvent, false); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEventMftFt0a, false); + } } PROCESS_SWITCH(HfTaskFlow, processMixedMftFt0aChChReassociated2d, "DATA : Process mixed-event correlations for MFT-FT0-A h-h case", false); @@ -3312,7 +3604,11 @@ struct HfTaskFlow { soa::SmallGroups const& reassociated3dMftTracks, aod::FT0s const& ft0s) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated3dMftTracks, ft0s, perColReassociated3dTracks, perColReassociated3dTracks, mixedEvent, false); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated3dMftTracks, ft0s, perColReassociated3dTracks, perColReassociated3dTracks, mixedEvent, false); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated3dMftTracks, ft0s, perColReassociated3dTracks, perColReassociated3dTracks, mixedEventMftFt0a, false); + } } PROCESS_SWITCH(HfTaskFlow, processMixedMftFt0aChChReassociated3d, "DATA : Process mixed-event correlations for MFT-FT0-A h-h case", false); @@ -3321,7 +3617,11 @@ struct HfTaskFlow { soa::SmallGroups const& reassociated2dMftTracks, aod::FT0s const& ft0s) { - mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEvent, true); + if (!configTask.doEtaDependentFlow && !configTask.doVariationContainers) { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEvent, true); + } else { + mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, reassociated2dMftTracks, ft0s, perColReassociated2dTracks, perColReassociated2dTracks, mixedEventMftFt0a, true); + } } PROCESS_SWITCH(HfTaskFlow, processMixedMftFt0aChChNonAmbiguous, "DATA : Process mixed-event correlations for MFT-FT0-A h-h case", false); @@ -3372,6 +3672,51 @@ struct HfTaskFlow { } PROCESS_SWITCH(HfTaskFlow, processMixedFt0aFt0cChCh, "DATA : Process mixed-event correlations for FT0A-FT0C h-h case", false); + // =================================================================================================================================================================================================================================================================== + // MONTE-CARLO + // =================================================================================================================================================================================================================================================================== + + // void processMixedMcGen(aod::McCollisions const& mcCollisions, + // aod::McParticles const& mcParticles, + // SmallGroupMcCollisions const& collisions) + // { + // auto getTracksSize = [&mcParticles, this](aod::McCollisions::iterator const& mcCollision) { + // auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + // auto multiplicity = associatedTracks.size(); + // return multiplicity; + // }; + + // using MixedBinning = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; + // MixedBinning const binningOnVtxAndMult{{getTracksSize}, {configAxis.binsMixingVertex, configAxis.binsMixingMultiplicity}, true}; + + // for (auto const& [collision1, collision2] : soa::selfCombinations(binningOnVtxAndMult, configTask.nMixedEvents, -1, mcCollisions, mcCollisions)) { + + // auto tracks1 = mcParticles.sliceBy(perMcColMcParticles, collision1.globalIndex()); + // auto tracks2 = mcParticles.sliceBy(perMcColMcParticles, collision2.globalIndex()); + + // if ((tracks1.size() < configCollision.minMultiplicity || tracks1.size() >= configCollision.maxMultiplicity)) { + // continue; + // } + // if ((tracks2.size() < configCollision.minMultiplicity || tracks2.size() >= configCollision.maxMultiplicity)) { + // continue; + // } + + // auto groupedCollisions = collisions.sliceBy(collisionPerMcCollision, collision1.globalIndex()); + + // mixedEvent->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + // fillCorrelationsMonteCarlo(mixedEvent, CorrelationContainer::CFStep::kCFStepAll, mcParticles, mcParticles, mcParticles.size(), collision1.posZ(), false); + + // if (groupedCollisions.size() == 0) { + // return; + // } + + // mixedEvent->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + // fillCorrelationsMonteCarlo(mixedEvent, CorrelationContainer::CFStep::kCFStepTrackedOnlyPrim, mcParticles, mcParticles, mcParticles.size(), collision1.posZ(), false); + // } + + // } + // PROCESS_SWITCH(HfTaskFlow, processMixedMcGen, "MC Gen : Process mixed-event correlations", false); + }; // End of struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 989b8a7160462cc01b87bd6b13bceb4ae49ce778 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Sat, 30 May 2026 23:29:13 +0200 Subject: [PATCH 362/449] [PWGLF] Random cone to compute delta pT distributions (#16471) --- .../Strangeness/strangenessInJetsIons.cxx | 127 ++++++++++++------ 1 file changed, 87 insertions(+), 40 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index b129823c74d..dcc1d5818ca 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -153,6 +153,7 @@ struct StrangenessInJetsIons { Configurable calculateFeeddownMatrix{"calculateFeeddownMatrix", true, "Fill feeddown matrix for Lambda if MC"}; Configurable useV0inJetRec{"useV0inJetRec", true, "Include V0s in jet reconstruction"}; Configurable doThermalToyModel{"doThermalToyModel", false, "Use the thermal toy model to embed background particles to the jet finder input list"}; + Configurable doPlotRho{"doPlotRho", false, "Plot rho distributions computed with perpendicular cone and area median method."}; Configurable saveChargedParticleMB{"saveChargedParticleMB", false, "Store charged particle information to build inclusive spectra."}; // Event selection @@ -281,6 +282,7 @@ struct StrangenessInJetsIons { const AxisSpec qtarmAxis{1000, 0.0f, 0.30f, "q_{T}^{arm}"}; const AxisSpec numBkgParticles{500, 0.0, 500.0, "Number of particles"}; const AxisSpec deltaPtAxis{2400, -60.0, 60.0, "#delta #it{p}_{T} (GeV/#it{c})"}; + const AxisSpec rhoAxis{100, 0.0, 50.0, "#it{#rho} (GeV/#it{c})"}; // Join enum ParticleOfInterest and the configurable vector particlesOfInterest in a map particleOfInterestDict const std::vector& particleOnOff = particleOfInterest; @@ -331,8 +333,11 @@ struct StrangenessInJetsIons { registryData.add("n_jets_vs_mult", "n_jets_vs_mult", HistType::kTH2F, {multAxis, numJets}); // Delta pT distribution - registryData.add("delta_pT_data", "delta_pT_data", HistType::kTH2F, {multAxis, deltaPtAxis}); - registryData.add("delta_pT_RC_data", "delta_pT_RC_data", HistType::kTH2F, {multAxis, deltaPtAxis}); + registryData.add("h2_centrality_deltaPt_RandomCone", "h2_centrality_deltaPt_RandomCone", HistType::kTH2F, {multAxis, deltaPtAxis}); + registryData.add("h2_centrality_rhoPerp", "h2_centrality_rhoPerp", HistType::kTH2F, {multAxis, rhoAxis}); + + registryData.add("rho_perp", "rho_perp", HistType::kTH2F, {multAxis, rhoAxis}); + registryData.add("rho_median", "rho_median", HistType::kTH2F, {multAxis, rhoAxis}); // Armenteros-Podolanski plot // registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); @@ -396,10 +401,6 @@ struct StrangenessInJetsIons { registryMC.add("n_jets_vs_mult_pT_mc_gen", "n_jets_vs_mult_pT_mc_gen", HistType::kTH2F, {multAxis, ptJetAxis}); registryMC.add("n_jets_vs_mult_mc_gen", "n_jets_vs_mult_mc_gen", HistType::kTH2F, {multAxis, numJets}); - // Delta pT distribution - registryMC.add("delta_pT_gen", "delta_pT_gen", HistType::kTH2F, {multAxis, deltaPtAxis}); - // registryMC.add("delta_pT_RC_gen", "delta_pT_RC_gen", HistType::kTH2F, {multAxis, deltaPtAxis}); - if (doThermalToyModel) { registryMC.add("thermalToy_pT_gen", "thermalToy_pT_gen", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("thermalToy_nBkg_gen", "thermalToy_nBkg_gen", HistType::kTH2F, {multAxis, numBkgParticles}); @@ -501,9 +502,6 @@ struct StrangenessInJetsIons { registryMC.add("n_jets_vs_mult_pT_mc_rec", "n_jets_vs_mult_pT_mc_rec", HistType::kTH2F, {multAxis, ptJetAxis}); registryMC.add("n_jets_vs_mult_mc_rec", "n_jets_vs_mult_mc_rec", HistType::kTH2F, {multAxis, numJets}); - // Delta pT distribution - registryMC.add("delta_pT_rec", "delta_pT_rec", HistType::kTH2F, {multAxis, deltaPtAxis}); - if (doThermalToyModel) { registryMC.add("thermalToy_pT_rec", "thermalToy_pT_rec", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("thermalToy_nBkg_rec", "thermalToy_nBkg_rec", HistType::kTH2F, {multAxis, numBkgParticles}); @@ -757,6 +755,54 @@ struct StrangenessInJetsIons { u2.SetXYZ(u2x, u2y, pz); } + void computeRandomConeDeltaPt(const std::vector& fjParticles, + const std::vector& jets, + float multiplicity, double rhoPerp) + { + // Generate eta and phi for random cone in acceptance region + double randomConeEta = fRng.Uniform(configTracks.etaMin + rJet, configTracks.etaMax - rJet); + double randomConePhi = fRng.Uniform(0.0, TMath::TwoPi()); + + // Exclude leading jet region + if (!jets.empty()) { + float dPhiLeadingJet = getDeltaPhi(jets[0].phi(), randomConePhi); + float dEtaLeadingJet = jets[0].eta() - randomConeEta; + float dRLeadingJet = std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet); + + int attempts = 0; + const int maxAttempts = 100; + // If the random cone overlaps with the leading jet (distance < 1.5), then generate the coordinates again + while (dRLeadingJet < 1.5 && attempts < maxAttempts) { + randomConeEta = fRng.Uniform(configTracks.etaMin + rJet, configTracks.etaMax - rJet); + randomConePhi = fRng.Uniform(0.0, TMath::TwoPi()); + + dPhiLeadingJet = getDeltaPhi(jets[0].phi(), randomConePhi); + dEtaLeadingJet = jets[0].eta() - randomConeEta; + dRLeadingJet = std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet); + attempts++; + } + } + + // Sum pT of all the particles (charged tracks + V0 if included) falling in the random cone + float randomConePt = 0.0; + for (auto const& part : fjParticles) { + float dPhi = getDeltaPhi(part.phi(), randomConePhi); + float dEta = part.eta() - randomConeEta; + float dR = std::sqrt(dEta * dEta + dPhi * dPhi); + + if (dR < rJet) { + randomConePt += part.pt(); + } + } + + // Compute delta pT: pT_cone - (Area_cone * rho) + double coneArea = TMath::Pi() * rJet * rJet; + double deltaPtRandomCone = randomConePt - (coneArea * rhoPerp); + + registryData.fill(HIST("h2_centrality_deltaPt_RandomCone"), multiplicity, deltaPtRandomCone); + registryData.fill(HIST("h2_centrality_rhoPerp"), multiplicity, rhoPerp); + } + // Find ITS hit template bool hasITSHitOnLayer(const TrackIts& track, int layer) @@ -1940,19 +1986,20 @@ struct StrangenessInJetsIons { pj.set_user_index(p.pdgCode()); v0PseudoJets.push_back(pj); // LOG(info) << "[AddV0sForJetReconstructionMCP] Add V0 as input for jet finder."; + } + } - // Remove V0 daughter particles if already in the input list for the jet finder - for (long unsigned int i = 0; i < fjParticleObj.size(); ++i) { - const auto& mcPart = fjParticleObj[i]; - if (!mcPart.has_mothers()) - continue; - auto mother = mcParticles.iteratorAt(mcPart.mothersIds()[0]); - int motherPdg = std::abs(mother.pdgCode()); - if (motherPdg == kK0Short || motherPdg == kLambda0) { - isTrackReplaced[i] = true; - // LOG(info) << "[AddV0sForJetReconstructionMCP] V0 daughter particle found in fjParticleObj."; - } - } + // Remove V0 daughter particles if already in the input list for the jet finder + for (long unsigned int i = 0; i < fjParticleObj.size(); ++i) { + const auto& mcPart = fjParticleObj[i]; + if (!mcPart.has_mothers()) + continue; + auto mother = mcParticles.iteratorAt(mcPart.mothersIds()[0]); + int motherPdg = std::abs(mother.pdgCode()); + // LOG(info) << "[AddV0sForJetReconstructionMCP] Mother pdg code:" << motherPdg; + if (motherPdg == kK0Short || motherPdg == kLambda0) { + isTrackReplaced[i] = true; + // LOG(info) << "[AddV0sForJetReconstructionMCP] V0 daughter particle found in fjParticleObj."; } } @@ -2036,6 +2083,9 @@ struct StrangenessInJetsIons { double phi = fRng.Uniform(0.0, TMath::TwoPi()); double eta = fRng.Uniform(configTracks.etaMin, configTracks.etaMax); + if (pt < 0.1f) + continue; + double px = pt * std::cos(phi); double py = pt * std::sin(phi); double pz = pt * std::sinh(eta); @@ -2150,13 +2200,6 @@ struct StrangenessInJetsIons { std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); - // Jet selection - bool isAtLeastOneJetSelected = false; - std::vector selectedJet; - std::vector ue1; - std::vector ue2; - std::vector jetPt; - // Event multiplicity float multiplicity; if (centrEstimator == 0) { @@ -2165,6 +2208,22 @@ struct StrangenessInJetsIons { multiplicity = collision.centFT0M(); } + if (doPlotRho) { + auto [rhoMedian, rhoMMedian] = backgroundSub.estimateRhoAreaMedian(fjParticles, true); + registryData.fill(HIST("rho_perp"), multiplicity, rhoPerp); + registryData.fill(HIST("rho_median"), multiplicity, rhoMedian); + } + + // Delta pT distributions with random cone technique + computeRandomConeDeltaPt(fjParticles, jets, multiplicity, rhoPerp); + + // Jet selection + bool isAtLeastOneJetSelected = false; + std::vector selectedJet; + std::vector ue1; + std::vector ue2; + std::vector jetPt; + // Loop over reconstructed jets for (const auto& jet : jets) { @@ -2179,10 +2238,6 @@ struct StrangenessInJetsIons { continue; isAtLeastOneJetSelected = true; - // delta pT distribution after jet selection by pT - double deltaPt = jet.pt() - jetMinusBkg.pt(); - registryData.fill(HIST("delta_pT_data"), multiplicity, deltaPt); - // Calculation of perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); @@ -2536,10 +2591,6 @@ struct StrangenessInJetsIons { // Fill jet counter registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); - // delta pT distribution after jet selection by pT - double deltaPt = jet.pt() - jetMinusBkg.pt(); - registryMC.fill(HIST("delta_pT_gen"), genMultiplicity, deltaPt); - // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); double coneRadius = std::sqrt(jet.area() / PI); // TODO: replace with rJet (similar results) @@ -2848,10 +2899,6 @@ struct StrangenessInJetsIons { continue; isAtLeastOneJetSelected = true; - // delta pT distribution after jet selection by pT - double deltaPt = jet.pt() - jetMinusBkg.pt(); - registryMC.fill(HIST("delta_pT_rec"), multiplicity, deltaPt); - // Perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); From 8df5bd33c4d212abaae8add81983cf085d2117c8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Sun, 31 May 2026 10:24:45 +0200 Subject: [PATCH 363/449] [PWGLF] Add random cone histograms (phi randomized) (#16472) --- .../Strangeness/strangenessInJetsIons.cxx | 174 +++++++++++++++++- 1 file changed, 171 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index dcc1d5818ca..f8184f1e1d2 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -154,6 +154,7 @@ struct StrangenessInJetsIons { Configurable useV0inJetRec{"useV0inJetRec", true, "Include V0s in jet reconstruction"}; Configurable doThermalToyModel{"doThermalToyModel", false, "Use the thermal toy model to embed background particles to the jet finder input list"}; Configurable doPlotRho{"doPlotRho", false, "Plot rho distributions computed with perpendicular cone and area median method."}; + Configurable doRandomConeSys{"doRandomConeSys", false, "Study particle contribution outside jets using random cones with same pseudorapidity and phi generated in [pi/3, 2*pi/3]."}; Configurable saveChargedParticleMB{"saveChargedParticleMB", false, "Store charged particle information to build inclusive spectra."}; // Event selection @@ -336,9 +337,10 @@ struct StrangenessInJetsIons { registryData.add("h2_centrality_deltaPt_RandomCone", "h2_centrality_deltaPt_RandomCone", HistType::kTH2F, {multAxis, deltaPtAxis}); registryData.add("h2_centrality_rhoPerp", "h2_centrality_rhoPerp", HistType::kTH2F, {multAxis, rhoAxis}); - registryData.add("rho_perp", "rho_perp", HistType::kTH2F, {multAxis, rhoAxis}); - registryData.add("rho_median", "rho_median", HistType::kTH2F, {multAxis, rhoAxis}); - + if (doPlotRho) { + registryData.add("rho_perp", "rho_perp", HistType::kTH2F, {multAxis, rhoAxis}); + registryData.add("rho_median", "rho_median", HistType::kTH2F, {multAxis, rhoAxis}); + } // Armenteros-Podolanski plot // registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); @@ -350,6 +352,11 @@ struct StrangenessInJetsIons { registryData.add("AntiLambda_in_ue", "AntiLambda_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); registryData.add("K0s_in_jet", "K0s_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); registryData.add("K0s_in_ue", "K0s_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + if (doRandomConeSys) { + registryData.add("Lambda_in_rc", "Lambda_in_rc", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("AntiLambda_in_rc", "AntiLambda_in_rc", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("K0s_in_rc", "K0s_in_rc", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + } } if (particleOfInterestDict[ParticleOfInterest::kCascades]) { registryData.add("XiPos_in_jet", "XiPos_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); @@ -414,6 +421,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + if (doRandomConeSys) { + registryMC.add("Lambda_generated_rc", "Lambda_generated_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_rc", "AntiLambda_generated_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_rc", "K0s_generated_rc", HistType::kTH2F, {multAxis, ptAxis}); + } // --- Histograms for the full event (without jets) registryMC.add("K0s_generated_MB", "K0s_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); @@ -521,6 +533,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + if (doRandomConeSys) { + registryMC.add("Lambda_reconstructed_rc", "Lambda_reconstructed_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_rc", "AntiLambda_reconstructed_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_rc", "K0s_reconstructed_rc", HistType::kTH2F, {multAxis, ptAxis}); + } // Histograms for secondary hadrons registryMC.add("K0s_reconstructed_jet_incl", "K0s_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); @@ -529,6 +546,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue_incl", "Lambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet_incl", "AntiLambda_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue_incl", "AntiLambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + if (doRandomConeSys) { + registryMC.add("Lambda_reconstructed_rc_incl", "Lambda_reconstructed_rc_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_rc_incl", "AntiLambda_reconstructed_rc_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_rc_incl", "K0s_reconstructed_rc_incl", HistType::kTH2F, {multAxis, ptAxis}); + } // Histograms for generated particles in reconstructed events registryMC.add("K0s_gen_recoEvent_jet", "K0s_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -537,6 +559,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_gen_recoEvent_ue", "Lambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_gen_recoEvent_jet", "AntiLambda_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_gen_recoEvent_ue", "AntiLambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + if (doRandomConeSys) { + registryMC.add("Lambda_gen_recoEvent_rc", "Lambda_gen_recoEvent_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_gen_recoEvent_rc", "AntiLambda_gen_recoEvent_rc", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_gen_recoEvent_rc", "K0s_gen_recoEvent_rc", HistType::kTH2F, {multAxis, ptAxis}); + } // --- Histograms for the full event (without jets) registryMC.add("K0s_reconstructed_MB", "K0s_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); @@ -755,6 +782,23 @@ struct StrangenessInJetsIons { u2.SetXYZ(u2x, u2y, pz); } + // Compute two random directions in phi to vector p + void getRandomConeDirections(const fastjet::PseudoJet& jet, TVector3& u1, TVector3& u2, double minDeltaPhi, double maxDeltaPhi) + { + // Generate random deltaPhi in specified range + double randomDeltaPhi = fRng.Uniform(minDeltaPhi, maxDeltaPhi); + + u1.SetPtEtaPhi(jet.pt(), jet.eta(), jet.phi() + randomDeltaPhi); + u2.SetPtEtaPhi(jet.pt(), jet.eta(), jet.phi() - randomDeltaPhi); + } + + float getDeltaR(double eta1, double phi1, double etaAxis, double phiAxis) + { + float deltaEta = eta1 - etaAxis; + float deltaPhi = getDeltaPhi(phi1, phiAxis); + return std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + } + void computeRandomConeDeltaPt(const std::vector& fjParticles, const std::vector& jets, float multiplicity, double rhoPerp) @@ -2222,6 +2266,8 @@ struct StrangenessInJetsIons { std::vector selectedJet; std::vector ue1; std::vector ue2; + std::vector rcSys1; // randomn cone 1 + std::vector rcSys2; // randomn cone 2 std::vector jetPt; // Loop over reconstructed jets @@ -2246,6 +2292,13 @@ struct StrangenessInJetsIons { continue; } + TVector3 rcSysAxis1(0, 0, 0), rcSysAxis2(0, 0, 0); + if (doRandomConeSys) { + getRandomConeDirections(jet, rcSysAxis1, rcSysAxis2, TMath::Pi() / 3.0, 2.0 * TMath::Pi() / 3.0); + rcSys1.emplace_back(rcSysAxis1); + rcSys2.emplace_back(rcSysAxis2); + } + // Store jet and UE axes selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); @@ -2287,6 +2340,13 @@ struct StrangenessInJetsIons { const float deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); const float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + bool isInRC = false; + if (doRandomConeSys) { + const float deltaRrc1 = getDeltaR(v0dir.Eta(), v0dir.Phi(), rcSys1[i].Eta(), rcSys1[i].Phi()); + const float deltaRrc2 = getDeltaR(v0dir.Eta(), v0dir.Phi(), rcSys2[i].Eta(), rcSys2[i].Phi()); + isInRC = (deltaRrc1 < rJet) || (deltaRrc2 < rJet); + } + // Fill Armenteros-Podolanski TH2 // registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); @@ -2298,6 +2358,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryData.fill(HIST("K0s_in_ue"), multiplicity, v0.pt(), v0.mK0Short()); } + if (doRandomConeSys && isInRC) { + registryData.fill(HIST("K0s_in_rc"), multiplicity, v0.pt(), v0.mK0Short()); + } } // Lambda if (passedLambdaSelection(v0, pos, neg, vtxPos)) { @@ -2307,6 +2370,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryData.fill(HIST("Lambda_in_ue"), multiplicity, v0.pt(), v0.mLambda()); } + if (doRandomConeSys && isInRC) { + registryData.fill(HIST("Lambda_in_rc"), multiplicity, v0.pt(), v0.mLambda()); + } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg, vtxPos)) { @@ -2316,6 +2382,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryData.fill(HIST("AntiLambda_in_ue"), multiplicity, v0.pt(), v0.mAntiLambda()); } + if (doRandomConeSys && isInRC) { + registryData.fill(HIST("AntiLambda_in_rc"), multiplicity, v0.pt(), v0.mAntiLambda()); + } } } } @@ -2600,6 +2669,11 @@ struct StrangenessInJetsIons { continue; } + TVector3 rcSysAxis1(0, 0, 0), rcSysAxis2(0, 0, 0); + if (doRandomConeSys) { + getRandomConeDirections(jet, rcSysAxis1, rcSysAxis2, TMath::Pi() / 3.0, 2.0 * TMath::Pi() / 3.0); + } + // Loop over strange hadrons int index = -1; for (const auto& hadron : strHadronMomentum) { @@ -2617,6 +2691,13 @@ struct StrangenessInJetsIons { double deltaPhiUe2 = getDeltaPhi(hadron.Phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + bool isInRC = false; + if (doRandomConeSys) { + const float deltaRrc1 = getDeltaR(hadron.Eta(), hadron.Phi(), rcSysAxis1.Eta(), rcSysAxis1.Phi()); + const float deltaRrc2 = getDeltaR(hadron.Eta(), hadron.Phi(), rcSysAxis2.Eta(), rcSysAxis2.Phi()); + isInRC = (deltaRrc1 < rJet) || (deltaRrc2 < rJet); + } + // Select particles inside jet if (deltaRJet < coneRadius) { switch (pdg[index]) { @@ -2762,6 +2843,29 @@ struct StrangenessInJetsIons { break; } } + + // Select particles inside random cones (RC) + if (doRandomConeSys && isInRC) { + switch (pdg[index]) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_rc"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_rc"), genMultiplicity, hadron.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_rc"), genMultiplicity, hadron.Pt()); + } + break; + default: + break; + } + } } } // Fill jet counter @@ -2782,6 +2886,8 @@ struct StrangenessInJetsIons { std::vector selectedJet; std::vector ue1; std::vector ue2; + std::vector rcSys1; // randomn cone 1 + std::vector rcSys2; // randomn cone 2 // Jet and area definitions fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); @@ -2804,6 +2910,8 @@ struct StrangenessInJetsIons { selectedJet.clear(); ue1.clear(); ue2.clear(); + rcSys1.clear(); + rcSys2.clear(); // Fill event counter before any selection registryMC.fill(HIST("number_of_events_mc_rec"), 0.5); @@ -2907,6 +3015,13 @@ struct StrangenessInJetsIons { continue; } + TVector3 rcSysAxis1(0, 0, 0), rcSysAxis2(0, 0, 0); + if (doRandomConeSys) { + getRandomConeDirections(jet, rcSysAxis1, rcSysAxis2, TMath::Pi() / 3.0, 2.0 * TMath::Pi() / 3.0); + rcSys1.emplace_back(rcSysAxis1); + rcSys2.emplace_back(rcSysAxis2); + } + // Store selected jet and UE cone axes selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); @@ -2950,6 +3065,13 @@ struct StrangenessInJetsIons { const double deltaPhiUe2 = getDeltaPhi(momVec.Phi(), ue2[i].Phi()); const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + bool isInRC = false; + if (doRandomConeSys) { + const float deltaRrc1 = getDeltaR(momVec.Eta(), momVec.Phi(), rcSys1[i].Eta(), rcSys1[i].Phi()); + const float deltaRrc2 = getDeltaR(momVec.Eta(), momVec.Phi(), rcSys2[i].Eta(), rcSys2[i].Phi()); + isInRC = (deltaRrc1 < rJet) || (deltaRrc2 < rJet); + } + // Select particles inside jet if (deltaRJet < rJet) { switch (particle.pdgCode()) { @@ -2993,6 +3115,27 @@ struct StrangenessInJetsIons { break; } } + if (doRandomConeSys && isInRC) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_gen_recoEvent_rc"), multiplicity, momVec.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_gen_recoEvent_rc"), multiplicity, momVec.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_gen_recoEvent_rc"), multiplicity, momVec.Pt()); + } + break; + default: + break; + } + } } // ---------------------------------------- @@ -3047,6 +3190,13 @@ struct StrangenessInJetsIons { double deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + bool isInRC = false; + if (doRandomConeSys) { + const float deltaRrc1 = getDeltaR(v0dir.Eta(), v0dir.Phi(), rcSys1[i].Eta(), rcSys1[i].Phi()); + const float deltaRrc2 = getDeltaR(v0dir.Eta(), v0dir.Phi(), rcSys2[i].Eta(), rcSys2[i].Phi()); + isInRC = (deltaRrc1 < rJet) || (deltaRrc2 < rJet); + } + // Fill Armenteros-Podolanski TH2 // registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); @@ -3058,6 +3208,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("K0s_reconstructed_ue"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("K0s_reconstructed_rc"), multiplicity, v0.pt()); + } } // Lambda if (passedLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0 && isPhysPrim) { @@ -3067,6 +3220,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("Lambda_reconstructed_ue"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("Lambda_reconstructed_rc"), multiplicity, v0.pt()); + } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0Bar && isPhysPrim) { @@ -3076,6 +3232,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("AntiLambda_reconstructed_ue"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("AntiLambda_reconstructed_rc"), multiplicity, v0.pt()); + } } // Fill inclusive spectra @@ -3087,6 +3246,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("K0s_reconstructed_ue_incl"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("K0s_reconstructed_rc_incl"), multiplicity, v0.pt()); + } } // Lambda if (passedLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0) { @@ -3096,6 +3258,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("Lambda_reconstructed_ue_incl"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("Lambda_reconstructed_rc_incl"), multiplicity, v0.pt()); + } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg, vtxPos) && pdgParent == kLambda0Bar) { @@ -3105,6 +3270,9 @@ struct StrangenessInJetsIons { if (deltaRue1 < rJet || deltaRue2 < rJet) { registryMC.fill(HIST("AntiLambda_reconstructed_ue_incl"), multiplicity, v0.pt()); } + if (doRandomConeSys && isInRC) { + registryMC.fill(HIST("AntiLambda_reconstructed_rc_incl"), multiplicity, v0.pt()); + } } } } From 74867bc25886a3a7f7c1ded02d70da062c8cd752 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Sun, 31 May 2026 19:41:44 +0200 Subject: [PATCH 364/449] [PWGLF] Prepare histograms for unfolding + delta pT distributions in MC (#16478) --- .../Strangeness/strangenessInJetsIons.cxx | 230 +++++++++++++++++- 1 file changed, 227 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index f8184f1e1d2..6f6a013eb70 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -269,6 +269,8 @@ struct StrangenessInJetsIons { const AxisSpec ptAxis{500, 0.0, 50.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec ptJetAxis{100, 0.0, 100.0, "#it{p}_{T,jet} (GeV/#it{c})"}; + const AxisSpec ptJetRecoAxisUnfold{200, 0.0, 200.0, "#it{p}_{T,jet}^{rec} (GeV/#it{c})"}; + const AxisSpec ptJetGenAxisUnfold{200, 0.0, 200.0, "#it{p}_{T,jet}^{gen} (GeV/#it{c})"}; const AxisSpec ptChargedAxis{10000, 0.0, 100.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec numJets{21, -0.5, 20.5, "Number of jets per collision"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; @@ -413,6 +415,9 @@ struct StrangenessInJetsIons { registryMC.add("thermalToy_nBkg_gen", "thermalToy_nBkg_gen", HistType::kTH2F, {multAxis, numBkgParticles}); } + registryMC.add("h2_centrality_deltaPt_RandomCone_gen", "h2_centrality_deltaPt_RandomCone_gen", HistType::kTH2F, {multAxis, deltaPtAxis}); + registryMC.add("h2_centrality_rhoPerp_gen", "h2_centrality_rhoPerp_gen", HistType::kTH2F, {multAxis, rhoAxis}); + // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -522,6 +527,10 @@ struct StrangenessInJetsIons { registryMC.add("charged_embedJets_rec_jet", "charged_embedJets_rec_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("charged_embedJets_rec_ue", "charged_embedJets_rec_ue", HistType::kTH2F, {multAxis, ptAxis}); } + + registryMC.add("h2_centrality_deltaPt_RandomCone_rec", "h2_centrality_deltaPt_RandomCone_rec", HistType::kTH2F, {multAxis, deltaPtAxis}); + registryMC.add("h2_centrality_rhoPerp_rec", "h2_centrality_rhoPerp_rec", HistType::kTH2F, {multAxis, rhoAxis}); + // Armenteros-Podolanski plot // registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); @@ -669,6 +678,22 @@ struct StrangenessInJetsIons { registryDataMB.add("ChargedTrack_in_MB", "ChargedTrack_in_MB", HistType::kTH2F, {multAxis, ptChargedAxis}); } } + + if (doprocessPrepareUnfolding) { + // Response matrix detector (only mathced) + // Assi: X = Centrality, Y = pT_gen, Z = pT_reco + registryMC.add("hDetectorResponse", "hDetectorResponse", HistType::kTH3F, {multAxis, ptJetGenAxisUnfold, ptJetRecoAxisUnfold}); + + // Efficiency components (GEN level) + // Assi: X = Centrality, Y = pT_gen + registryMC.add("hJetPtGenTotal", "hJetPtGenTotal", HistType::kTH2F, {multAxis, ptJetGenAxisUnfold}); + registryMC.add("hJetPtGenMatched", "hJetPtGenMatched", HistType::kTH2F, {multAxis, ptJetGenAxisUnfold}); + + // Purity components (RECO level) + // Assi: X = Centrality, Y = pT_reco + registryMC.add("hJetPtRecoTotal", "hJetPtRecoTotal", HistType::kTH2F, {multAxis, ptJetRecoAxisUnfold}); + registryMC.add("hJetPtRecoMatched", "hJetPtRecoMatched", HistType::kTH2F, {multAxis, ptJetRecoAxisUnfold}); + } } // Delta phi calculation @@ -799,9 +824,11 @@ struct StrangenessInJetsIons { return std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); } + // selProcess = 0 (data), = 1 (MC GEN), = 2 (MC REC) void computeRandomConeDeltaPt(const std::vector& fjParticles, const std::vector& jets, - float multiplicity, double rhoPerp) + float multiplicity, double rhoPerp, + int selProcess = 0) { // Generate eta and phi for random cone in acceptance region double randomConeEta = fRng.Uniform(configTracks.etaMin + rJet, configTracks.etaMax - rJet); @@ -843,8 +870,17 @@ struct StrangenessInJetsIons { double coneArea = TMath::Pi() * rJet * rJet; double deltaPtRandomCone = randomConePt - (coneArea * rhoPerp); - registryData.fill(HIST("h2_centrality_deltaPt_RandomCone"), multiplicity, deltaPtRandomCone); - registryData.fill(HIST("h2_centrality_rhoPerp"), multiplicity, rhoPerp); + if (selProcess == 0) { + registryData.fill(HIST("h2_centrality_deltaPt_RandomCone"), multiplicity, deltaPtRandomCone); + registryData.fill(HIST("h2_centrality_rhoPerp"), multiplicity, rhoPerp); + } else if (selProcess == 1) { + // Ricordati di definire questi istogrammi nel tuo book/registry MC! + registryMC.fill(HIST("h2_centrality_deltaPt_RandomCone_gen"), multiplicity, deltaPtRandomCone); + registryMC.fill(HIST("h2_centrality_rhoPerp_gen"), multiplicity, rhoPerp); + } else if (selProcess == 2) { + registryMC.fill(HIST("h2_centrality_deltaPt_RandomCone_rec"), multiplicity, deltaPtRandomCone); + registryMC.fill(HIST("h2_centrality_rhoPerp_rec"), multiplicity, rhoPerp); + } } // Find ITS hit @@ -2149,6 +2185,48 @@ struct StrangenessInJetsIons { } } + void ProcessJetMatchingFactorized(const std::vector& jetsGen, + const std::vector& jetsReco, + float centrality) + { + const double maxDeltaR = 0.24; + std::vector isRecoJetMatched(jetsReco.size(), false); + + for (const auto& jetGen : jetsGen) { + registryMC.fill(HIST("hJetPtGenTotal"), centrality, jetGen.pt()); + } + + for (const auto& jetReco : jetsReco) { + registryMC.fill(HIST("hJetPtRecoTotal"), centrality, jetReco.pt()); + } + + // --- Geometrical matching reco <----> gen + for (const auto& jetGen : jetsGen) { + int bestRecoIdx = -1; + double minDeltaR = maxDeltaR; + + // Search closest jet RECO in (eta,phi) space + for (long unsigned int iReco = 0; iReco < jetsReco.size(); ++iReco) { + if (isRecoJetMatched[iReco]) + continue; + + double dR = jetGen.delta_R(jetsReco[iReco]); + if (dR < minDeltaR) { + minDeltaR = dR; + bestRecoIdx = iReco; + } + } + + if (bestRecoIdx != -1) { + isRecoJetMatched[bestRecoIdx] = true; // RECO matched + + registryMC.fill(HIST("hDetectorResponse"), centrality, jetGen.pt(), jetsReco[bestRecoIdx].pt()); + registryMC.fill(HIST("hJetPtGenMatched"), centrality, jetGen.pt()); + registryMC.fill(HIST("hJetPtRecoMatched"), centrality, jetsReco[bestRecoIdx].pt()); + } + } + } + // Process data void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, DaughterTracks const& tracks, @@ -2636,6 +2714,9 @@ struct StrangenessInJetsIons { // Estimate background energy density (rho) in perpendicular cone auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); + // Delta pT distributions with random cone technique + computeRandomConeDeltaPt(fjParticles, jets, genMultiplicity, rhoPerp, 1); + // Loop over clustered jets int countSelJet = 0; // number of selected jets for (const auto& jet : jets) { @@ -2989,6 +3070,9 @@ struct StrangenessInJetsIons { std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); + // Delta pT distributions with random cone technique + computeRandomConeDeltaPt(fjParticles, jets, multiplicity, rhoPerp, 2); + // Jet selection bool isAtLeastOneJetSelected = false; std::vector jetPt; @@ -3868,6 +3952,146 @@ struct StrangenessInJetsIons { } } PROCESS_SWITCH(StrangenessInJetsIons, processDataMB, "Process data in minimum bias events", false); + + void processPrepareUnfolding(SimCollisions const& recoCollisions, + soa::Join const&, + DaughterTracksMC const& mcTracks, soa::Join const& fullV0s, + aod::McParticles const& mcParticles) + { + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over reco collisions + for (const auto& recoColl : recoCollisions) { + if (!recoColl.has_mcCollision()) { + continue; + } + + // Event selections + if (!recoColl.sel8()) + continue; + if (std::fabs(recoColl.posZ()) > zVtx) + continue; + if (requireNoSameBunchPileup && !recoColl.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + if (requireGoodZvtxFT0vsPV && !recoColl.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + // Centrality + const auto& mcCollision = recoColl.mcCollision_as>(); + float centrality; + if (centrEstimator == 0) { + centrality = mcCollision.centFT0C(); + } else { + centrality = mcCollision.centFT0M(); + } + + std::vector jetsGenThisEvent; + std::vector jetsRecoThisEvent; + + // ---- Extract reconstructed jets ---- + // Number of V0 and cascades per collision + auto v0sPerColl = fullV0s.sliceBy(perCollisionV0, recoColl.globalIndex()); + auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, recoColl.globalIndex()); + const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mcCollision.globalIndex()); + + // Vertex position vector + TVector3 vtxPos(recoColl.posX(), recoColl.posY(), recoColl.posZ()); + std::vector fjParticlesReco; + std::vector> fjTracks; + for (auto const& track : tracksPerColl) { + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fjParticlesReco.emplace_back(fourMomentum); + fjTracks.push_back(track); + } + + // Include V0s as tracks for jet reconstruction + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionMCD(fjParticlesReco, fjTracks, v0sPerColl, mcParticles, vtxPos); + } + fjTracks.clear(); + + if (fjParticlesReco.size() >= 1) { // Reject empty events + fastjet::ClusterSequenceArea csReco(fjParticlesReco, jetDef, areaDef); + std::vector recoJets = fastjet::sorted_by_pt(csReco.inclusive_jets()); + if (recoJets.empty()) + continue; + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticlesReco, recoJets[0], rJet); + + for (const auto& jet : recoJets) { + // jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) + continue; + + // jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < minJetPt) + continue; + + jetsRecoThisEvent.push_back(jetMinusBkg); + } + } + // ---------------------------------------- + + // ---- Extract generated jets ---- + // LOG(info) << "recoCollisions.globalIndex()" << recoColl.globalIndex(); + // LOG(info) << "recoColl.mcCollisionId()" << recoColl.mcCollisionId(); + // LOG(info) << "mcCollision.globalIndex()" << mcCollision.globalIndex(); + std::vector fjParticlesGen; + std::vector> fjParticleObj; + + for (const auto& particle : mcParticlesPerColl) { + double minPtParticle = 0.1f; + if (particle.eta() < configTracks.etaMin || particle.eta() > configTracks.etaMax || particle.pt() < minPtParticle) + continue; + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + + // Build 4-momentum assuming charged pion mass + static constexpr float kMassPionChargedSquared = o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged; + const double energy = std::sqrt(particle.p() * particle.p() + kMassPionChargedSquared); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fourMomentum.set_user_index(particle.pdgCode()); + fjParticlesGen.emplace_back(fourMomentum); + fjParticleObj.push_back(particle); + } + + if (useV0inJetRec && particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + AddV0sForJetReconstructionMCP(fjParticlesGen, fjParticleObj, mcParticlesPerColl, mcParticles); + } + + if (fjParticlesGen.size() >= 1) { // Skip events with no particles + fastjet::ClusterSequenceArea csGen(fjParticlesGen, jetDef, areaDef); + std::vector genJets = fastjet::sorted_by_pt(csGen.inclusive_jets()); + if (genJets.empty()) + continue; + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticlesGen, genJets[0], rJet); + + for (const auto& jet : genJets) { + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) + continue; + + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < minJetPt) + continue; + + jetsGenThisEvent.push_back(jetMinusBkg); + } + } + // ---------------------------------------- + + // Fill histograms for unfolding + ProcessJetMatchingFactorized(jetsGenThisEvent, jetsRecoThisEvent, centrality); + } + } + PROCESS_SWITCH(StrangenessInJetsIons, processPrepareUnfolding, "Process to prepare hsitograms for the unfolding procedure", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 6e0340f8b712d35554d07db7fe6016fe80143fd9 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Mon, 1 Jun 2026 09:30:16 +0200 Subject: [PATCH 365/449] [PWGLF] Add explicit ROOT leaflists for tree branches (#16477) --- .../Nuspex/coalescenceTreeProducer.cxx | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx index e58a906a391..4b478ad4d89 100644 --- a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx +++ b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx @@ -79,7 +79,7 @@ struct CoalescenceTreeProducer { Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; - OutputObj treeBoundState{"treeBoundState"}; + OutputObj treeBoundState{"treeBoundState", OutputObjHandlingPolicy::AnalysisObject}; int64_t eventID = 0; // Event ID int64_t idB1 = 0, idB2 = 0, idB3 = 0; // MC particle IDs @@ -162,45 +162,47 @@ struct CoalescenceTreeProducer { // Tree for pairs/triplets. // For deuterons only the first two baryons are stored. // For three-body states, the third-baryon branches are also created. - treeBoundState->Branch("eventID", &eventID); - - treeBoundState->Branch("idB1", &idB1); - treeBoundState->Branch("idB2", &idB2); - - treeBoundState->Branch("pdgB1", &pdgB1); - treeBoundState->Branch("pdgB2", &pdgB2); - - treeBoundState->Branch("chargeB1", &chargeB1); - treeBoundState->Branch("chargeB2", &chargeB2); - - treeBoundState->Branch("xB1", &xB1); - treeBoundState->Branch("yB1", &yB1); - treeBoundState->Branch("zB1", &zB1); - treeBoundState->Branch("tB1", &tB1); - treeBoundState->Branch("pxB1", &pxB1); - treeBoundState->Branch("pyB1", &pyB1); - treeBoundState->Branch("pzB1", &pzB1); - - treeBoundState->Branch("xB2", &xB2); - treeBoundState->Branch("yB2", &yB2); - treeBoundState->Branch("zB2", &zB2); - treeBoundState->Branch("tB2", &tB2); - treeBoundState->Branch("pxB2", &pxB2); - treeBoundState->Branch("pyB2", &pyB2); - treeBoundState->Branch("pzB2", &pzB2); + treeBoundState.setObject(new TTree("BoundStateTree", "Tree for coalescence studies")); + treeBoundState->Branch("eventID", &eventID, "eventID/L"); + + treeBoundState->Branch("idB1", &idB1, "idB1/L"); + treeBoundState->Branch("idB2", &idB2, "idB2/L"); + + treeBoundState->Branch("pdgB1", &pdgB1, "pdgB1/I"); + treeBoundState->Branch("pdgB2", &pdgB2, "pdgB2/I"); + + treeBoundState->Branch("chargeB1", &chargeB1, "chargeB1/I"); + treeBoundState->Branch("chargeB2", &chargeB2, "chargeB2/I"); + + treeBoundState->Branch("xB1", &xB1, "xB1/F"); + treeBoundState->Branch("yB1", &yB1, "yB1/F"); + treeBoundState->Branch("zB1", &zB1, "zB1/F"); + treeBoundState->Branch("tB1", &tB1, "tB1/F"); + treeBoundState->Branch("pxB1", &pxB1, "pxB1/F"); + treeBoundState->Branch("pyB1", &pyB1, "pyB1/F"); + treeBoundState->Branch("pzB1", &pzB1, "pzB1/F"); + + treeBoundState->Branch("xB2", &xB2, "xB2/F"); + treeBoundState->Branch("yB2", &yB2, "yB2/F"); + treeBoundState->Branch("zB2", &zB2, "zB2/F"); + treeBoundState->Branch("tB2", &tB2, "tB2/F"); + treeBoundState->Branch("pxB2", &pxB2, "pxB2/F"); + treeBoundState->Branch("pyB2", &pyB2, "pyB2/F"); + treeBoundState->Branch("pzB2", &pzB2, "pzB2/F"); if (static_cast(boundStateSpecies) != kDeuteron) { - treeBoundState->Branch("idB3", &idB3); - treeBoundState->Branch("pdgB3", &pdgB3); - treeBoundState->Branch("chargeB3", &chargeB3); - - treeBoundState->Branch("xB3", &xB3); - treeBoundState->Branch("yB3", &yB3); - treeBoundState->Branch("zB3", &zB3); - treeBoundState->Branch("tB3", &tB3); - treeBoundState->Branch("pxB3", &pxB3); - treeBoundState->Branch("pyB3", &pyB3); - treeBoundState->Branch("pzB3", &pzB3); + treeBoundState->Branch("idB3", &idB3, "idB3/L"); + + treeBoundState->Branch("pdgB3", &pdgB3, "pdgB3/I"); + treeBoundState->Branch("chargeB3", &chargeB3, "chargeB3/I"); + + treeBoundState->Branch("xB3", &xB3, "xB3/F"); + treeBoundState->Branch("yB3", &yB3, "yB3/F"); + treeBoundState->Branch("zB3", &zB3, "zB3/F"); + treeBoundState->Branch("tB3", &tB3, "tB3/F"); + treeBoundState->Branch("pxB3", &pxB3, "pxB3/F"); + treeBoundState->Branch("pyB3", &pyB3, "pyB3/F"); + treeBoundState->Branch("pzB3", &pzB3, "pzB3/F"); } } From fa734a6eeb24458cff1e1c83220f3ce527bc2f49 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Mon, 1 Jun 2026 09:35:56 +0200 Subject: [PATCH 366/449] [PWGLF] added feature so exclude Li4 for the kstar resolution (#16454) --- PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index fa2bb7a33a1..b836a7293c8 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -143,7 +143,7 @@ enum ParticleFlags { kFromLi4 = BIT(1), // from Li4 decay kFromHypertriton = BIT(2), // from hypertriton decay kFromMaterial = BIT(3), // from material - kFromOtherDecays = BIT(4), // from other decays + kFromOtherDecays = BIT(4), // from other (weak) decays }; constexpr double kItsParamsDefault[static_cast(Species::kAllSpecies)][6] = { @@ -291,7 +291,9 @@ struct he3HadronFemto { Configurable settingFillMultiplicity{"settingFillMultiplicity", false, "Fill multiplicity table"}; Configurable settingFillQa{"settingFillQa", false, "Fill QA table"}; - Configurable settingFillPrimariesAndMixedMc{"settingFillPrimariesAndMixedMc", false, "Fill primary MC tracks and mixed tracks (e.g. a primary track and one from Li4)"}; + Configurable settingFillPrimariesMc{"settingFillPrimariesMc", false, "Fill primary MC tracks"}; + Configurable settingFillLi4DaughtersMc{"settingFillLi4DaughtersMc", true, "Fill tracks from Li4 decays in MC"}; + Configurable settingFillMixedMc{"settingFillMixedMc", false, "Fill mixed MC tracks (e.g. a primary track and one from Li4)"}; // Zorro Configurable settingSkimmedProcessing{"settingSkimmedProcessing", false, "Skimmed dataset processing"}; @@ -1059,7 +1061,7 @@ struct he3HadronFemto { } else if (std::abs(mother.pdgCode()) == H3LPDG) { flag |= ParticleFlags::kFromHypertriton; } else { - flag |= ParticleFlags::kFromOtherDecays; + return; // other decays is thought for weak decays } } @@ -1260,7 +1262,16 @@ struct he3HadronFemto { he3Hadcand.flags |= Flags::kMixedPair; } - if (!settingFillPrimariesAndMixedMc && ((he3Hadcand.flags == Flags::kMixedPair) || he3Hadcand.flags == Flags::kBothPrimaries)) { + LOG(info) << "He3 flags: " << int(he3Hadcand.flagsHe3) << ", Hadron flags: " << int(he3Hadcand.flagsHad) << ", Pair flags: " << int(he3Hadcand.flags); + if (!settingFillPrimariesMc && (he3Hadcand.flags == Flags::kBothPrimaries)) { + continue; + } + + if (!settingFillLi4DaughtersMc && (he3Hadcand.flags == Flags::kBothFromLi4)) { + continue; + } + + if (!settingFillMixedMc && (he3Hadcand.flags == Flags::kMixedPair)) { continue; } From 9f1a0284bb976f2a56cf574810d6193dcd018b04 Mon Sep 17 00:00:00 2001 From: Andrea Giovanni Riffero Date: Mon, 1 Jun 2026 09:50:40 +0200 Subject: [PATCH 367/449] [PWGUD] Update FwdMuonsUPC (#16307) Co-authored-by: ALICE Action Bot --- PWGUD/Tasks/CMakeLists.txt | 2 +- .../{FwdMuonsUPC.cxx => fwdMuonsUpc.cxx} | 497 ++++++------------ 2 files changed, 160 insertions(+), 339 deletions(-) rename PWGUD/Tasks/{FwdMuonsUPC.cxx => fwdMuonsUpc.cxx} (52%) diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 6dbb62a449b..2fb8fa5fbf9 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -200,7 +200,7 @@ o2physics_add_dpl_workflow(upc-pion-analysis COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(fwd-muons-upc - SOURCES FwdMuonsUPC.cxx + SOURCES fwdMuonsUpc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGPIDSelector COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/FwdMuonsUPC.cxx b/PWGUD/Tasks/fwdMuonsUpc.cxx similarity index 52% rename from PWGUD/Tasks/FwdMuonsUPC.cxx rename to PWGUD/Tasks/fwdMuonsUpc.cxx index b3351965727..6057c47f4cb 100644 --- a/PWGUD/Tasks/FwdMuonsUPC.cxx +++ b/PWGUD/Tasks/fwdMuonsUpc.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file FwdMuonsUPC.cxx +/// \file fwdMuonsUpc.cxx /// \brief perform some selections on fwd events and saves the results /// executable name o2-analysis-ud-fwd-muon-upc @@ -18,6 +18,8 @@ #include "PWGUD/DataModel/UDTables.h" +#include "Common/Core/RecoDecay.h" + #include #include #include @@ -30,7 +32,9 @@ #include #include -#include +#include +#include +#include #include #include @@ -77,6 +81,10 @@ DECLARE_SOA_COLUMN(Ezna, ezna, float); DECLARE_SOA_COLUMN(Tznc, tznc, float); DECLARE_SOA_COLUMN(Eznc, eznc, float); DECLARE_SOA_COLUMN(Nclass, nclass, int); +// other info +DECLARE_SOA_COLUMN(PDCAp, pDCAp, float); +DECLARE_SOA_COLUMN(PDCAn, pDCAn, float); +DECLARE_SOA_COLUMN(AmpV0A, ampV0A, std::vector); } // namespace dimu namespace o2::aod @@ -87,7 +95,8 @@ DECLARE_SOA_TABLE(DiMu, "AOD", "DIMU", dimu::PhiAv, dimu::PhiCh, dimu::EnergyP, dimu::Pxp, dimu::Pyp, dimu::Pzp, dimu::Ptp, dimu::Etap, dimu::Phip, dimu::TrackTypep, dimu::EnergyN, dimu::Pxn, dimu::Pyn, dimu::Pzn, dimu::Ptn, dimu::Etan, dimu::Phin, dimu::TrackTypen, - dimu::Tzna, dimu::Ezna, dimu::Tznc, dimu::Eznc, dimu::Nclass); + dimu::Tzna, dimu::Ezna, dimu::Tznc, dimu::Eznc, dimu::Nclass, + dimu::PDCAp, dimu::PDCAn, dimu::AmpV0A); } // namespace o2::aod // for saving tree with info on gen MC @@ -149,6 +158,10 @@ DECLARE_SOA_COLUMN(GenPhip, genPhip, float); DECLARE_SOA_COLUMN(GenPtn, genPtn, float); DECLARE_SOA_COLUMN(GenEtan, genEtan, float); DECLARE_SOA_COLUMN(GenPhin, genPhin, float); +// other info +DECLARE_SOA_COLUMN(PDCAp, pDCAp, float); +DECLARE_SOA_COLUMN(PDCAn, pDCAn, float); +DECLARE_SOA_COLUMN(AmpV0A, ampV0A, std::vector); } // namespace recodimu namespace o2::aod @@ -161,7 +174,8 @@ DECLARE_SOA_TABLE(RecoDimu, "AOD", "RECODIMU", recodimu::Ptn, recodimu::Etan, recodimu::Phin, recodimu::TrackTypen, recodimu::GenPt, recodimu::GenRap, recodimu::GenPhi, recodimu::GenPtp, recodimu::GenEtap, recodimu::GenPhip, - recodimu::GenPtn, recodimu::GenEtan, recodimu::GenPhin); + recodimu::GenPtn, recodimu::GenEtan, recodimu::GenPhin, + recodimu::PDCAp, recodimu::PDCAn, recodimu::AmpV0A); } // namespace o2::aod using namespace o2; @@ -172,23 +186,20 @@ using namespace o2::framework::expressions; const float kRAbsMin = 17.6; const float kRAbsMid = 26.5; const float kRAbsMax = 89.5; -const float kPDca1 = 200.; -const float kPDca2 = 200.; float kEtaMin = -4.0; float kEtaMax = -2.5; const float kPtMin = 0.; -const float kMaxAmpV0A = 100.; const int kReqMatchMIDTracks = 2; const int kReqMatchMFTTracks = 2; const int kMaxChi2MFTMatch = 30; const float kMaxZDCTime = 2.; -const float kMaxZDCTimeHisto = 10.; -const int kMuonPDG = 13; +const int k2Tracks = 2; +const int k4Tracks = 4; -struct FwdMuonsUPC { +struct FwdMuonsUpc { - // a pdg object + // a PDG object Service pdg; using CandidatesFwd = soa::Join; @@ -201,50 +212,32 @@ struct FwdMuonsUPC { // defining histograms using histogram registry: different histos for the different process functions HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry reg0n0n{"reg0n0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry regXn0n{"regXn0n", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry regXnXn{"regXnXn", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mcGenRegistry{"mcGenRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mcRecoRegistry{"mcRecoRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // CONFIGURABLES - static constexpr double Pi = o2::constants::math::PI; // pT of muon pairs - Configurable nBinsPt{"nBinsPt", 250, "N bins in pT histo"}; - Configurable lowPt{"lowPt", 0., "lower limit in pT histo"}; - Configurable highPt{"highPt", 2, "upper limit in pT histo"}; + ConfigurableAxis axisPt{"axisPt", {250, 0.0f, 2.0f}, "#it{p}_{T}^{#mu#mu} (GeV/#it{c})"}; + // pT fit + ConfigurableAxis axisPtFit{"axisPtFit", {VARIABLE_WIDTH, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.175, 0.20, 0.25, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.20, 1.40, 1.60, 1.80, 2.00, 2.50, 3.00, 3.50}, "#it{p}_{T} (GeV/c)"}; // mass of muon pairs - Configurable nBinsMass{"nBinsMass", 500, "N bins in mass histo"}; - Configurable lowMass{"lowMass", 0., "lower limit in mass histo"}; - Configurable highMass{"highMass", 10., "upper limit in mass histo"}; - // eta of muon pairs - Configurable nBinsEta{"nBinsEta", 600, "N bins in eta histo"}; - Configurable lowEta{"lowEta", -10., "lower limit in eta histo"}; - Configurable highEta{"highEta", -2., "upper limit in eta histo"}; + ConfigurableAxis axisMass{"axisMass", {500, 0.0f, 10.0f}, "m_{#mu#mu} (GeV/#it{c}^{2})"}; // rapidity of muon pairs - Configurable nBinsRapidity{"nBinsRapidity", 250, "N bins in rapidity histo"}; - Configurable lowRapidity{"lowRapidity", -4.5, "lower limit in rapidity histo"}; - Configurable highRapidity{"highRapidity", -2., "upper limit in rapidity histo"}; - // phi of muon pairs - Configurable nBinsPhi{"nBinsPhi", 600, "N bins in phi histo"}; - Configurable lowPhi{"lowPhi", -Pi, "lower limit in phi histo"}; - Configurable highPhi{"highPhi", Pi, "upper limit in phi histo"}; - // pT of single muons - Configurable nBinsPtSingle{"nBinsPtSingle", 500, "N bins in pT histo single muon"}; - Configurable lowPtSingle{"lowPtSingle", 0., "lower limit in pT histo single muon"}; - Configurable highPtSingle{"highPtSingle", 2., "upper limit in pT histo single muon"}; - // eta of single muons - Configurable nBinsEtaSingle{"nBinsEtaSingle", 250, "N bins in eta histo single muon"}; - Configurable lowEtaSingle{"lowEtaSingle", -4.5, "lower limit in eta histo single muon"}; - Configurable highEtaSingle{"highEtaSingle", -2., "upper limit in eta histo single muon"}; - // phi of single muons - Configurable nBinsPhiSingle{"nBinsPhiSingle", 600, "N bins in phi histo single muon"}; - Configurable lowPhiSingle{"lowPhiSingle", -Pi, "lower limit in phi histo single muon"}; - Configurable highPhiSingle{"highPhiSingle", Pi, "upper limit in phi histo single muon"}; - // ZDC - Configurable nBinsZDCen{"nBinsZDCen", 200, "N bins in ZN energy"}; - Configurable lowEnZN{"lowEnZN", -50., "lower limit in ZN energy histo"}; - Configurable highEnZN{"highEnZN", 250., "upper limit in ZN energy histo"}; + ConfigurableAxis axisRapidity{"axisRapidity", {250, -4.5f, -2.0f}, "y_{#mu#mu}"}; + + // cuts on pair kinematics + Configurable lowPt{"lowPt", 0., "Low pT cut"}; + Configurable highPt{"highPt", 2, "High pT cut"}; + Configurable lowMass{"lowMass", 0., "Low mass cut"}; + Configurable highMass{"highMass", 10., "High mass cut"}; + Configurable lowRapidity{"lowRapidity", -4.5, "Low rapidity cut"}; + Configurable highRapidity{"highRapidity", -2., "High rapidity cut"}; + + // cuts on pDCA + Configurable pDCA1{"pDCA1", 200., "pDCA cut for tracks with rAbs < 26.5 cm"}; + Configurable pDCA2{"pDCA2", 200., "pDCA cut for tracks with rAbs > 26.5 cm"}; + + // cut on V0A amplitude + Configurable maxAmpV0A{"maxAmpV0A", 100., "Max amplitude in V0A"}; + // my track type // 0 = MCH-MID-MFT // 1 = MCH-MID @@ -252,138 +245,26 @@ struct FwdMuonsUPC { void init(InitContext&) { - // binning of pT axis fr fit - std::vector ptFitBinning = { - 0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, - 0.11, 0.12, 0.13, 0.14, 0.15, 0.175, 0.20, 0.25, 0.30, 0.40, 0.50, - 0.60, 0.70, 0.80, 0.90, 1.00, 1.20, 1.40, 1.60, 1.80, 2.00, 2.50, - 3.00, 3.50}; - - std::vector ptFitBinningHalfWidth = { - 0.00, 0.005, 0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04, 0.045, 0.05, - 0.055, 0.06, 0.065, 0.07, 0.075, 0.08, 0.085, 0.09, 0.095, 0.10, - 0.105, 0.11, 0.115, 0.12, 0.125, 0.13, 0.135, 0.14, 0.145, 0.15, - 0.1625, 0.175, 0.1875, 0.20, 0.225, 0.25, 0.275, 0.30, 0.35, 0.40, - 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, - 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.25, - 2.50, 2.75, 3.00, 3.25, 3.50}; - // axis - const AxisSpec axisPt{nBinsPt, lowPt, highPt, "#it{p}_{T} GeV/#it{c}"}; - const AxisSpec axisPtFit = {ptFitBinning, "#it{p}_{T} (GeV/c)"}; - const AxisSpec axisPtFit2 = {ptFitBinningHalfWidth, "#it{p}_{T} (GeV/c)"}; - const AxisSpec axisMass{nBinsMass, lowMass, highMass, "m_{#mu#mu} GeV/#it{c}^{2}"}; - const AxisSpec axisEta{nBinsEta, lowEta, highEta, "#eta"}; - const AxisSpec axisRapidity{nBinsRapidity, lowRapidity, highRapidity, "Rapidity"}; - const AxisSpec axisPhi{nBinsPhi, lowPhi, highPhi, "#varphi"}; - const AxisSpec axisPtSingle{nBinsPtSingle, lowPtSingle, highPtSingle, "#it{p}_{T}_{ trk} GeV/#it{c}"}; - const AxisSpec axisTimeZN{200, -10, 10, "ZDC time (ns)"}; - const AxisSpec axisEnergyZNA{nBinsZDCen, lowEnZN, highEnZN, "ZNA energy (TeV)"}; - const AxisSpec axisEnergyZNC{nBinsZDCen, lowEnZN, highEnZN, "ZNC energy (TeV)"}; - const AxisSpec axisEtaSingle{nBinsEtaSingle, lowEtaSingle, highEtaSingle, "#eta_{trk}"}; - const AxisSpec axisPhiSingle{nBinsPhiSingle, lowPhiSingle, highPhiSingle, "#varphi_{trk}"}; + const AxisSpec ptAxis{axisPt, "#it{p}_{T}^{#mu#mu} (GeV/#it{c})", "ptAxis"}; + const AxisSpec ptFitAxis{axisPtFit, "#it{p}_{T} (GeV/c)", "ptFitAxis"}; + const AxisSpec massAxis{axisMass, "m_{#mu#mu} (GeV/#it{c}^{2})", "massAxis"}; + const AxisSpec rapidityAxis{axisRapidity, "y_{#mu#mu}", "rapidityAxis"}; // histos - // data and reco MC - registry.add("hMass", "Invariant mass of muon pairs;;#counts", kTH1D, {axisMass}); - registry.add("hPt", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPt}); - registry.add("hPtFit", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit}); - registry.add("hPtFit2", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit2}); - registry.add("hEta", "Pseudorapidty of muon pairs;;#counts", kTH1D, {axisEta}); - registry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {axisRapidity}); - registry.add("hPhi", "#varphi of muon pairs;;#counts", kTH1D, {axisPhi}); - registry.add("hCharge", "Charge;;;#counts", kTH1D, {{5, -2.5, 2.5}}); - registry.add("hContrib", "hContrib;;#counts", kTH1D, {{6, -0.5, 5.5}}); - registry.add("hEvSign", "Sum of the charges of all the tracks in each event;;#counts", kTH1D, {{5, -2.5, 2.5}}); - registry.add("hPtTrkPos", "Pt of positive muons;;#counts", kTH1D, {axisPtSingle}); - registry.add("hPtTrkNeg", "Pt of negative muons;;#counts", kTH1D, {axisPtSingle}); - registry.add("hEtaTrkPos", "#eta of positive muons;;#counts", kTH1D, {axisEtaSingle}); - registry.add("hEtaTrkNeg", "#eta of negative muons;;#counts", kTH1D, {axisEtaSingle}); - registry.add("hPhiTrkPos", "#varphi of positive muons;;#counts", kTH1D, {axisPhiSingle}); - registry.add("hPhiTrkNeg", "#varphi of negative muons;;#counts", kTH1D, {axisPhiSingle}); - registry.add("hSameSign", "hSameSign;;#counts", kTH1D, {{6, -0.5, 5.5}}); - registry.add("hPhiCharge", "#phi #it{charge}", kTH1D, {axisPhi}); - registry.add("hPhiAverage", "#phi #it{average}", kTH1D, {axisPhi}); - - // data - registry.add("hTimeZNA", "ZNA Times;;#counts", kTH1D, {axisTimeZN}); - registry.add("hTimeZNC", "ZNC Times;;#counts", kTH1D, {axisTimeZN}); - registry.add("hEnergyZN", "ZNA vs ZNC energy", kTH2D, {axisEnergyZNA, axisEnergyZNC}); - - reg0n0n.add("hMass", "Invariant mass of muon pairs - 0n0n;;#counts", kTH1D, {axisMass}); - reg0n0n.add("hPt", "Transverse momentum of muon pairs - 0n0n;;#counts", kTH1D, {axisPt}); - reg0n0n.add("hEta", "Pseudorapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisEta}); - reg0n0n.add("hRapidity", "Rapidty of muon pairs - 0n0n;;#counts", kTH1D, {axisRapidity}); - reg0n0n.add("hPtFit", "Transverse momentum of muon pairs - 0n0n;;#counts", kTH1D, {axisPtFit}); - - regXn0n.add("hMass", "Invariant mass of muon pairs - Xn0n;;#counts", kTH1D, {axisMass}); - regXn0n.add("hPt", "Transverse momentum of muon pairs - Xn0n;;#counts", kTH1D, {axisPt}); - regXn0n.add("hEta", "Pseudorapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisEta}); - regXn0n.add("hRapidity", "Rapidty of muon pairs - Xn0n;;#counts", kTH1D, {axisRapidity}); - regXn0n.add("hPtFit", "Transverse momentum of muon pairs - Xn0n;;#counts", kTH1D, {axisPtFit}); - - regXnXn.add("hMass", "Invariant mass of muon pairs - XnXn;;#counts", kTH1D, {axisMass}); - regXnXn.add("hPt", "Transverse momentum of muon pairs - XnXn;;#counts", kTH1D, {axisPt}); - regXnXn.add("hEta", "Pseudorapidty of muon pairs - XnXn;;#counts", kTH1D, {axisEta}); - regXnXn.add("hRapidity", "Rapidty of muon pairs - XnXn;;#counts", kTH1D, {axisRapidity}); - regXnXn.add("hPtFit", "Transverse momentum of muon pairs - XnXn;;#counts", kTH1D, {axisPtFit}); - - // gen MC - mcGenRegistry.add("hMass", "Invariant mass of muon pairs;;#counts", kTH1D, {axisMass}); - mcGenRegistry.add("hPt", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPt}); - mcGenRegistry.add("hEta", "Pseudorapidty of muon pairs;;#counts", kTH1D, {axisEta}); - mcGenRegistry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {axisRapidity}); - mcGenRegistry.add("hPhi", "#varphi of muon pairs;;#counts", kTH1D, {axisPhi}); - mcGenRegistry.add("hPtTrkPos", "Pt of positive muons;;#counts", kTH1D, {axisPtSingle}); - mcGenRegistry.add("hPtTrkNeg", "Pt of negative muons;;#counts", kTH1D, {axisPtSingle}); - mcGenRegistry.add("hEtaTrkPos", "#eta of positive muons;;#counts", kTH1D, {axisEtaSingle}); - mcGenRegistry.add("hEtaTrkNeg", "#eta of negative muons;;#counts", kTH1D, {axisEtaSingle}); - mcGenRegistry.add("hPhiTrkPos", "#varphi of positive muons;;#counts", kTH1D, {axisPhiSingle}); - mcGenRegistry.add("hPhiTrkNeg", "#varphi of negative muons;;#counts", kTH1D, {axisPhiSingle}); - mcGenRegistry.add("hPhiCharge", "#phi #it{charge}", kTH1D, {axisPhi}); - mcGenRegistry.add("hPhiAverage", "#phi #it{average}", kTH1D, {axisPhi}); - - // reco MC - mcRecoRegistry.add("hMass", "Invariant mass of muon pairs;;#counts", kTH1D, {axisMass}); - mcRecoRegistry.add("hPt", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPt}); - mcRecoRegistry.add("hPtFit", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit}); - mcRecoRegistry.add("hPtFit2", "Transverse momentum of muon pairs;;#counts", kTH1D, {axisPtFit2}); - mcRecoRegistry.add("hEta", "Pseudorapidty of muon pairs;;#counts", kTH1D, {axisEta}); - mcRecoRegistry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {axisRapidity}); - mcRecoRegistry.add("hPhi", "#varphi of muon pairs;;#counts", kTH1D, {axisPhi}); - mcRecoRegistry.add("hCharge", "Charge;;;#counts", kTH1D, {{5, -2.5, 2.5}}); - mcRecoRegistry.add("hContrib", "hContrib;;#counts", kTH1D, {{6, -0.5, 5.5}}); - mcRecoRegistry.add("hEvSign", "Sum of the charges of all the tracks in each event;;#counts", kTH1D, {{5, -2.5, 2.5}}); - mcRecoRegistry.add("hPtTrkPos", "Pt of positive muons;;#counts", kTH1D, {axisPtSingle}); - mcRecoRegistry.add("hPtTrkNeg", "Pt of negative muons;;#counts", kTH1D, {axisPtSingle}); - mcRecoRegistry.add("hEtaTrkPos", "#eta of positive muons;;#counts", kTH1D, {axisEtaSingle}); - mcRecoRegistry.add("hEtaTrkNeg", "#eta of negative muons;;#counts", kTH1D, {axisEtaSingle}); - mcRecoRegistry.add("hPhiTrkPos", "#varphi of positive muons;;#counts", kTH1D, {axisPhiSingle}); - mcRecoRegistry.add("hPhiTrkNeg", "#varphi of negative muons;;#counts", kTH1D, {axisPhiSingle}); - mcRecoRegistry.add("hSameSign", "hSameSign;;#counts", kTH1D, {{6, -0.5, 5.5}}); - mcRecoRegistry.add("hPhiCharge", "#phi #it{charge}", kTH1D, {axisPhi}); - mcRecoRegistry.add("hPhiAverage", "#phi #it{average}", kTH1D, {axisPhi}); - - // corr gen-reco - mcRecoRegistry.add("hPtcorr", "gen pT vs reco pT", kTH2D, {axisPt, axisPt}); - mcRecoRegistry.add("hRapcorr", "gen rapidity vs reco rapidity", kTH2D, {axisRapidity, axisRapidity}); - mcRecoRegistry.add("hPhicorr", "gen #phi vs reco #phi", kTH2D, {axisPhi, axisPhi}); + registry.add("hMass", "Invariant mass of muon pairs;;#counts", kTH1D, {massAxis}); + registry.add("hPt", "Transverse momentum of muon pairs;;#counts", kTH1D, {ptAxis}); + registry.add("hPtFit", "Transverse momentum of muon pairs;;#counts", kTH1D, {ptFitAxis}); + registry.add("hRapidity", "Rapidty of muon pairs;;#counts", kTH1D, {rapidityAxis}); } // FUNCTIONS - // retrieve particle mass (GeV/c^2) from TDatabasePDG - float particleMass(int pid) - { - auto mass = pdg->Mass(pid); - return mass; - } - // template function that fills a map with the collision id of each udcollision as key // and a vector with the tracks // map == (key, element) == (udCollisionId, vector of trks) template - void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks const& tracks) { for (const auto& tr : tracks) { int32_t candId = tr.udCollisionId(); @@ -398,13 +279,16 @@ struct FwdMuonsUPC { // and a vector with the tracks // map == (key, element) == (udMcCollisionId, vector of mc particles) template - void collectMcCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + void collectMcCandIDs(std::unordered_map>& tracksPerCand, TTracks const& tracks) { for (const auto& tr : tracks) { int32_t candId = tr.udMcCollisionId(); if (candId < 0) { continue; } + if (std::abs(tr.pdgCode()) != PDG_t::kMuonMinus) { + continue; + } tracksPerCand[candId].push_back(tr.globalIndex()); } } @@ -434,11 +318,11 @@ struct FwdMuonsUPC { // struct used to store the ZDC info in a map struct ZDCinfo { - float timeA; - float timeC; - float enA; - float enC; - int32_t id; + float timeA = 0.f; + float timeC = 0.f; + float enA = 0.f; + float enC = 0.f; + int32_t id = -1; }; // function that fills a map with the collision id of each udcollision as key @@ -475,12 +359,11 @@ struct FwdMuonsUPC { { float rAbs = fwdTrack.rAtAbsorberEnd(); float pDca = fwdTrack.pDca(); - TLorentzVector p; - auto mMu = particleMass(kMuonPDG); - p.SetXYZM(fwdTrack.px(), fwdTrack.py(), fwdTrack.pz(), mMu); - float eta = p.Eta(); - float pt = p.Pt(); - float pDcaMax = rAbs < kRAbsMid ? kPDca1 : kPDca2; + + std::array trackMomentum{fwdTrack.px(), fwdTrack.py(), fwdTrack.pz()}; + float eta = RecoDecay::eta(trackMomentum); + float pt = RecoDecay::pt(trackMomentum); + float pDcaMax = rAbs < kRAbsMid ? pDCA1 : pDCA2; if (eta < kEtaMin || eta > kEtaMax) return false; @@ -494,9 +377,9 @@ struct FwdMuonsUPC { } // function to compute phi for azimuth anisotropy - void computePhiAnis(TLorentzVector p1, TLorentzVector p2, int sign1, float& phiAverage, float& phiCharge) + void computePhiAnis(ROOT::Math::PxPyPzMVector p1, ROOT::Math::PxPyPzMVector p2, int sign1, float& phiAverage, float& phiCharge) { - TLorentzVector tSum, tDiffAv, tDiffCh; + ROOT::Math::PxPyPzMVector tSum, tDiffAv, tDiffCh; tSum = p1 + p2; float halfUnity = 0.5; if (sign1 > 0) { @@ -514,9 +397,9 @@ struct FwdMuonsUPC { } // average - phiAverage = tSum.DeltaPhi(tDiffAv); + phiAverage = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffAv); // charge - phiCharge = tSum.DeltaPhi(tDiffCh); + phiCharge = ROOT::Math::VectorUtil::DeltaPhi(tSum, tDiffCh); } // function that processes the candidates: @@ -531,15 +414,19 @@ struct FwdMuonsUPC { const auto& ampsV0A = cand.amplitudesV0A(); const auto& ampsRelBCsV0A = cand.ampRelBCsV0A(); for (unsigned int i = 0; i < ampsV0A.size(); ++i) { - if (std::abs(ampsRelBCsV0A[i]) <= 1) { - if (ampsV0A[i] > kMaxAmpV0A) + if (std::abs(ampsRelBCsV0A[i]) <= 0) { + if (ampsV0A[i] > maxAmpV0A) return; } } + // select events with exactly 2 forward tracks + if (cand.numContrib() != k2Tracks) { + return; + } + // select opposite charge events only if (cand.netCharge() != 0) { - registry.fill(HIST("hSameSign"), cand.numContrib()); return; } @@ -574,11 +461,9 @@ struct FwdMuonsUPC { return; // form Lorentz vectors - TLorentzVector p1, p2; - auto mMu = particleMass(kMuonPDG); - p1.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), mMu); - p2.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), mMu); - TLorentzVector p = p1 + p2; + ROOT::Math::PxPyPzMVector p1{tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p2{tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p = p1 + p2; // cut on pair kinematics // select mass @@ -602,13 +487,6 @@ struct FwdMuonsUPC { float phiCharge = 0; computePhiAnis(p1, p2, tr1.sign(), phiAverage, phiCharge); - // zdc info - if (std::abs(zdc.timeA) < kMaxZDCTimeHisto) - registry.fill(HIST("hTimeZNA"), zdc.timeA); - if (std::abs(zdc.timeC) < kMaxZDCTimeHisto) - registry.fill(HIST("hTimeZNC"), zdc.timeC); - registry.fill(HIST("hEnergyZN"), zdc.enA, zdc.enC); - // divide the events in neutron classes bool neutronA = false; bool neutronC = false; @@ -619,75 +497,42 @@ struct FwdMuonsUPC { if (std::abs(zdc.timeC) < kMaxZDCTime) neutronC = true; - if (std::isinf(zdc.timeC)) - neutronC = false; - if (std::isinf(zdc.timeA)) - neutronA = false; - - // fill the histos in neutron classes and assign neutron class label + // assign neutron class label // 0n0n if (neutronC == false && neutronA == false) { znClass = 1; - reg0n0n.fill(HIST("hMass"), p.M()); - reg0n0n.fill(HIST("hPt"), p.Pt()); - reg0n0n.fill(HIST("hPtFit"), p.Pt()); - reg0n0n.fill(HIST("hEta"), p.Eta()); - reg0n0n.fill(HIST("hRapidity"), p.Rapidity()); } else if (neutronA ^ neutronC) { // Xn0n + 0nXn if (neutronA) znClass = 2; else if (neutronC) znClass = 3; - regXn0n.fill(HIST("hMass"), p.M()); - regXn0n.fill(HIST("hPt"), p.Pt()); - regXn0n.fill(HIST("hPtFit"), p.Pt()); - regXn0n.fill(HIST("hEta"), p.Eta()); - regXn0n.fill(HIST("hRapidity"), p.Rapidity()); } else if (neutronA && neutronC) { // XnXn znClass = 4; - regXnXn.fill(HIST("hMass"), p.M()); - regXnXn.fill(HIST("hPt"), p.Pt()); - regXnXn.fill(HIST("hPtFit"), p.Pt()); - regXnXn.fill(HIST("hEta"), p.Eta()); - regXnXn.fill(HIST("hRapidity"), p.Rapidity()); } - // fill the histos without looking at neutron emission - registry.fill(HIST("hContrib"), cand.numContrib()); - registry.fill(HIST("hPtTrkPos"), p1.Pt()); - registry.fill(HIST("hPtTrkNeg"), p2.Pt()); - registry.fill(HIST("hEtaTrkPos"), p1.Eta()); - registry.fill(HIST("hEtaTrkNeg"), p2.Eta()); - registry.fill(HIST("hPhiTrkPos"), p1.Phi()); - registry.fill(HIST("hPhiTrkNeg"), p2.Phi()); - registry.fill(HIST("hEvSign"), cand.netCharge()); + // fill the histos registry.fill(HIST("hMass"), p.M()); registry.fill(HIST("hPt"), p.Pt()); registry.fill(HIST("hPtFit"), p.Pt()); - registry.fill(HIST("hPtFit2"), p.Pt()); - registry.fill(HIST("hEta"), p.Eta()); registry.fill(HIST("hRapidity"), p.Rapidity()); - registry.fill(HIST("hPhi"), p.Phi()); - registry.fill(HIST("hCharge"), tr1.sign()); - registry.fill(HIST("hCharge"), tr2.sign()); - registry.fill(HIST("hPhiAverage"), phiAverage); - registry.fill(HIST("hPhiCharge"), phiCharge); // store the event to save it into a tree if (tr1.sign() > 0) { dimuSel(cand.runNumber(), p.M(), p.E(), p.Px(), p.Py(), p.Pz(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.PseudoRapidity(), p1.Phi(), static_cast(myTrackType), - p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.PseudoRapidity(), p2.Phi(), static_cast(myTrackType), - zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.Eta(), p1.Phi(), static_cast(myTrackType), + p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.Eta(), p2.Phi(), static_cast(myTrackType), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass, + tr1.pDca(), tr2.pDca(), ampsV0A); } else { dimuSel(cand.runNumber(), p.M(), p.E(), p.Px(), p.Py(), p.Pz(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.PseudoRapidity(), p2.Phi(), static_cast(myTrackType), - p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.PseudoRapidity(), p1.Phi(), static_cast(myTrackType), - zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass); + p2.E(), p2.Px(), p2.Py(), p2.Pz(), p2.Pt(), p2.Eta(), p2.Phi(), static_cast(myTrackType), + p1.E(), p1.Px(), p1.Py(), p1.Pz(), p1.Pt(), p1.Eta(), p1.Phi(), static_cast(myTrackType), + zdc.timeA, zdc.enA, zdc.timeC, zdc.enC, znClass, + tr2.pDca(), tr1.pDca(), ampsV0A); } } @@ -698,15 +543,18 @@ struct FwdMuonsUPC { { // check that all pairs are mu+mu- - if (std::abs(McPart1.pdgCode()) != kMuonPDG && std::abs(McPart2.pdgCode()) != kMuonPDG) + if (std::abs(McPart1.pdgCode()) != PDG_t::kMuonMinus || std::abs(McPart2.pdgCode()) != PDG_t::kMuonMinus) { LOGF(debug, "PDG codes: %d | %d", McPart1.pdgCode(), McPart2.pdgCode()); + return; + } + if (McPart1.pdgCode() + McPart2.pdgCode() != 0) { + return; + } // create Lorentz vectors - TLorentzVector p1, p2; - auto mMu = particleMass(kMuonPDG); - p1.SetXYZM(McPart1.px(), McPart1.py(), McPart1.pz(), mMu); - p2.SetXYZM(McPart2.px(), McPart2.py(), McPart2.pz(), mMu); - TLorentzVector p = p1 + p2; + ROOT::Math::PxPyPzMVector p1{McPart1.px(), McPart1.py(), McPart1.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p2{McPart2.px(), McPart2.py(), McPart2.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p = p1 + p2; // cut on pair kinematics // select mass @@ -731,31 +579,22 @@ struct FwdMuonsUPC { computePhiAnis(p1, p2, -McPart1.pdgCode(), phiAverage, phiCharge); // fill the histos - mcGenRegistry.fill(HIST("hPtTrkPos"), p1.Pt()); - mcGenRegistry.fill(HIST("hPtTrkNeg"), p2.Pt()); - mcGenRegistry.fill(HIST("hEtaTrkPos"), p1.Eta()); - mcGenRegistry.fill(HIST("hEtaTrkNeg"), p2.Eta()); - mcGenRegistry.fill(HIST("hPhiTrkPos"), p1.Phi()); - mcGenRegistry.fill(HIST("hPhiTrkNeg"), p2.Phi()); - mcGenRegistry.fill(HIST("hMass"), p.M()); - mcGenRegistry.fill(HIST("hPt"), p.Pt()); - mcGenRegistry.fill(HIST("hEta"), p.Eta()); - mcGenRegistry.fill(HIST("hRapidity"), p.Rapidity()); - mcGenRegistry.fill(HIST("hPhi"), p.Phi()); - mcGenRegistry.fill(HIST("hPhiAverage"), phiAverage); - mcGenRegistry.fill(HIST("hPhiCharge"), phiCharge); + registry.fill(HIST("hMass"), p.M()); + registry.fill(HIST("hPt"), p.Pt()); + registry.fill(HIST("hPtFit"), p.Pt()); + registry.fill(HIST("hRapidity"), p.Rapidity()); // store the event to save it into a tree if (McPart1.pdgCode() < 0) { dimuGen(p.M(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p1.Pt(), p1.PseudoRapidity(), p1.Phi(), - p2.Pt(), p2.PseudoRapidity(), p2.Phi()); + p1.Pt(), p1.Eta(), p1.Phi(), + p2.Pt(), p2.Eta(), p2.Phi()); } else { dimuGen(p.M(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p2.Pt(), p2.PseudoRapidity(), p2.Phi(), - p1.Pt(), p1.PseudoRapidity(), p1.Phi()); + p2.Pt(), p2.Eta(), p2.Phi(), + p1.Pt(), p1.Eta(), p1.Phi()); } } @@ -767,22 +606,28 @@ struct FwdMuonsUPC { { // check that all pairs are mu+mu- - if (std::abs(McPart1.pdgCode()) != kMuonPDG && std::abs(McPart2.pdgCode()) != kMuonPDG) + if (std::abs(McPart1.pdgCode()) != PDG_t::kMuonMinus || std::abs(McPart2.pdgCode()) != PDG_t::kMuonMinus) { LOGF(debug, "PDG codes: %d | %d", McPart1.pdgCode(), McPart2.pdgCode()); + return; + } // V0 selection const auto& ampsV0A = cand.amplitudesV0A(); const auto& ampsRelBCsV0A = cand.ampRelBCsV0A(); for (unsigned int i = 0; i < ampsV0A.size(); ++i) { - if (std::abs(ampsRelBCsV0A[i]) <= 1) { - if (ampsV0A[i] > kMaxAmpV0A) + if (std::abs(ampsRelBCsV0A[i]) <= 0) { + if (ampsV0A[i] > maxAmpV0A) return; } } + // select events with exactly 2 forward tracks + if (cand.numContrib() != k2Tracks) { + return; + } + // select opposite charge events only if (cand.netCharge() != 0) { - registry.fill(HIST("hSameSign"), cand.numContrib()); return; } @@ -817,11 +662,9 @@ struct FwdMuonsUPC { return; // form Lorentz vectors - TLorentzVector p1, p2; - auto mMu = particleMass(kMuonPDG); - p1.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), mMu); - p2.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), mMu); - TLorentzVector p = p1 + p2; + ROOT::Math::PxPyPzMVector p1{tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p2{tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p = p1 + p2; // cut on pair kinematics (reco candidates) // select mass @@ -845,16 +688,14 @@ struct FwdMuonsUPC { float phiCharge = 0; computePhiAnis(p1, p2, tr1.sign(), phiAverage, phiCharge); - // gen particle - TLorentzVector p1Mc, p2Mc; - p1Mc.SetXYZM(McPart1.px(), McPart1.py(), McPart1.pz(), mMu); - p2Mc.SetXYZM(McPart2.px(), McPart2.py(), McPart2.pz(), mMu); - TLorentzVector pMc = p1Mc + p2Mc; + ROOT::Math::PxPyPzMVector p1Mc{McPart1.px(), McPart1.py(), McPart1.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector p2Mc{McPart2.px(), McPart2.py(), McPart2.pz(), o2::constants::physics::MassMuon}; + ROOT::Math::PxPyPzMVector pMc = p1Mc + p2Mc; // compute gen phi for azimuth anisotropy float phiGenAverage = 0; float phiGenCharge = 0; - computePhiAnis(p1, p2, -McPart1.pdgCode(), phiGenAverage, phiGenCharge); + computePhiAnis(p1Mc, p2Mc, -McPart1.pdgCode(), phiGenAverage, phiGenCharge); // print info in case of problems if (tr1.sign() * McPart1.pdgCode() > 0 || tr2.sign() * McPart2.pdgCode() > 0) { @@ -865,68 +706,34 @@ struct FwdMuonsUPC { } // fill the histos - // reco info - mcRecoRegistry.fill(HIST("hContrib"), cand.numContrib()); - mcRecoRegistry.fill(HIST("hPtTrkPos"), p1.Pt()); - mcRecoRegistry.fill(HIST("hPtTrkNeg"), p2.Pt()); - mcRecoRegistry.fill(HIST("hEtaTrkPos"), p1.Eta()); - mcRecoRegistry.fill(HIST("hEtaTrkNeg"), p2.Eta()); - mcRecoRegistry.fill(HIST("hPhiTrkPos"), p1.Phi()); - mcRecoRegistry.fill(HIST("hPhiTrkNeg"), p2.Phi()); - mcRecoRegistry.fill(HIST("hEvSign"), cand.netCharge()); - mcRecoRegistry.fill(HIST("hMass"), p.M()); - mcRecoRegistry.fill(HIST("hPt"), p.Pt()); - mcRecoRegistry.fill(HIST("hPtFit"), p.Pt()); - mcRecoRegistry.fill(HIST("hPtFit2"), p.Pt()); - mcRecoRegistry.fill(HIST("hEta"), p.Eta()); - mcRecoRegistry.fill(HIST("hRapidity"), p.Rapidity()); - mcRecoRegistry.fill(HIST("hPhi"), p.Phi()); - mcRecoRegistry.fill(HIST("hCharge"), tr1.sign()); - mcRecoRegistry.fill(HIST("hCharge"), tr2.sign()); - mcRecoRegistry.fill(HIST("hPhiAverage"), phiAverage); - mcRecoRegistry.fill(HIST("hPhiCharge"), phiCharge); - - // gen info (of reco events) - mcGenRegistry.fill(HIST("hPtTrkPos"), p1Mc.Pt()); - mcGenRegistry.fill(HIST("hPtTrkNeg"), p2Mc.Pt()); - mcGenRegistry.fill(HIST("hEtaTrkPos"), p1Mc.Eta()); - mcGenRegistry.fill(HIST("hEtaTrkNeg"), p2Mc.Eta()); - mcGenRegistry.fill(HIST("hPhiTrkPos"), p1Mc.Phi()); - mcGenRegistry.fill(HIST("hPhiTrkNeg"), p2Mc.Phi()); - mcGenRegistry.fill(HIST("hMass"), pMc.M()); - mcGenRegistry.fill(HIST("hPt"), pMc.Pt()); - mcGenRegistry.fill(HIST("hEta"), pMc.Eta()); - mcGenRegistry.fill(HIST("hRapidity"), pMc.Rapidity()); - mcGenRegistry.fill(HIST("hPhi"), pMc.Phi()); - mcGenRegistry.fill(HIST("hPhiAverage"), phiGenAverage); - mcGenRegistry.fill(HIST("hPhiCharge"), phiGenCharge); - - // reco-gen correlations - mcRecoRegistry.fill(HIST("hPtcorr"), p.Pt(), pMc.Pt()); - mcRecoRegistry.fill(HIST("hRapcorr"), p.Rapidity(), pMc.Rapidity()); - mcRecoRegistry.fill(HIST("hPhicorr"), p.Phi(), pMc.Phi()); + registry.fill(HIST("hMass"), p.M()); + registry.fill(HIST("hPt"), p.Pt()); + registry.fill(HIST("hPtFit"), p.Pt()); + registry.fill(HIST("hRapidity"), p.Rapidity()); // store the event to save it into a tree if (tr1.sign() > 0) { dimuReco(cand.runNumber(), p.M(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p1.Pt(), p1.PseudoRapidity(), p1.Phi(), static_cast(myTrackType), - p2.Pt(), p2.PseudoRapidity(), p2.Phi(), static_cast(myTrackType), + p1.Pt(), p1.Eta(), p1.Phi(), static_cast(myTrackType), + p2.Pt(), p2.Eta(), p2.Phi(), static_cast(myTrackType), // gen info pMc.Pt(), pMc.Rapidity(), pMc.Phi(), - p1Mc.Pt(), p1Mc.PseudoRapidity(), p1Mc.Phi(), - p2Mc.Pt(), p2Mc.PseudoRapidity(), p2Mc.Phi()); + p1Mc.Pt(), p1Mc.Eta(), p1Mc.Phi(), + p2Mc.Pt(), p2Mc.Eta(), p2Mc.Phi(), + tr1.pDca(), tr2.pDca(), ampsV0A); } else { dimuReco(cand.runNumber(), p.M(), p.Pt(), p.Rapidity(), p.Phi(), phiAverage, phiCharge, - p2.Pt(), p2.PseudoRapidity(), p2.Phi(), static_cast(myTrackType), - p1.Pt(), p1.PseudoRapidity(), p1.Phi(), static_cast(myTrackType), + p2.Pt(), p2.Eta(), p2.Phi(), static_cast(myTrackType), + p1.Pt(), p1.Eta(), p1.Phi(), static_cast(myTrackType), // gen info pMc.Pt(), pMc.Rapidity(), pMc.Phi(), - p2Mc.Pt(), p2Mc.PseudoRapidity(), p2Mc.Phi(), - p1Mc.Pt(), p1Mc.PseudoRapidity(), p1Mc.Phi()); + p2Mc.Pt(), p2Mc.Eta(), p2Mc.Phi(), + p1Mc.Pt(), p1Mc.Eta(), p1Mc.Phi(), + tr2.pDca(), tr1.pDca(), ampsV0A); } } @@ -946,6 +753,10 @@ struct FwdMuonsUPC { // loop over the candidates for (const auto& item : tracksPerCand) { + if (item.second.size() != k2Tracks) { + LOGF(debug, "number track = %d", item.second.size()); + continue; + } int32_t trId1 = item.second[0]; int32_t trId2 = item.second[1]; int32_t candID = item.first; @@ -968,18 +779,28 @@ struct FwdMuonsUPC { } } - PROCESS_SWITCH(FwdMuonsUPC, processData, "", true); + PROCESS_SWITCH(FwdMuonsUpc, processData, "", true); // process MC Truth void processMcGen(aod::UDMcCollisions const& mccollisions, aod::UDMcParticles const& McParts) { - // map with the tracks std::unordered_map> tracksPerCand; collectMcCandIDs(tracksPerCand, McParts); // loop over the candidates for (const auto& item : tracksPerCand) { + if (item.second.size() != k2Tracks) { + LOGF(debug, "mc parts = %d", item.second.size()); + for (const auto& id : item.second) { + auto p = McParts.iteratorAt(id); + LOGF(debug, + " part %d: pdg=%d status=%d has_mothers=%d has_daughters=%d", + id, p.pdgCode(), p.statusCode(), + p.has_mothers(), p.has_daughters()); + } + continue; + } int32_t trId1 = item.second[0]; int32_t trId2 = item.second[1]; int32_t candID = item.first; @@ -990,12 +811,12 @@ struct FwdMuonsUPC { processMcGenCand(cand, tr1, tr2); } } - PROCESS_SWITCH(FwdMuonsUPC, processMcGen, "", false); + PROCESS_SWITCH(FwdMuonsUpc, processMcGen, "", false); // process reco MC (gen info included) void processMcReco(CandidatesFwd const& eventCandidates, CompleteFwdTracks const& fwdTracks, - aod::UDMcCollisions const&, + aod::UDMcCollisions const& /*mccollisions*/, aod::UDMcParticles const& McParts) { std::unordered_map> tracksPerCandAll; @@ -1003,7 +824,7 @@ struct FwdMuonsUPC { // loop over the candidates for (const auto& item : tracksPerCandAll) { - if (item.second.size() != 4) { + if (item.second.size() != k4Tracks) { LOGF(debug, "number track (reco + gen) = %d", item.second.size()); continue; } @@ -1030,12 +851,12 @@ struct FwdMuonsUPC { processMcRecoCand(cand, tr1, trMc1, tr2, trMc2); } } - PROCESS_SWITCH(FwdMuonsUPC, processMcReco, "", false); + PROCESS_SWITCH(FwdMuonsUpc, processMcReco, "", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; } From 268aeb72c02057bb0d3957440e7d20a8a9f1006d Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Mon, 1 Jun 2026 11:04:17 +0200 Subject: [PATCH 368/449] [Common,PWGLF] Add TOF NSigma from TOF PID framework (#16393) Co-authored-by: Daiki Sekihata Co-authored-by: ALICE Action Bot --- Common/Core/PID/PIDTOFParamService.cxx | 5 +- Common/Core/PID/PIDTOFParamService.h | 6 +- PWGLF/DataModel/LFStrangenessPIDTables.h | 79 ++- PWGLF/DataModel/LFStrangenessTables.h | 7 +- .../Strangeness/Converters/CMakeLists.txt | 7 +- .../stradautrackstofpidconverter.cxx | 11 +- .../stradautrackstofpidconverter2.cxx | 10 +- .../stradautrackstofpidconverter3.cxx | 56 ++ .../Strangeness/strangederivedbuilder.cxx | 53 +- .../Strangeness/strangenesstofpid.cxx | 633 ++++++++++++++---- 10 files changed, 702 insertions(+), 165 deletions(-) create mode 100644 PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx diff --git a/Common/Core/PID/PIDTOFParamService.cxx b/Common/Core/PID/PIDTOFParamService.cxx index 463ddd6ee48..f614e17dd7c 100644 --- a/Common/Core/PID/PIDTOFParamService.cxx +++ b/Common/Core/PID/PIDTOFParamService.cxx @@ -69,7 +69,8 @@ void o2::pid::tof::TOFResponseImpl::inheritFromBaseTask(o2::framework::InitConte } void o2::pid::tof::TOFResponseImpl::initSetup(o2::ccdb::BasicCCDBManager* ccdb, - o2::framework::InitContext& initContext) + o2::framework::InitContext& initContext, + const std::string task) { if (mIsInit) { LOG(fatal) << "TOFResponseImpl already initialized, cannot re-initialize"; @@ -78,7 +79,7 @@ void o2::pid::tof::TOFResponseImpl::initSetup(o2::ccdb::BasicCCDBManager* ccdb, if (!ccdb) { LOG(fatal) << "CCDB manager is not set, cannot initialize TOFResponseImpl"; } - inheritFromBaseTask(initContext); // Gets the configuration parameters from the base task (tof-signal) + inheritFromBaseTask(initContext, task); // Gets the configuration parameters from the base task (tof-signal) mCcdb = ccdb; // Set the CCDB manager mCcdb->setURL(mUrl); mCcdb->setTimestamp(mTimestamp); diff --git a/Common/Core/PID/PIDTOFParamService.h b/Common/Core/PID/PIDTOFParamService.h index 69d8fbfed0d..f6747c598ef 100644 --- a/Common/Core/PID/PIDTOFParamService.h +++ b/Common/Core/PID/PIDTOFParamService.h @@ -49,14 +49,14 @@ struct TOFResponseImpl { /// \note This function should be called in the init function of each task that uses the TOF response /// \note The parameters are loaded from the CCDB and stored in the static variable `parameters` /// \note The metadata information is also initialized in this function - void initSetup(o2::ccdb::BasicCCDBManager* ccdb, o2::framework::InitContext& initContext); + void initSetup(o2::ccdb::BasicCCDBManager* ccdb, o2::framework::InitContext& initContext, const std::string task = "tof-signal"); /// Initialize the TOF response parameters in the init function of each task /// \param ccdb Service pointer to the CCDB manager template - void initSetup(T ccdb, o2::framework::InitContext& initContext) + void initSetup(T ccdb, o2::framework::InitContext& initContext, const std::string task = "tof-signal") { - initSetup(ccdb.operator->(), initContext); + initSetup(ccdb.operator->(), initContext, task); } /// Initialize the TOF response parameters in the process function of each task, should be called only at least once per run diff --git a/PWGLF/DataModel/LFStrangenessPIDTables.h b/PWGLF/DataModel/LFStrangenessPIDTables.h index 14c3dade24c..852be92347d 100644 --- a/PWGLF/DataModel/LFStrangenessPIDTables.h +++ b/PWGLF/DataModel/LFStrangenessPIDTables.h @@ -112,6 +112,7 @@ DECLARE_SOA_INDEX_COLUMN(DauTrackExtra, dauTrackExtra); //! point to daughter th DECLARE_SOA_INDEX_COLUMN(StraCollision, straCollision); //! point to collision associated with this track (not the V0/Casc) DECLARE_SOA_COLUMN(TOFSignal, tofSignal, float); //! track TOF signal DECLARE_SOA_COLUMN(TOFEvTime, tofEvTime, float); //! event time +DECLARE_SOA_COLUMN(TOFEvTimeErr, tofEvTimeErr, float); //! event time error for TOF DECLARE_SOA_COLUMN(Length, length, float); //! track length (to assigned PV) DECLARE_SOA_COLUMN(TOFExpMom, tofExpMom, float); //! tof Exp Mom (to assigned PV) @@ -171,7 +172,17 @@ DECLARE_SOA_TABLE_VERSIONED(DauTrackTOFPIDs_001, "AOD", "DAUTRACKTOFPID", 1, // dautrack::TOFExpTimeKa, dautrack::TOFExpTimePr); -using DauTrackTOFPIDs = DauTrackTOFPIDs_001; // second gen: with collision Id, with TOFExpMom +DECLARE_SOA_TABLE_VERSIONED(DauTrackTOFPIDs_002, "AOD", "DAUTRACKTOFPID", 2, // raw table (for posterior TOF calculation) + o2::soa::Index<>, + dautrack::StraCollisionId, dautrack::DauTrackExtraId, + dautrack::TOFSignal, dautrack::TOFEvTime, dautrack::TOFEvTimeErr, + dautrack::Length, dautrack::TOFExpMom, + dautrack::TOFExpTimeEl, + dautrack::TOFExpTimePi, + dautrack::TOFExpTimeKa, + dautrack::TOFExpTimePr); + +using DauTrackTOFPIDs = DauTrackTOFPIDs_002; // second gen: with collision Id, with TOFExpMom namespace v0data { @@ -211,6 +222,34 @@ DECLARE_SOA_COLUMN(TOFNSigmaALaPi, tofNSigmaALaPi, float); //! positive DECLARE_SOA_COLUMN(TOFNSigmaK0PiPlus, tofNSigmaK0PiPlus, float); //! positive track NSigma from pion <- k0short expectation DECLARE_SOA_COLUMN(TOFNSigmaK0PiMinus, tofNSigmaK0PiMinus, float); //! negative track NSigma from pion <- k0short expectation +// for wrong hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElPosFromPhoton, tofNSigmaElPosFromPhoton, float); //! n sigma of positive track from photon conversion under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElNegFromPhoton, tofNSigmaElNegFromPhoton, float); //! n sigma of negative track from photon conversion under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiPosFromPhoton, tofNSigmaPiPosFromPhoton, float); //! n sigma of positive track from photon conversion under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiNegFromPhoton, tofNSigmaPiNegFromPhoton, float); //! n sigma of negative track from photon conversion under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaPosFromPhoton, tofNSigmaKaPosFromPhoton, float); //! n sigma of positive track from photon conversion under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaNegFromPhoton, tofNSigmaKaNegFromPhoton, float); //! n sigma of negative track from photon conversion under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrPosFromPhoton, tofNSigmaPrPosFromPhoton, float); //! n sigma of positive track from photon conversion under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrNegFromPhoton, tofNSigmaPrNegFromPhoton, float); //! n sigma of negative track from photon conversion under proton hypothesis + +DECLARE_SOA_COLUMN(TOFNSigmaElPosFromK0S, tofNSigmaElPosFromK0S, float); //! n sigma of positive track from K0S under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElNegFromK0S, tofNSigmaElNegFromK0S, float); //! n sigma of negative track from K0S under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiPosFromK0S, tofNSigmaPiPosFromK0S, float); //! n sigma of positive track from K0S under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiNegFromK0S, tofNSigmaPiNegFromK0S, float); //! n sigma of negative track from K0S under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaPosFromK0S, tofNSigmaKaPosFromK0S, float); //! n sigma of positive track from K0S under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaNegFromK0S, tofNSigmaKaNegFromK0S, float); //! n sigma of negative track from K0S under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrPosFromK0S, tofNSigmaPrPosFromK0S, float); //! n sigma of positive track from K0S under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrNegFromK0S, tofNSigmaPrNegFromK0S, float); //! n sigma of negative track from K0S under proton hypothesis + +DECLARE_SOA_COLUMN(TOFNSigmaElPosFromLambda, tofNSigmaElPosFromLambda, float); //! n sigma of positive track from Lambda under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElNegFromLambda, tofNSigmaElNegFromLambda, float); //! n sigma of negative track from Lambda under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiPosFromLambda, tofNSigmaPiPosFromLambda, float); //! n sigma of positive track from Lambda under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiNegFromLambda, tofNSigmaPiNegFromLambda, float); //! n sigma of negative track from Lambda under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaPosFromLambda, tofNSigmaKaPosFromLambda, float); //! n sigma of positive track from Lambda under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaNegFromLambda, tofNSigmaKaNegFromLambda, float); //! n sigma of negative track from Lambda under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrPosFromLambda, tofNSigmaPrPosFromLambda, float); //! n sigma of positive track from Lambda under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrNegFromLambda, tofNSigmaPrNegFromLambda, float); //! n sigma of negative track from Lambda under proton hypothesis + // dynamics to replace hasTOF (note: that condition does not match track hasTOF!) // note: only single hypothesis check necessary; other hypotheses will always be valid DECLARE_SOA_DYNAMIC_COLUMN(PositiveHasTOF, positiveHasTOF, //! positive daughter TOF calculation valid @@ -317,10 +356,20 @@ DECLARE_SOA_TABLE(V0TOFNSigmas, "AOD", "V0TOFNSIGMA", // processed NSigma table v0data::TofAntiLambdaCompatibility, v0data::TofK0ShortCompatibility); +DECLARE_SOA_TABLE(V0TOFNSigmasAll, "AOD", "V0TOFNSIGMAALL", // processed NSigma table (for analysis) including wrong hypothesis + v0data::TOFNSigmaElPosFromPhoton, v0data::TOFNSigmaElPosFromK0S, v0data::TOFNSigmaElPosFromLambda, + v0data::TOFNSigmaElNegFromPhoton, v0data::TOFNSigmaElNegFromK0S, v0data::TOFNSigmaElNegFromLambda, + v0data::TOFNSigmaPiPosFromPhoton, v0data::TOFNSigmaPiPosFromK0S, v0data::TOFNSigmaPiPosFromLambda, + v0data::TOFNSigmaPiNegFromPhoton, v0data::TOFNSigmaPiNegFromK0S, v0data::TOFNSigmaPiNegFromLambda, + v0data::TOFNSigmaKaPosFromPhoton, v0data::TOFNSigmaKaPosFromK0S, v0data::TOFNSigmaKaPosFromLambda, + v0data::TOFNSigmaKaNegFromPhoton, v0data::TOFNSigmaKaNegFromK0S, v0data::TOFNSigmaKaNegFromLambda, + v0data::TOFNSigmaPrPosFromPhoton, v0data::TOFNSigmaPrPosFromK0S, v0data::TOFNSigmaPrPosFromLambda, + v0data::TOFNSigmaPrNegFromPhoton, v0data::TOFNSigmaPrNegFromK0S, v0data::TOFNSigmaPrNegFromLambda); + namespace cascdata { // define constants for NSigma operation -const float kNoTOFValue = -1e+6; +constexpr float kNoTOFValue = -1e+6; const float kEpsilon = 1e-4; // lengths as stored in the AO2D for TOF calculations @@ -354,6 +403,27 @@ DECLARE_SOA_COLUMN(TOFNSigmaOmLaPi, tofNSigmaOmLaPi, float); //! meson track NSi DECLARE_SOA_COLUMN(TOFNSigmaOmLaPr, tofNSigmaOmLaPr, float); //! baryon track NSigma from proton <- lambda <- om expectation DECLARE_SOA_COLUMN(TOFNSigmaOmKa, tofNSigmaOmKa, float); //! bachelor track NSigma from kaon <- om expectation +// for wrong hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElFromLambdaFromXi, tofNSigmaElFromLambdaFromXi, float); //! nigma of positive track from Lambda from Xi under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElFromXi, tofNSigmaElFromXi, float); //! nigma of bachelor track from Xi under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElFromLambdaFromOmega, tofNSigmaElFromLambdaFromOmega, float); //! nigma of positive track from Lambda from Omega under electron hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaElFromOmega, tofNSigmaElFromOmega, float); //! nigma of bachelor track from Omega under electron hypothesis + +DECLARE_SOA_COLUMN(TOFNSigmaPiFromLambdaFromXi, tofNSigmaPiFromLambdaFromXi, float); //! nigma of positive track from Lambda from Xi under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiFromXi, tofNSigmaPiFromXi, float); //! nigma of bachelor track from Xi under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiFromLambdaFromOmega, tofNSigmaPiFromLambdaFromOmega, float); //! nigma of positive track from Lambda from Omega under pion hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPiFromOmega, tofNSigmaPiFromOmega, float); //! nigma of bachelor track from Omega under pion hypothesis + +DECLARE_SOA_COLUMN(TOFNSigmaKaFromLambdaFromXi, tofNSigmaKaFromLambdaFromXi, float); //! nigma of positive track from Lambda from Xi under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaFromXi, tofNSigmaKaFromXi, float); //! nigma of bachelor track from Xi under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaFromLambdaFromOmega, tofNSigmaKaFromLambdaFromOmega, float); //! nigma of positive track from Lambda from Omega under kaon hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaKaFromOmega, tofNSigmaKaFromOmega, float); //! nigma of bachelor track from Omega under kaon hypothesis + +DECLARE_SOA_COLUMN(TOFNSigmaPrFromLambdaFromXi, tofNSigmaPrFromLambdaFromXi, float); //! nigma of positive track from Lambda from Xi under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrFromXi, tofNSigmaPrFromXi, float); //! nigma of bachelor track from Xi under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrFromLambdaFromOmega, tofNSigmaPrFromLambdaFromOmega, float); //! nigma of positive track from Lambda from Omega under proton hypothesis +DECLARE_SOA_COLUMN(TOFNSigmaPrFromOmega, tofNSigmaPrFromOmega, float); //! nigma of bachelor track from Omega under proton hypothesis + // dynamics to replace hasTOF (note: that condition does not match track hasTOF!) // note: only single hypothesis check necessary; other hypotheses will always be valid DECLARE_SOA_DYNAMIC_COLUMN(PositiveHasTOF, positiveHasTOF, //! positive daughter TOF calculation valid @@ -437,6 +507,11 @@ DECLARE_SOA_TABLE(CascTOFNSigmas, "AOD", "CascTOFNSigmas", // Nsigmas for cascad cascdata::BachelorHasTOF, cascdata::TofXiCompatibility, cascdata::TofOmegaCompatibility); +DECLARE_SOA_TABLE(CascTOFNSigmasAll, "AOD", "CascTOFNSigmasAll", // Nsigmas for cascades including wrong hypothesis + cascdata::TOFNSigmaElFromLambdaFromXi, cascdata::TOFNSigmaElFromXi, cascdata::TOFNSigmaElFromLambdaFromOmega, cascdata::TOFNSigmaElFromOmega, + cascdata::TOFNSigmaPiFromLambdaFromXi, cascdata::TOFNSigmaPiFromXi, cascdata::TOFNSigmaPiFromLambdaFromOmega, cascdata::TOFNSigmaPiFromOmega, + cascdata::TOFNSigmaKaFromLambdaFromXi, cascdata::TOFNSigmaKaFromXi, cascdata::TOFNSigmaKaFromLambdaFromOmega, cascdata::TOFNSigmaKaFromOmega, + cascdata::TOFNSigmaPrFromLambdaFromXi, cascdata::TOFNSigmaPrFromXi, cascdata::TOFNSigmaPrFromLambdaFromOmega, cascdata::TOFNSigmaPrFromOmega); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFSTRANGENESSPIDTABLES_H_ diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index 777b2675c5f..dc2f4846058 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -65,6 +65,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(EnergyCommonZNC, energyCommonZNC, //! get the total s // event time DECLARE_SOA_COLUMN(EventTime, eventTime, float); //! event time (FT0, TOF) for TOF PID (stored once per event) +// event time +DECLARE_SOA_COLUMN(EventTimeErr, eventTimeErr, float); //! event time (FT0, TOF) for TOF PID (stored once per event) } // namespace stracollision //______________________________________________________ @@ -325,13 +327,16 @@ DECLARE_SOA_TABLE(StraStamps_000, "AOD", "STRASTAMPS", //! information for ID-in bc::RunNumber, timestamp::Timestamp); DECLARE_SOA_TABLE_VERSIONED(StraStamps_001, "AOD", "STRASTAMPS", 1, //! information for ID-ing mag field if needed bc::RunNumber, timestamp::Timestamp, bc::GlobalBC); -DECLARE_SOA_TABLE(StraEvTimes, "AOD", "STRAEVTIMES", //! event time (FT0, TOF) +DECLARE_SOA_TABLE(StraEvTimes_000, "AOD", "STRAEVTIMES", //! event time (FT0, TOF) stracollision::EventTime); +DECLARE_SOA_TABLE_VERSIONED(StraEvTimes_001, "AOD", "STRAEVTIMES", 1, //! event time (FT0, TOF) + stracollision::EventTime, stracollision::EventTimeErr); using StraRawCents = StraRawCents_004; using StraCents = StraCents_002; using StraEvSels = StraEvSels_005; using StraStamps = StraStamps_001; +using StraEvTimes = StraEvTimes_001; using StraCollision = StraCollisions::iterator; using StraCent = StraCents::iterator; diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 8239715863d..175a7c852bd 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -29,9 +29,14 @@ o2physics_add_dpl_workflow(stradautrackstofpidconverter2 PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(stradautrackstofpidconverter3 + SOURCES stradautrackstofpidconverter3.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(stradautracksextraconverter SOURCES stradautracksextraconverter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(stradautracksextraconverter2 diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx index 6c57959c7f4..a3cabe45b2d 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx @@ -8,6 +8,14 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +// +/// \file stradautrackstofpidconverter.cxx +/// \brief Produces DauTrackTOFPIDs from V0TOFs and CascTOFs table +/// +/// \author David Dobrigkeit Chinellato , Austrian Academy of Sciences & MBI +/// \author Romain Schotter , Austrian Academy of Sciences & MBI +// + #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -21,7 +29,6 @@ using namespace o2; using namespace o2::framework; -// Converts V0 version 001 to 002 struct stradautrackstofpidconverter { Produces dautracktofpids; @@ -49,7 +56,7 @@ struct stradautrackstofpidconverter { lTOFEvTimes[casc.bachTrackExtraId()] = casc.bachTOFEventTime(); } for (unsigned int ii = 0; ii < dauTracks.size(); ii++) { - dautracktofpids(-1, -1, lTOFSignals[ii], lTOFEvTimes[ii], lLengths[ii], 0.0f); + dautracktofpids(-1, -1, lTOFSignals[ii], lTOFEvTimes[ii], 999.0f /*dummy event time error for TOF*/, lLengths[ii], 0.0f); } } }; diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx index 875450e6f67..de6dde54201 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx @@ -8,6 +8,14 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +// +/// \file stradautrackstofpidconverter2.cxx +/// \brief Converts DauTrackTOFPIDs_000 into DauTrackTOFPID_001 and StraEvTimes_000 +/// +/// \author David Dobrigkeit Chinellato , Austrian Academy of Sciences & MBI +/// \author Romain Schotter , Austrian Academy of Sciences & MBI +// + #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -24,7 +32,7 @@ using namespace o2::framework; // converts DauTrackTOFPIDs_000 to _001 struct stradautrackstofpidconverter2 { Produces dautracktofpids; - Produces straEvTimes; + Produces straEvTimes; void process(aod::StraCollisions const& collisions, soa::Join const& dauTracks, soa::Join const& v0s) { diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx new file mode 100644 index 00000000000..c03cbead81e --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx @@ -0,0 +1,56 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file stradautrackstofpidconverter3.cxx +/// \brief Converts DauTrackTOFPID_001 and StraEvTimes_000 into DauTrackTOFPID_002 and StraEvTimes_001 +/// +/// \author David Dobrigkeit Chinellato , Austrian Academy of Sciences & MBI +/// \author Romain Schotter , Austrian Academy of Sciences & MBI + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; + +// converts DauTrackTOFPIDs_001 to _002 +struct stradautrackstofpidconverter3 { + Produces dautracktofpids; + Produces straEvTimes; + + void process(aod::DauTrackTOFPIDs_001 const& dauTracks, aod::StraEvTimes_000 const& straEvTimes_000) + { + // create new TOFPIDs + for (const auto& dauTrack : dauTracks) { + dautracktofpids( + -1, + -1, + dauTrack.tofSignal(), + dauTrack.tofEvTime(), + 999.0f, /*dummy event time error for TOF*/ + dauTrack.length(), + 0.0f); + } + for (const auto& value : straEvTimes_000) { + straEvTimes(value.eventTime(), 999.0f /*dummy event time error for TOF*/); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx index f4afc11f227..1878aaa9135 100644 --- a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx @@ -9,11 +9,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // +/// \file strangederivedbuilder.cxx +/// \brief this task provides general links between collisions and strange objects reconstructed in various ways. +/// It is meant to help with providing auxiliary information when dealing with derived data. +/// +/// \author David Dobrigkeit Chinellato , Austrian Academy of Sciences & MBI +/// \author Romain Schotter , Austrian Academy of Sciences & MBI +// //__________________________________________________ -// this task provides general links between collisions -// and strange objects reconstructed in various ways. -// It is meant to help with providing auxiliary information -// when dealing with derived data. +// #include "PWGLF/DataModel/EPCalibrationTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" @@ -481,7 +485,7 @@ struct strangederivedbuilder { if constexpr (requires { udCollIterator.gapSide(); }) { // check if this table is the expected one auto udCollision = udCollisions.sliceBy(udCollisionsPerCollision, collIdx); if (udCollision.size() == 1) { // check that the slicing provide a unique UD collision - for (auto& udColl : udCollision) { + for (const auto& udColl : udCollision) { gapSide = udColl.gapSide(); totalFT0AmplitudeA = udColl.totalFT0AmplitudeA(); totalFT0AmplitudeC = udColl.totalFT0AmplitudeC(); @@ -652,21 +656,26 @@ struct strangederivedbuilder { void populateEventTimes(coll const& collisions, TTracks const& tracks) { std::vector collisionEventTime(collisions.size(), 0.0); + std::vector collisionEventTimeErr(collisions.size(), 0.0); std::vector collisionNtracks(collisions.size(), 0); for (const auto& track : tracks) { if (track.hasTOF() && track.collisionId() >= 0) { collisionEventTime[track.collisionId()] += track.tofEvTime(); + // Take the average of the error instead of propagating the error as all event time error from tracks are fully correlated + collisionEventTimeErr[track.collisionId()] += track.tofEvTimeErr(); collisionNtracks[track.collisionId()]++; } } for (const auto& collision : collisions) { if (collisionNtracks[collision.globalIndex()] > 0) { collisionEventTime[collision.globalIndex()] /= static_cast(collisionNtracks[collision.globalIndex()]); + collisionEventTimeErr[collision.globalIndex()] /= static_cast(collisionNtracks[collision.globalIndex()]); } else { collisionEventTime[collision.globalIndex()] = -1e+6; // undefined + collisionEventTimeErr[collision.globalIndex()] = -1e-6; // undefined } histos.fill(HIST("h2dCollisionTimesVsNTracks"), collisionNtracks[collision.globalIndex()], collisionEventTime[collision.globalIndex()]); - products.straEvTimes(collisionEventTime[collision.globalIndex()]); + products.straEvTimes(collisionEventTime[collision.globalIndex()], collisionEventTimeErr[collision.globalIndex()]); } } @@ -896,7 +905,7 @@ struct strangederivedbuilder { aod::dautrack::packing::packInInt8(tr.tpcNSigmaPr())); // populate daughter-level TOF information if (tr.hasTOF()) { - products.dauTrackTOFPIDs(tr.collisionId(), products.dauTrackExtras.lastIndex(), tr.tofSignal(), tr.tofEvTime(), tr.length(), tr.tofExpMom()); + products.dauTrackTOFPIDs(tr.collisionId(), products.dauTrackExtras.lastIndex(), tr.tofSignal(), tr.tofEvTime(), tr.tofEvTimeErr(), tr.length(), tr.tofExpMom()); } } else { // populate with empty fully-compatible Nsigmas if no corresponding table available @@ -1029,8 +1038,8 @@ struct strangederivedbuilder { void processPureSimulation(aod::McParticles const& mcParticles) { - for (auto& mcp : mcParticles) { - if (TMath::Abs(mcp.y()) < 0.5) { + for (auto const& mcp : mcParticles) { + if (std::abs(mcp.y()) < 0.5) { static_for<0, nSpecies - 1>([&](auto i) { constexpr int index = i.value; if (mcp.pdgCode() == particlePDGCodes[index] && bitcheck(enabledBits, index)) { @@ -1047,7 +1056,7 @@ struct strangederivedbuilder { // identify best-of collision int biggestNContribs = -1; float bestCentrality = 100.5; - for (auto& collision : collisions) { + for (auto const& collision : collisions) { if (biggestNContribs < collision.numContrib()) { biggestNContribs = collision.numContrib(); bestCentrality = collision.centFT0C(); @@ -1059,8 +1068,8 @@ struct strangederivedbuilder { } histos.fill(HIST("h2dNVerticesVsCentrality"), bestCentrality, collisions.size()); - for (auto& mcp : mcParticles) { - if (TMath::Abs(mcp.y()) < 0.5 && mcp.isPhysicalPrimary()) { + for (auto const& mcp : mcParticles) { + if (std::abs(mcp.y()) < 0.5 && mcp.isPhysicalPrimary()) { static_for<0, nSpecies - 1>([&](auto i) { constexpr int index = i.value; if (mcp.pdgCode() == particlePDGCodes[index] && bitcheck(enabledBits, index)) { @@ -1083,29 +1092,29 @@ struct strangederivedbuilder { std::fill(genOmegaPlus.begin(), genOmegaPlus.end(), 0); // this process function also checks if a given collision was reconstructed and checks explicitly for splitting, etc - for (auto& mcCollision : mcCollisions) { + for (auto const& mcCollision : mcCollisions) { const uint64_t mcCollIndex = mcCollision.globalIndex(); // use one of the generated histograms as the bin finder auto hBinFinder = histos.get(HIST("h2dGeneratedK0Short")); auto mcParticles = mcParticlesEntireTable.sliceBy(mcParticlePerMcCollision, mcCollIndex); - for (auto& mcp : mcParticles) { - if (TMath::Abs(mcp.y()) < 0.5 && mcp.isPhysicalPrimary()) { + for (auto const& mcp : mcParticles) { + if (std::abs(mcp.y()) < 0.5 && mcp.isPhysicalPrimary()) { auto binNumber = hBinFinder->FindBin(mcCollision.bestCollisionCentFT0C(), mcp.pt()); // caution: pack - if (mcp.pdgCode() == 310) + if (mcp.pdgCode() == PDG_t::kK0Short) genK0Short[binNumber]++; - if (mcp.pdgCode() == 3122) + if (mcp.pdgCode() == PDG_t::kLambda0) genLambda[binNumber]++; - if (mcp.pdgCode() == -3122) + if (mcp.pdgCode() == PDG_t::kLambda0Bar) genAntiLambda[binNumber]++; - if (mcp.pdgCode() == 3312) + if (mcp.pdgCode() == PDG_t::kXiMinus) genXiMinus[binNumber]++; - if (mcp.pdgCode() == -3312) + if (mcp.pdgCode() == PDG_t::kXiPlusBar) genXiPlus[binNumber]++; - if (mcp.pdgCode() == 3334) + if (mcp.pdgCode() == PDG_t::kOmegaMinus) genOmegaMinus[binNumber]++; - if (mcp.pdgCode() == -3334) + if (mcp.pdgCode() == PDG_t::kOmegaPlusBar) genOmegaPlus[binNumber]++; } } diff --git a/PWGLF/TableProducer/Strangeness/strangenesstofpid.cxx b/PWGLF/TableProducer/Strangeness/strangenesstofpid.cxx index cd189e45c83..a1145093ae0 100644 --- a/PWGLF/TableProducer/Strangeness/strangenesstofpid.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenesstofpid.cxx @@ -13,6 +13,7 @@ // Strangeness TOF PID // *+-+*+-+*+-+*+-+*+-+*+-+* // +/// \file strangenesstofpid.cxx /// \author Nicolò Jacazio /// \author David Dobrigkeit Chinellato /// \since 11/05/2023 @@ -63,8 +64,10 @@ #include #include #include -#include +#include +#include #include +#include #include using namespace o2; @@ -76,7 +79,7 @@ using std::array; // For original data loops using V0OriginalDatas = soa::Join; using CascOriginalDatas = soa::Join; -using TracksWithAllExtras = soa::Join; +using TracksWithAllExtras = soa::Join; // For derived data analysis using dauTracks = soa::Join; @@ -94,7 +97,11 @@ struct strangenesstofpid { Produces casctofpids; // cascades: table with base info Produces casctofnsigmas; // cascades: table with Nsigmas + Produces v0tofnsigmasall; // table with nsigmas including wrong hypothesis + Produces casctofnsigmasall; // cascades: table with Nsigmas including wrong hypothesis + Service ccdb; + Service mTOFResponse; // mean vertex position to be used if no collision associated o2::dataformats::MeanVertexObject* mVtx = nullptr; @@ -108,10 +115,14 @@ struct strangenesstofpid { Configurable calculationMethod{"calculationMethod", 0, "algorithm for TOF calculation. 0: fast analytical withouot eloss, 1: O2 Propagator + trackLTIntegral (slow), 2: both methods and do comparison studies (slow)"}; Configurable calculateV0s{"calculateV0s", -1, "calculate V0-related TOF PID (0: no, 1: yes, -1: auto)"}; Configurable calculateCascades{"calculateCascades", -1, "calculate cascade-related TOF PID (0: no, 1: yes, -1: auto)"}; + Configurable useNsigmaCalibStrTOF{"useNsigmaCalibStrTOF", true, "if true, use manual strangeness TOF PID calibration"}; Configurable reassociateTracks{"reassociateTracks", true, "if true, reassociate tracks to the collision the V0 or cascade belongs to. Relevant especially at high IR"}; Configurable doBCshift{"doBCshift", true, "if true, perform time shift for collisions in different BCs when reassigning"}; Configurable rejectUndefinedTof{"rejectUndefinedTof", true, "if true, reject tracks with TOF signal 0.000f for safety"}; + Configurable calculateV0sNSigmaAll{"calculateV0sNSigmaAll", -1, "calculate all V0-related TOF n sigma(0: no, 1: yes, -1: auto)"}; + Configurable calculateCascadesNSigmaAll{"calculateCascadesNSigmaAll", -1, "calculate all cascade-related TOF n sigma(0: no, 1: yes, -1: auto)"}; + // auxiliary / debug tables as desired Configurable calculateV0TOFPIDs{"calculateV0TOFPIDs", -1, "calculate V0TOFPIDs table (0: no, 1: yes, -1: auto)"}; Configurable calculateV0TOFBetas{"calculateV0TOFBetas", -1, "calculate V0TOFBetas table (0: no, 1: yes, -1: auto)"}; @@ -150,15 +161,41 @@ struct strangenesstofpid { // CCDB options struct : ConfigurableGroup { - std::string prefix = "ccdb"; + // std::string prefix = "ccdb"; Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable nSigmaPath{"nSigmaPath", "Users/d/ddobrigk/stratof", "Path of information for n-sigma calculation"}; Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + // necessary for TOFResponse + Configurable grpLhcIfPath{"ccdb-path-grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + Configurable timeShiftCCDBPathPos{"timeShiftCCDBPathPos", "Analysis/PID/TOFOffsetPos", "Path of the TOF time shift vs eta for pos. tracks. If empty none is taken"}; + Configurable timeShiftCCDBPathNeg{"timeShiftCCDBPathNeg", "Analysis/PID/TOFOffsetNeg", "Path of the TOF time shift vs eta for neg. tracks. If empty none is taken"}; + Configurable timeShiftCCDBPathPosMC{"timeShiftCCDBPathPosMC", "", "Path of the TOF time shift for MC vs eta for pos. tracks. If empty none is taken"}; + Configurable timeShiftCCDBPathNegMC{"timeShiftCCDBPathNegMC", "", "Path of the TOF time shift for MC vs eta for neg. tracks. If empty none is taken"}; + Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; + Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; + Configurable reconstructionPass{"reconstructionPass", "metadata", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + Configurable reconstructionPassDefault{"reconstructionPassDefault", "unanchored", {"Default pass to get if the standard one is not found"}}; + Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", false, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + Configurable enableTimeDependentResponse{"enableTimeDependentResponse", true, "Flag to use the collision timestamp to fetch the PID Response"}; + Configurable collisionSystem{"collisionSystem", -1, "Collision system: -1 (autoset), 0 (pp), 1 (PbPb), 2 (XeXe), 3 (pPb)"}; + Configurable autoSetProcessFunctions{"autoSetProcessFunctions", true, "Flag to autodetect the process functions to use"}; } ccdbConfigurations; + // Metadata options + struct : ConfigurableGroup { + std::string prefix = "metadata"; + // necessary for TOFResponse when running over derived data (where no metadata can be found) + Configurable overrideMetadata{"overrideMetadata", false, "Override metadataInfo with custom information. Enable when running over derived data"}; + Configurable Run{"Run", "3", "Is it Run 3 ? If yes: 3 ; otherwise: 2"}; + Configurable DataType{"DataType", "Data", "Is it Data? If yes: Data ; otherwise: MC"}; + Configurable AnchorPassName{"AnchorPassName", "apass1", "Anchor pass name (only if needed for DataType = MC)"}; + Configurable RecoPassName{"RecoPassName", "apass1", "Reco pass name (only if needed for DataType = Data)"}; + } metadataConfigurations; + // manual Configurable useCustomRunNumber{"useCustomRunNumber", false, "Use custom timestamp"}; Configurable manualRunNumber{"manualRunNumber", 544122, "manual run number if no collisions saved"}; @@ -290,7 +327,7 @@ struct strangenesstofpid { cosAngle1 /= modulus1; sinAngle1 /= modulus1; length1 = trcCircle.rC * TMath::ACos(cosAngle1); - length1 *= sqrt(1.0f + track.getTgl() * track.getTgl()); + length1 *= std::sqrt(1.0f + track.getTgl() * track.getTgl()); modulus2 = std::hypot(interceptX2 - trcCircle.xC, interceptY2 - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); cosAngle2 = (interceptX2 - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (interceptY2 - trcCircle.yC) * (startPoint[1] - trcCircle.yC); @@ -298,7 +335,7 @@ struct strangenesstofpid { cosAngle2 /= modulus2; sinAngle2 /= modulus2; length2 = trcCircle.rC * TMath::ACos(cosAngle2); - length2 *= sqrt(1.0f + track.getTgl() * track.getTgl()); + length2 *= std::sqrt(1.0f + track.getTgl() * track.getTgl()); // rotate transverse momentum vector such that it is at intercepts float angle1 = TMath::ACos(cosAngle1); @@ -400,6 +437,21 @@ struct strangenesstofpid { } } + if (calculateV0sNSigmaAll.value < 0) { + // check if TOF information is required, enable if so + calculateV0sNSigmaAll.value = isTableRequiredInWorkflow(initContext, "V0TOFNSigmasAll"); + if (calculateV0sNSigmaAll.value > 0) { + LOGF(info, "Strangeness TOF PID: all V0 TOF PID calculations enabled automatically"); + } + } + if (calculateCascadesNSigmaAll.value < 0) { + // check if TOF information is required, enable if so + calculateCascadesNSigmaAll.value = isTableRequiredInWorkflow(initContext, "CascTOFNSigmasAll"); + if (calculateCascadesNSigmaAll.value > 0) { + LOGF(info, "Strangeness TOF PID: all Cascade TOF PID calculations enabled automatically"); + } + } + nSigmaCalibLoaded = false; nSigmaCalibObjects = nullptr; @@ -427,6 +479,17 @@ struct strangenesstofpid { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + LOGF(info, "intializing TOFResponse"); + std::string taskName = initContext.services().get().name; + if (doprocessDerivedData || metadataConfigurations.overrideMetadata) { + LOG(info) << "Overriding metadata info. Run = " << metadataConfigurations.Run.value << " ; DataType = " << metadataConfigurations.DataType.value << " ; AnchorPassName (only if DataType = MC) = " << metadataConfigurations.AnchorPassName.value << " ; RecoPassName (only if DataType = Data) = " << metadataConfigurations.RecoPassName.value; + mTOFResponse->metadataInfo.set("Run", metadataConfigurations.Run.value); + mTOFResponse->metadataInfo.set("DataType", metadataConfigurations.DataType.value); + mTOFResponse->metadataInfo.set("AnchorPassName", metadataConfigurations.AnchorPassName.value); + mTOFResponse->metadataInfo.set("RecoPassName", metadataConfigurations.RecoPassName.value); + } + mTOFResponse->initSetup(ccdb, initContext, taskName); + // per event histos.add("hCandidateCounter", "hCandidateCounter", kTH1F, {{500, -0.5f, 499.5f}}); @@ -447,6 +510,7 @@ struct strangenesstofpid { histos.add("h2dTOFSignalCascadeBachelor", "h2dTOFSignalCascadeBachelor", kTH2F, {axes.axisTimeLong, axes.axisBCshift}); histos.add("hCollisionTimes", "hCollisionTimes", kTH1F, {{2000, -1000.0f, 1000.0f}}); + histos.add("hCollisionTimesError", "hCollisionTimesError", kTH1F, {{2000, -1000.0f, 1000.0f}}); // measured vs expected total time QA if (doQA) { @@ -532,6 +596,8 @@ struct strangenesstofpid { histos.add("h2dNSigmaNegativeLambdaPr", "h2dNSigmaNegativeLambdaPr", {HistType::kTH2F, {axes.axisP, axes.axisNSigma}}); histos.add("h2dNSigmaPositiveK0ShortPi", "h2dNSigmaPositiveK0ShortPi", {HistType::kTH2F, {axes.axisP, axes.axisNSigma}}); histos.add("h2dNSigmaNegativeK0ShortPi", "h2dNSigmaNegativeK0ShortPi", {HistType::kTH2F, {axes.axisP, axes.axisNSigma}}); + histos.add("h2dNSigmaPositivePhotonEl", "h2dNSigmaPositivePhotonEl", {HistType::kTH2F, {axes.axisP, axes.axisNSigma}}); + histos.add("h2dNSigmaNegativePhotonEl", "h2dNSigmaNegativePhotonEl", {HistType::kTH2F, {axes.axisP, axes.axisNSigma}}); } if (calculateCascades.value > 0) { @@ -559,7 +625,7 @@ struct strangenesstofpid { if (propagationConfiguration.d_bz_input > -990) { d_bz = propagationConfiguration.d_bz_input; o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { + if (std::fabs(d_bz) > 1e-5) { grpmag.setL3Current(30000.f / (d_bz / 5.0f)); } o2::base::Propagator::initFieldFromGRP(&grpmag); @@ -587,80 +653,6 @@ struct strangenesstofpid { LOG(info) << "Retrieved GRP for run " << runNumber << " with magnetic field of " << d_bz << " kZG"; } - // if TOF Nsigma desired - if (doNSigmas) { - nSigmaCalibObjects = ccdb->getForRun(ccdbConfigurations.nSigmaPath, runNumber); - if (nSigmaCalibObjects) { - LOGF(info, "loaded TList with this many objects: %i", nSigmaCalibObjects->GetEntries()); - nSigmaCalibLoaded = true; // made it thus far, mark loaded - - if (calculateV0s.value) { - hMeanPosLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosLaPi")); - hMeanPosLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosLaPr")); - hMeanNegLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegLaPi")); - hMeanNegLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegLaPr")); - hMeanPosK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosK0Pi")); - hMeanNegK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegK0Pi")); - - hSigmaPosLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosLaPi")); - hSigmaPosLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosLaPr")); - hSigmaNegLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegLaPi")); - hSigmaNegLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegLaPr")); - hSigmaPosK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosK0Pi")); - hSigmaNegK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegK0Pi")); - - if (!hMeanPosLaPi) - LOG(info) << "Problems finding mean histogram hMeanPosLaPi!"; - if (!hMeanPosLaPr) - LOG(info) << "Problems finding mean histogram hMeanPosLaPr!"; - if (!hMeanNegLaPi) - LOG(info) << "Problems finding mean histogram hMeanNegLaPi!"; - if (!hMeanNegLaPr) - LOG(info) << "Problems finding mean histogram hMeanNegLaPr!"; - if (!hMeanPosK0Pi) - LOG(info) << "Problems finding mean histogram hMeanPosK0Pi!"; - if (!hMeanNegK0Pi) - LOG(info) << "Problems finding mean histogram hMeanNegK0Pi!"; - if (!hSigmaPosK0Pi || !hSigmaNegK0Pi || !hSigmaPosLaPi || !hSigmaPosLaPr || !hSigmaNegLaPi || !hSigmaNegLaPr) { - LOG(info) << "Problems finding sigma histograms!"; - } - } - - if (calculateCascades.value) { - hMeanPosXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosXiPi")); - hMeanPosXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosXiPr")); - hMeanNegXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegXiPi")); - hMeanNegXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegXiPr")); - hMeanBachXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanBachXiPi")); - hMeanPosOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosOmPi")); - hMeanPosOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosOmPr")); - hMeanNegOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegOmPi")); - hMeanNegOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegOmPr")); - hMeanBachOmKa = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanBachOmKa")); - - hSigmaPosXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosXiPi")); - hSigmaPosXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosXiPr")); - hSigmaNegXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegXiPi")); - hSigmaNegXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegXiPr")); - hSigmaBachXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaBachXiPi")); - hSigmaPosOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosOmPi")); - hSigmaPosOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosOmPr")); - hSigmaNegOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegOmPi")); - hSigmaNegOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegOmPr")); - hSigmaBachOmKa = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaBachOmKa")); - - if (!hMeanPosXiPi || !hMeanPosXiPr || !hMeanNegXiPi || !hMeanNegXiPr || !hMeanBachXiPi) - LOG(info) << "Problems finding xi mean histograms!"; - if (!hMeanPosOmPi || !hMeanPosOmPr || !hMeanNegOmPi || !hMeanNegOmPr || !hMeanBachOmKa) - LOG(info) << "Problems finding omega sigma histograms!"; - if (!hSigmaPosXiPi || !hSigmaPosXiPr || !hSigmaNegXiPi || !hSigmaNegXiPr || !hSigmaBachXiPi) - LOG(info) << "Problems finding xi sigma histograms!"; - if (!hSigmaPosOmPi || !hSigmaPosOmPr || !hSigmaNegOmPi || !hSigmaNegOmPr || !hSigmaBachOmKa) - LOG(info) << "Problems finding omega sigma histograms!"; - } - } - } - // if (calculationMethod.value > 0 && !lut) { // // setMatLUT only after magfield has been initalized // // (setMatLUT has implicit and problematic init field call if not) @@ -671,6 +663,82 @@ struct strangenesstofpid { // LOG(info) << "Material look-up table loaded!"; // } mRunNumber = runNumber; + + // if TOF Nsigma desired + if (useNsigmaCalibStrTOF) { + if (doNSigmas) { + nSigmaCalibObjects = ccdb->getForRun(ccdbConfigurations.nSigmaPath, runNumber); + if (nSigmaCalibObjects) { + LOGF(info, "loaded TList with this many objects: %i", nSigmaCalibObjects->GetEntries()); + nSigmaCalibLoaded = true; // made it thus far, mark loaded + + if (calculateV0s.value) { + hMeanPosLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosLaPi")); + hMeanPosLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosLaPr")); + hMeanNegLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegLaPi")); + hMeanNegLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegLaPr")); + hMeanPosK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosK0Pi")); + hMeanNegK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegK0Pi")); + + hSigmaPosLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosLaPi")); + hSigmaPosLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosLaPr")); + hSigmaNegLaPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegLaPi")); + hSigmaNegLaPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegLaPr")); + hSigmaPosK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosK0Pi")); + hSigmaNegK0Pi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegK0Pi")); + + if (!hMeanPosLaPi) + LOG(info) << "Problems finding mean histogram hMeanPosLaPi!"; + if (!hMeanPosLaPr) + LOG(info) << "Problems finding mean histogram hMeanPosLaPr!"; + if (!hMeanNegLaPi) + LOG(info) << "Problems finding mean histogram hMeanNegLaPi!"; + if (!hMeanNegLaPr) + LOG(info) << "Problems finding mean histogram hMeanNegLaPr!"; + if (!hMeanPosK0Pi) + LOG(info) << "Problems finding mean histogram hMeanPosK0Pi!"; + if (!hMeanNegK0Pi) + LOG(info) << "Problems finding mean histogram hMeanNegK0Pi!"; + if (!hSigmaPosK0Pi || !hSigmaNegK0Pi || !hSigmaPosLaPi || !hSigmaPosLaPr || !hSigmaNegLaPi || !hSigmaNegLaPr) { + LOG(info) << "Problems finding sigma histograms!"; + } + } + + if (calculateCascades.value) { + hMeanPosXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosXiPi")); + hMeanPosXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosXiPr")); + hMeanNegXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegXiPi")); + hMeanNegXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegXiPr")); + hMeanBachXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanBachXiPi")); + hMeanPosOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosOmPi")); + hMeanPosOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanPosOmPr")); + hMeanNegOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegOmPi")); + hMeanNegOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanNegOmPr")); + hMeanBachOmKa = reinterpret_cast(nSigmaCalibObjects->FindObject("hMeanBachOmKa")); + + hSigmaPosXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosXiPi")); + hSigmaPosXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosXiPr")); + hSigmaNegXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegXiPi")); + hSigmaNegXiPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegXiPr")); + hSigmaBachXiPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaBachXiPi")); + hSigmaPosOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosOmPi")); + hSigmaPosOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaPosOmPr")); + hSigmaNegOmPi = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegOmPi")); + hSigmaNegOmPr = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaNegOmPr")); + hSigmaBachOmKa = reinterpret_cast(nSigmaCalibObjects->FindObject("hSigmaBachOmKa")); + + if (!hMeanPosXiPi || !hMeanPosXiPr || !hMeanNegXiPi || !hMeanNegXiPr || !hMeanBachXiPi) + LOG(info) << "Problems finding xi mean histograms!"; + if (!hMeanPosOmPi || !hMeanPosOmPr || !hMeanNegOmPi || !hMeanNegOmPr || !hMeanBachOmKa) + LOG(info) << "Problems finding omega sigma histograms!"; + if (!hSigmaPosXiPi || !hSigmaPosXiPr || !hSigmaNegXiPi || !hSigmaNegXiPr || !hSigmaBachXiPi) + LOG(info) << "Problems finding xi sigma histograms!"; + if (!hSigmaPosOmPi || !hSigmaPosOmPr || !hSigmaNegOmPi || !hSigmaNegOmPr || !hSigmaBachOmKa) + LOG(info) << "Problems finding omega sigma histograms!"; + } + } + } + } } float velocity(float lMomentum, float lMass) @@ -685,15 +753,20 @@ struct strangenesstofpid { struct v0TofInfo { // holds processed information regarding TOF for V0s float timeK0Short = o2::aod::v0data::kNoTOFValue; float timeLambda = o2::aod::v0data::kNoTOFValue; + float timePhoton = o2::aod::v0data::kNoTOFValue; float timePositivePr = o2::aod::v0data::kNoTOFValue; float timePositivePi = o2::aod::v0data::kNoTOFValue; + float timePositiveEl = o2::aod::v0data::kNoTOFValue; float timeNegativePr = o2::aod::v0data::kNoTOFValue; float timeNegativePi = o2::aod::v0data::kNoTOFValue; + float timeNegativeEl = o2::aod::v0data::kNoTOFValue; float timeAsPrimaryPositivePr = o2::aod::v0data::kNoTOFValue; float timeAsPrimaryPositivePi = o2::aod::v0data::kNoTOFValue; + float timeAsPrimaryPositiveEl = o2::aod::v0data::kNoTOFValue; float timeAsPrimaryNegativePr = o2::aod::v0data::kNoTOFValue; float timeAsPrimaryNegativePi = o2::aod::v0data::kNoTOFValue; + float timeAsPrimaryNegativeEl = o2::aod::v0data::kNoTOFValue; float deltaTimePositiveLambdaPi = o2::aod::v0data::kNoTOFValue; float deltaTimeNegativeLambdaPi = o2::aod::v0data::kNoTOFValue; @@ -701,6 +774,8 @@ struct strangenesstofpid { float deltaTimeNegativeLambdaPr = o2::aod::v0data::kNoTOFValue; float deltaTimePositiveK0ShortPi = o2::aod::v0data::kNoTOFValue; float deltaTimeNegativeK0ShortPi = o2::aod::v0data::kNoTOFValue; + float deltaTimePositivePhotonEl = o2::aod::v0data::kNoTOFValue; + float deltaTimeNegativePhotonEl = o2::aod::v0data::kNoTOFValue; float nSigmaPositiveLambdaPi = o2::aod::v0data::kNoTOFValue; float nSigmaPositiveLambdaPr = o2::aod::v0data::kNoTOFValue; @@ -708,15 +783,38 @@ struct strangenesstofpid { float nSigmaNegativeLambdaPr = o2::aod::v0data::kNoTOFValue; float nSigmaPositiveK0ShortPi = o2::aod::v0data::kNoTOFValue; float nSigmaNegativeK0ShortPi = o2::aod::v0data::kNoTOFValue; + float nSigmaPositivePhotonEl = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativePhotonEl = o2::aod::v0data::kNoTOFValue; + + // n sigma with wrong hypothesis + float nSigmaPositiveLambdaEl = o2::aod::v0data::kNoTOFValue; + float nSigmaPositiveLambdaKa = o2::aod::v0data::kNoTOFValue; + float nSigmaPositiveK0ShortEl = o2::aod::v0data::kNoTOFValue; + float nSigmaPositiveK0ShortKa = o2::aod::v0data::kNoTOFValue; + float nSigmaPositiveK0ShortPr = o2::aod::v0data::kNoTOFValue; + float nSigmaPositivePhotonPi = o2::aod::v0data::kNoTOFValue; + float nSigmaPositivePhotonKa = o2::aod::v0data::kNoTOFValue; + float nSigmaPositivePhotonPr = o2::aod::v0data::kNoTOFValue; + + float nSigmaNegativeLambdaEl = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativeLambdaKa = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativeK0ShortEl = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativeK0ShortKa = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativeK0ShortPr = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativePhotonPi = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativePhotonKa = o2::aod::v0data::kNoTOFValue; + float nSigmaNegativePhotonPr = o2::aod::v0data::kNoTOFValue; // extra auxiliary variables float deltaDecayTimeLambda = o2::aod::v0data::kNoTOFValue; float deltaDecayTimeAntiLambda = o2::aod::v0data::kNoTOFValue; float deltaDecayTimeK0Short = o2::aod::v0data::kNoTOFValue; + float deltaDecayTimePhoton = o2::aod::v0data::kNoTOFValue; float betaLambda = o2::aod::v0data::kNoTOFValue; float betaAntiLambda = o2::aod::v0data::kNoTOFValue; float betaK0Short = o2::aod::v0data::kNoTOFValue; + float betaPhoton = o2::aod::v0data::kNoTOFValue; }; // structs to hold information @@ -748,6 +846,18 @@ struct strangenesstofpid { float nSigmaOmLaPr = o2::aod::cascdata::kNoTOFValue; float nSigmaOmLaPi = o2::aod::cascdata::kNoTOFValue; float nSigmaOmKa = o2::aod::cascdata::kNoTOFValue; + + // n sigma with wrong hypothesis + float nSigmaXiLaEl = o2::aod::cascdata::kNoTOFValue; + float nSigmaXiLaKa = o2::aod::cascdata::kNoTOFValue; + float nSigmaXiEl = o2::aod::cascdata::kNoTOFValue; + float nSigmaXiKa = o2::aod::cascdata::kNoTOFValue; + float nSigmaXiPr = o2::aod::cascdata::kNoTOFValue; + float nSigmaOmLaEl = o2::aod::cascdata::kNoTOFValue; + float nSigmaOmLaKa = o2::aod::cascdata::kNoTOFValue; + float nSigmaOmEl = o2::aod::cascdata::kNoTOFValue; + float nSigmaOmPi = o2::aod::cascdata::kNoTOFValue; + float nSigmaOmPr = o2::aod::cascdata::kNoTOFValue; }; struct trackTofInfo { // holds input track info @@ -758,9 +868,11 @@ struct strangenesstofpid { float tofExpMom = 0.0f; float tofSignal = 0.0f; float tofEvTime = 0.0f; + float tofEvTimeErr = 0.0f; float length = 0.0f; // save TPC PID here for completeness too + float tpcNSigmaEl = 0.0f; float tpcNSigmaPi = 0.0f; float tpcNSigmaKa = 0.0f; float tpcNSigmaPr = 0.0f; @@ -774,8 +886,8 @@ struct strangenesstofpid { template v0TofInfo calculateTofInfoV0(TCollisions const& collisions, int const& collisionId, TV0 const& v0, TTOFInfo const& pTof, TTOFInfo const& nTof) { - v0TofInfo v0tof; // return this struct - auto collision = collisions.rawIteratorAt(collisionId); + v0TofInfo v0tof; // return this struct + auto collision = collisions.rawIteratorAt(collisionId); // collisionId must be collisionId of V0. //_____________________________________________________________________________________________ // daughter tracks: initialize from V0 position and momenta @@ -787,8 +899,10 @@ struct strangenesstofpid { float lengthV0 = std::hypot(v0.x() - collision.posX(), v0.y() - collision.posY(), v0.z() - collision.posZ()); float velocityK0Short = velocity(v0.p(), o2::constants::physics::MassKaonNeutral); float velocityLambda = velocity(v0.p(), o2::constants::physics::MassLambda); - v0tof.timeK0Short = lengthV0 / velocityK0Short; // in picoseconds - v0tof.timeLambda = lengthV0 / velocityLambda; // in picoseconds + float velocityPhoton = TMath::C() * 1e-12 * 1e+2; // cm/ps + v0tof.timeK0Short = lengthV0 / velocityK0Short; // in picoseconds + v0tof.timeLambda = lengthV0 / velocityLambda; // in picoseconds + v0tof.timePhoton = lengthV0 / velocityPhoton; // in picoseconds //_____________________________________________________________________________________________ // define simple checks @@ -802,21 +916,26 @@ struct strangenesstofpid { bool k0ShortCandidate = std::abs(v0.mK0Short() - o2::constants::physics::MassKaonNeutral) < v0Group.qaMassWindow && std::abs(pTof.tpcNSigmaPi) < v0Group.qaTPCNSigma && std::abs(nTof.tpcNSigmaPi) < v0Group.qaTPCNSigma; + bool photonCandidate = std::abs(v0.mGamma() - o2::constants::physics::MassPhoton) < v0Group.qaMassWindow && + std::abs(pTof.tpcNSigmaEl) < v0Group.qaTPCNSigma && + std::abs(nTof.tpcNSigmaEl) < v0Group.qaTPCNSigma; bool pValidTOF = rejectUndefinedTof.value ? static_cast(std::fabs(pTof.tofSignal) > o2::aod::v0data::kEpsilon) : true; bool nValidTOF = rejectUndefinedTof.value ? static_cast(std::fabs(nTof.tofSignal) > o2::aod::v0data::kEpsilon) : true; //_____________________________________________________________________________________________ // Actual calculation - float velocityPositivePr, velocityPositivePi, lengthPositive; - velocityPositivePr = velocityPositivePi = lengthPositive = o2::aod::v0data::kNoTOFValue; + float velocityPositiveEl, velocityPositivePr, velocityPositivePi, lengthPositive; + velocityPositiveEl = velocityPositivePr = velocityPositivePi = lengthPositive = o2::aod::v0data::kNoTOFValue; if (pTof.hasTOF && pTof.tofEvTime > -1e+5 && pValidTOF) { // method 0: legacy standalone without use of primary particle TOF if (calculationMethod.value == 0) { + velocityPositiveEl = velocity(posTrack.getP(), o2::constants::physics::MassElectron); velocityPositivePr = velocity(posTrack.getP(), o2::constants::physics::MassProton); velocityPositivePi = velocity(posTrack.getP(), o2::constants::physics::MassPionCharged); lengthPositive = findInterceptLength(posTrack, d_bz); + v0tof.timePositiveEl = lengthPositive / velocityPositiveEl; v0tof.timePositivePr = lengthPositive / velocityPositivePr; v0tof.timePositivePi = lengthPositive / velocityPositivePi; } @@ -835,25 +954,56 @@ struct strangenesstofpid { } if (successPropag) { lengthPositive = pTof.length - ltIntegral.getL(); + v0tof.timePositiveEl = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, lengthPositive, o2::constants::physics::MassElectron * o2::constants::physics::MassElectron); v0tof.timePositivePr = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, lengthPositive, o2::constants::physics::MassProton * o2::constants::physics::MassProton); v0tof.timePositivePi = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, lengthPositive, o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged); // as primary + v0tof.timeAsPrimaryPositiveEl = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, pTof.length, o2::constants::physics::MassElectron * o2::constants::physics::MassElectron); v0tof.timeAsPrimaryPositivePr = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, pTof.length, o2::constants::physics::MassProton * o2::constants::physics::MassProton); v0tof.timeAsPrimaryPositivePi = o2::framework::pid::tof::MassToExpTime(pTof.tofExpMom, pTof.length, o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged); } } } if (lengthPositive > 0.0f) { + v0tof.deltaTimePositivePhotonEl = (pTof.tofSignal - pTof.tofEvTime) - (v0tof.timePhoton + v0tof.timePositiveEl); v0tof.deltaTimePositiveLambdaPr = (pTof.tofSignal - pTof.tofEvTime) - (v0tof.timeLambda + v0tof.timePositivePr); v0tof.deltaTimePositiveLambdaPi = (pTof.tofSignal - pTof.tofEvTime) - (v0tof.timeLambda + v0tof.timePositivePi); v0tof.deltaTimePositiveK0ShortPi = (pTof.tofSignal - pTof.tofEvTime) - (v0tof.timeK0Short + v0tof.timePositivePi); - // de facto nsigma - if (nSigmaCalibLoaded) { - v0tof.nSigmaPositiveLambdaPi = (v0tof.deltaTimePositiveLambdaPi - hMeanPosLaPi->Interpolate(v0.p())) / hSigmaPosLaPi->Interpolate(v0.p()); - v0tof.nSigmaPositiveLambdaPr = (v0tof.deltaTimePositiveLambdaPr - hMeanPosLaPr->Interpolate(v0.p())) / hSigmaPosLaPr->Interpolate(v0.p()); - v0tof.nSigmaPositiveK0ShortPi = (v0tof.deltaTimePositiveK0ShortPi - hMeanPosK0Pi->Interpolate(v0.p())) / hSigmaPosK0Pi->Interpolate(v0.p()); + if (useNsigmaCalibStrTOF) { + // de facto nsigma + if (nSigmaCalibLoaded) { + v0tof.nSigmaPositivePhotonEl = -999.; + v0tof.nSigmaPositiveLambdaPi = (v0tof.deltaTimePositiveLambdaPi - hMeanPosLaPi->Interpolate(v0.p())) / hSigmaPosLaPi->Interpolate(v0.p()); + v0tof.nSigmaPositiveLambdaPr = (v0tof.deltaTimePositiveLambdaPr - hMeanPosLaPr->Interpolate(v0.p())) / hSigmaPosLaPr->Interpolate(v0.p()); + v0tof.nSigmaPositiveK0ShortPi = (v0tof.deltaTimePositiveK0ShortPi - hMeanPosK0Pi->Interpolate(v0.p())) / hSigmaPosK0Pi->Interpolate(v0.p()); + // with wrong hypothesis + v0tof.nSigmaPositivePhotonPi = -999.; + v0tof.nSigmaPositivePhotonKa = -999.; + v0tof.nSigmaPositivePhotonPr = -999.; + v0tof.nSigmaPositiveLambdaEl = -999.; + v0tof.nSigmaPositiveLambdaKa = -999.; + v0tof.nSigmaPositiveK0ShortEl = -999.; + v0tof.nSigmaPositiveK0ShortKa = -999.; + v0tof.nSigmaPositiveK0ShortPr = -999.; + } + } else { + // use nSigma function from O2Physics/Common/Core/PID/PIDTOFParamService.h + v0tof.nSigmaPositivePhotonEl = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timePhoton, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveLambdaPi = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeLambda, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveLambdaPr = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeLambda, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveK0ShortPi = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeK0Short, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + + // with wrong hypothesis + v0tof.nSigmaPositivePhotonPi = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timePhoton, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositivePhotonKa = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timePhoton, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositivePhotonPr = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timePhoton, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveLambdaEl = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeLambda, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveLambdaKa = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeLambda, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveK0ShortEl = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeK0Short, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveK0ShortKa = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeK0Short, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + v0tof.nSigmaPositiveK0ShortPr = mTOFResponse->nSigma(pTof.tofSignal - v0tof.timeK0Short, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); } // do QA histograms (calibration / QC) @@ -883,18 +1033,25 @@ struct strangenesstofpid { histos.fill(HIST("h2dNSigmaPositiveK0ShortPi"), v0.pt(), v0tof.nSigmaPositiveK0ShortPi); } } + if (photonCandidate) { + if (doQANSigma && std::fabs(v0tof.nSigmaPositivePhotonEl - o2::aod::v0data::kNoTOFValue) > o2::aod::v0data::kEpsilon) { + histos.fill(HIST("h2dNSigmaPositivePhotonEl"), v0.pt(), v0tof.nSigmaPositivePhotonEl); + } + } } } } } - float velocityNegativePr, velocityNegativePi, lengthNegative; - velocityNegativePr = velocityNegativePi = lengthNegative = o2::aod::v0data::kNoTOFValue; + float velocityNegativeEl, velocityNegativePr, velocityNegativePi, lengthNegative; + velocityNegativeEl = velocityNegativePr = velocityNegativePi = lengthNegative = o2::aod::v0data::kNoTOFValue; if (nTof.hasTOF && nTof.tofEvTime > -1e+5 && nValidTOF) { // method 0: legacy standalone without use of primary particle TOF if (calculationMethod.value == 0) { + velocityNegativeEl = velocity(negTrack.getP(), o2::constants::physics::MassElectron); velocityNegativePr = velocity(negTrack.getP(), o2::constants::physics::MassProton); velocityNegativePi = velocity(negTrack.getP(), o2::constants::physics::MassPionCharged); lengthNegative = findInterceptLength(negTrack, d_bz); + v0tof.timeNegativeEl = lengthNegative / velocityNegativeEl; v0tof.timeNegativePr = lengthNegative / velocityNegativePr; v0tof.timeNegativePi = lengthNegative / velocityNegativePi; } @@ -913,25 +1070,56 @@ struct strangenesstofpid { } if (successPropag) { lengthNegative = nTof.length - ltIntegral.getL(); + v0tof.timeNegativeEl = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, lengthNegative, o2::constants::physics::MassElectron * o2::constants::physics::MassElectron); v0tof.timeNegativePr = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, lengthNegative, o2::constants::physics::MassProton * o2::constants::physics::MassProton); v0tof.timeNegativePi = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, lengthNegative, o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged); // as primary + v0tof.timeAsPrimaryNegativeEl = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, nTof.length, o2::constants::physics::MassElectron * o2::constants::physics::MassElectron); v0tof.timeAsPrimaryNegativePr = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, nTof.length, o2::constants::physics::MassProton * o2::constants::physics::MassProton); v0tof.timeAsPrimaryNegativePi = o2::framework::pid::tof::MassToExpTime(nTof.tofExpMom, nTof.length, o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged); } } } if (lengthNegative > 0.0f) { + v0tof.deltaTimeNegativePhotonEl = (nTof.tofSignal - nTof.tofEvTime) - (v0tof.timePhoton + v0tof.timeNegativeEl); v0tof.deltaTimeNegativeLambdaPr = (nTof.tofSignal - nTof.tofEvTime) - (v0tof.timeLambda + v0tof.timeNegativePr); v0tof.deltaTimeNegativeLambdaPi = (nTof.tofSignal - nTof.tofEvTime) - (v0tof.timeLambda + v0tof.timeNegativePi); v0tof.deltaTimeNegativeK0ShortPi = (nTof.tofSignal - nTof.tofEvTime) - (v0tof.timeK0Short + v0tof.timeNegativePi); - // de facto nsigma - if (nSigmaCalibLoaded) { - v0tof.nSigmaNegativeLambdaPi = (v0tof.deltaTimeNegativeLambdaPi - hMeanNegLaPi->Interpolate(v0.p())) / hSigmaNegLaPi->Interpolate(v0.p()); - v0tof.nSigmaNegativeLambdaPr = (v0tof.deltaTimeNegativeLambdaPr - hMeanNegLaPr->Interpolate(v0.p())) / hSigmaNegLaPr->Interpolate(v0.p()); - v0tof.nSigmaNegativeK0ShortPi = (v0tof.deltaTimeNegativeK0ShortPi - hMeanNegK0Pi->Interpolate(v0.p())) / hSigmaNegK0Pi->Interpolate(v0.p()); + if (useNsigmaCalibStrTOF) { + // de facto nsigma + if (nSigmaCalibLoaded) { + v0tof.nSigmaNegativePhotonEl = -999.; + v0tof.nSigmaNegativeLambdaPi = (v0tof.deltaTimeNegativeLambdaPi - hMeanNegLaPi->Interpolate(v0.p())) / hSigmaNegLaPi->Interpolate(v0.p()); + v0tof.nSigmaNegativeLambdaPr = (v0tof.deltaTimeNegativeLambdaPr - hMeanNegLaPr->Interpolate(v0.p())) / hSigmaNegLaPr->Interpolate(v0.p()); + v0tof.nSigmaNegativeK0ShortPi = (v0tof.deltaTimeNegativeK0ShortPi - hMeanNegK0Pi->Interpolate(v0.p())) / hSigmaNegK0Pi->Interpolate(v0.p()); + // with wrong hypothesis + v0tof.nSigmaNegativePhotonPi = -999.; + v0tof.nSigmaNegativePhotonKa = -999.; + v0tof.nSigmaNegativePhotonPr = -999.; + v0tof.nSigmaNegativeLambdaEl = -999.; + v0tof.nSigmaNegativeLambdaKa = -999.; + v0tof.nSigmaNegativeK0ShortEl = -999.; + v0tof.nSigmaNegativeK0ShortKa = -999.; + v0tof.nSigmaNegativeK0ShortPr = -999.; + } + } else { + // use nSigma function from O2Physics/Common/Core/PID/PIDTOFParamService.h + v0tof.nSigmaNegativePhotonEl = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timePhoton, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeLambdaPi = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeLambda, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeLambdaPr = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeLambda, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeK0ShortPi = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeK0Short, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + + // with wrong hypothesis + v0tof.nSigmaNegativePhotonPi = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timePhoton, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativePhotonKa = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timePhoton, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativePhotonPr = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timePhoton, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeLambdaEl = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeLambda, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeLambdaKa = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeLambda, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeK0ShortEl = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeK0Short, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeK0ShortKa = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeK0Short, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + v0tof.nSigmaNegativeK0ShortPr = mTOFResponse->nSigma(nTof.tofSignal - v0tof.timeK0Short, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); } // do QA histograms (calibration / QC) @@ -961,6 +1149,11 @@ struct strangenesstofpid { histos.fill(HIST("h2dNSigmaNegativeK0ShortPi"), v0.pt(), v0tof.nSigmaNegativeK0ShortPi); } } + if (photonCandidate) { + if (doQANSigma && std::fabs(v0tof.nSigmaNegativePhotonEl - o2::aod::v0data::kNoTOFValue) > o2::aod::v0data::kEpsilon) { + histos.fill(HIST("h2dNSigmaNegativePhotonEl"), v0.pt(), v0tof.nSigmaNegativePhotonEl); + } + } } } } @@ -983,17 +1176,20 @@ struct strangenesstofpid { // } // calculation of delta-decay-time (no reliance on event time) - if (nTof.hasTOF && pTof.hasTOF > 0) { // does not depend on event time + if (nTof.hasTOF && pTof.hasTOF) { // does not depend on event time + v0tof.deltaDecayTimePhoton = (pTof.tofSignal - v0tof.timePositiveEl) - (nTof.tofSignal - v0tof.timeNegativeEl); v0tof.deltaDecayTimeLambda = (pTof.tofSignal - v0tof.timePositivePr) - (nTof.tofSignal - v0tof.timeNegativePi); v0tof.deltaDecayTimeAntiLambda = (pTof.tofSignal - v0tof.timePositivePi) - (nTof.tofSignal - v0tof.timeNegativePr); v0tof.deltaDecayTimeK0Short = (pTof.tofSignal - v0tof.timePositivePi) - (nTof.tofSignal - v0tof.timeNegativePi); float evTimeMean = 0.5f * (pTof.tofEvTime + nTof.tofEvTime); + float decayTimePhoton = 0.5f * ((pTof.tofSignal - v0tof.timePositiveEl) + (nTof.tofSignal - v0tof.timeNegativeEl)) - evTimeMean; float decayTimeLambda = 0.5f * ((pTof.tofSignal - v0tof.timePositivePr) + (nTof.tofSignal - v0tof.timeNegativePi)) - evTimeMean; float decayTimeAntiLambda = 0.5f * ((pTof.tofSignal - v0tof.timePositivePi) + (nTof.tofSignal - v0tof.timeNegativePr)) - evTimeMean; float decayTimeK0Short = 0.5f * ((pTof.tofSignal - v0tof.timePositivePi) + (nTof.tofSignal - v0tof.timeNegativePi)) - evTimeMean; constexpr float lightSpeed = 0.0299792458; // in cm/ps + v0tof.betaPhoton = (lengthV0 / decayTimePhoton) / lightSpeed; v0tof.betaLambda = (lengthV0 / decayTimeLambda) / lightSpeed; v0tof.betaAntiLambda = (lengthV0 / decayTimeAntiLambda) / lightSpeed; v0tof.betaK0Short = (lengthV0 / decayTimeK0Short) / lightSpeed; @@ -1006,8 +1202,8 @@ struct strangenesstofpid { template cascTofInfo calculateTofInfoCascade(TCollisions const& collisions, int const& collisionId, TCascade const& cascade, TTOFInfo const& pTof, TTOFInfo const& nTof, TTOFInfo const& bTof) { - cascTofInfo casctof; // return this struct - auto collision = collisions.rawIteratorAt(collisionId); + cascTofInfo casctof; // return this struct + auto collision = collisions.rawIteratorAt(collisionId); // collisionId must be collisionId of cascade. //_____________________________________________________________________________________________ // daughter tracks: initialize from V0 position and momenta @@ -1041,7 +1237,7 @@ struct strangenesstofpid { // d3d = std::hypot(cascade.x() - cascCloseToPVPosition[0], cascade.y() - cascCloseToPVPosition[1], cascade.z() - cascCloseToPVPosition[2]); // cross-check variable float sinThetaOverTwo = d / (2.0f * trcCircleCascade.rC); lengthCascade = 2.0f * trcCircleCascade.rC * TMath::ASin(sinThetaOverTwo); - lengthCascade *= sqrt(1.0f + cascTrack.getTgl() * cascTrack.getTgl()); + lengthCascade *= std::sqrt(1.0f + cascTrack.getTgl() * cascTrack.getTgl()); } if (!successPropag) { @@ -1123,14 +1319,59 @@ struct strangenesstofpid { casctof.posDeltaTimeAsOmPi = (pTof.tofSignal - pTof.tofEvTime) - (omFlight + lambdaFlight + casctof.posFlightPi); casctof.posDeltaTimeAsOmPr = (pTof.tofSignal - pTof.tofEvTime) - (omFlight + lambdaFlight + casctof.posFlightPr); - // de facto nsigma - if (nSigmaCalibLoaded) { - if (cascade.sign() < 0) { - casctof.nSigmaXiLaPr = (casctof.posDeltaTimeAsXiPr - hMeanPosXiPr->Interpolate(cascade.p())) / hSigmaPosXiPr->Interpolate(cascade.p()); - casctof.nSigmaOmLaPr = (casctof.posDeltaTimeAsOmPr - hMeanPosOmPr->Interpolate(cascade.p())) / hSigmaPosOmPr->Interpolate(cascade.p()); + if (cascade.sign() < 0) { + if (useNsigmaCalibStrTOF) { + if (nSigmaCalibLoaded) { + casctof.nSigmaXiLaPr = (casctof.posDeltaTimeAsXiPr - hMeanPosXiPr->Interpolate(cascade.p())) / hSigmaPosXiPr->Interpolate(cascade.p()); + casctof.nSigmaOmLaPr = (casctof.posDeltaTimeAsOmPr - hMeanPosOmPr->Interpolate(cascade.p())) / hSigmaPosOmPr->Interpolate(cascade.p()); + // wrong hypothesis + casctof.nSigmaXiLaEl = -999.; + casctof.nSigmaXiLaKa = -999.; + casctof.nSigmaXiLaPi = -999.; + + casctof.nSigmaOmLaEl = -999.; + casctof.nSigmaOmLaKa = -999.; + casctof.nSigmaOmLaPi = -999.; + } } else { - casctof.nSigmaXiLaPi = (casctof.posDeltaTimeAsXiPi - hMeanPosXiPi->Interpolate(cascade.p())) / hSigmaPosXiPi->Interpolate(cascade.p()); - casctof.nSigmaOmLaPi = (casctof.posDeltaTimeAsOmPi - hMeanPosOmPi->Interpolate(cascade.p())) / hSigmaPosOmPi->Interpolate(cascade.p()); + casctof.nSigmaXiLaPr = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaPr = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + + // wrong hypothesis + casctof.nSigmaXiLaEl = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaXiLaKa = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaXiLaPi = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + + casctof.nSigmaOmLaEl = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaKa = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaPi = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + } + } else { + if (useNsigmaCalibStrTOF) { + if (nSigmaCalibLoaded) { + casctof.nSigmaXiLaPi = (casctof.posDeltaTimeAsXiPi - hMeanPosXiPi->Interpolate(cascade.p())) / hSigmaPosXiPi->Interpolate(cascade.p()); + casctof.nSigmaOmLaPi = (casctof.posDeltaTimeAsOmPi - hMeanPosOmPi->Interpolate(cascade.p())) / hSigmaPosOmPi->Interpolate(cascade.p()); + // wrong hypothesis + casctof.nSigmaXiLaEl = -999.; + casctof.nSigmaXiLaKa = -999.; + casctof.nSigmaXiLaPi = -999.; + + casctof.nSigmaOmLaEl = -999.; + casctof.nSigmaOmLaKa = -999.; + casctof.nSigmaOmLaPi = -999.; + } + } else { + casctof.nSigmaXiLaPi = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaPi = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + + // wrong hypothesis + casctof.nSigmaXiLaEl = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaXiLaKa = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaXiLaPr = mTOFResponse->nSigma(pTof.tofSignal - xiFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + + casctof.nSigmaOmLaEl = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaKa = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); + casctof.nSigmaOmLaPr = mTOFResponse->nSigma(pTof.tofSignal - omFlight - lambdaFlight, pTof.tofExpMom, lengthPositive, posTrack.getP(), posTrack.getEta(), pTof.tofEvTime, pTof.tofEvTimeErr); } } @@ -1215,14 +1456,59 @@ struct strangenesstofpid { casctof.negDeltaTimeAsOmPi = (nTof.tofSignal - nTof.tofEvTime) - (omFlight + lambdaFlight + casctof.negFlightPi); casctof.negDeltaTimeAsOmPr = (nTof.tofSignal - nTof.tofEvTime) - (omFlight + lambdaFlight + casctof.negFlightPr); - // de facto nsigma - if (nSigmaCalibLoaded) { - if (cascade.sign() < 0) { - casctof.nSigmaXiLaPi = (casctof.negDeltaTimeAsXiPi - hMeanNegXiPi->Interpolate(cascade.p())) / hSigmaNegXiPi->Interpolate(cascade.p()); - casctof.nSigmaOmLaPi = (casctof.negDeltaTimeAsOmPi - hMeanNegOmPi->Interpolate(cascade.p())) / hSigmaNegOmPi->Interpolate(cascade.p()); + if (cascade.sign() < 0) { + if (useNsigmaCalibStrTOF) { + if (nSigmaCalibLoaded) { + casctof.nSigmaXiLaPi = (casctof.negDeltaTimeAsXiPi - hMeanNegXiPi->Interpolate(cascade.p())) / hSigmaNegXiPi->Interpolate(cascade.p()); + casctof.nSigmaOmLaPi = (casctof.negDeltaTimeAsOmPi - hMeanNegOmPi->Interpolate(cascade.p())) / hSigmaNegOmPi->Interpolate(cascade.p()); + // wrong hypothesis + casctof.nSigmaXiLaEl = -999.; + casctof.nSigmaXiLaKa = -999.; + casctof.nSigmaXiLaPi = -999.; + + casctof.nSigmaOmLaEl = -999.; + casctof.nSigmaOmLaKa = -999.; + casctof.nSigmaOmLaPi = -999.; + } + } else { + casctof.nSigmaXiLaPi = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaPi = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + + // wrogn hypothesis + casctof.nSigmaXiLaEl = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaXiLaKa = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaXiLaPr = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + + casctof.nSigmaOmLaEl = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaKa = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaPr = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + } + } else { + if (useNsigmaCalibStrTOF) { + if (nSigmaCalibLoaded) { + casctof.nSigmaXiLaPr = (casctof.negDeltaTimeAsXiPr - hMeanNegXiPr->Interpolate(cascade.p())) / hSigmaNegXiPr->Interpolate(cascade.p()); + casctof.nSigmaOmLaPr = (casctof.negDeltaTimeAsOmPr - hMeanNegOmPr->Interpolate(cascade.p())) / hSigmaNegOmPr->Interpolate(cascade.p()); + // wrong hypothesis + casctof.nSigmaXiLaEl = -999.; + casctof.nSigmaXiLaKa = -999.; + casctof.nSigmaXiLaPi = -999.; + + casctof.nSigmaOmLaEl = -999.; + casctof.nSigmaOmLaKa = -999.; + casctof.nSigmaOmLaPi = -999.; + } } else { - casctof.nSigmaXiLaPr = (casctof.negDeltaTimeAsXiPr - hMeanNegXiPr->Interpolate(cascade.p())) / hSigmaNegXiPr->Interpolate(cascade.p()); - casctof.nSigmaOmLaPr = (casctof.negDeltaTimeAsOmPr - hMeanNegOmPr->Interpolate(cascade.p())) / hSigmaNegOmPr->Interpolate(cascade.p()); + casctof.nSigmaXiLaPr = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaPr = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + + // wrong hypothesis + casctof.nSigmaXiLaEl = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaXiLaKa = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaXiLaPi = mTOFResponse->nSigma(nTof.tofSignal - xiFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + + casctof.nSigmaOmLaEl = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaKa = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); + casctof.nSigmaOmLaPi = mTOFResponse->nSigma(nTof.tofSignal - omFlight - lambdaFlight, nTof.tofExpMom, lengthNegative, negTrack.getP(), negTrack.getEta(), nTof.tofEvTime, nTof.tofEvTimeErr); } } @@ -1305,15 +1591,32 @@ struct strangenesstofpid { casctof.bachDeltaTimeAsXiPi = (bTof.tofSignal - bTof.tofEvTime) - (xiFlight + casctof.bachFlightPi); casctof.bachDeltaTimeAsOmKa = (bTof.tofSignal - bTof.tofEvTime) - (omFlight + casctof.bachFlightKa); - // de facto nsigma - if (nSigmaCalibLoaded) { - if (cascade.sign() < 0) { - casctof.nSigmaXiPi = (casctof.bachDeltaTimeAsXiPi - hMeanBachXiPi->Interpolate(cascade.p())) / hSigmaBachXiPi->Interpolate(cascade.p()); - casctof.nSigmaOmKa = (casctof.bachDeltaTimeAsOmKa - hMeanBachOmKa->Interpolate(cascade.p())) / hSigmaBachOmKa->Interpolate(cascade.p()); - } else { + if (useNsigmaCalibStrTOF) { + if (nSigmaCalibLoaded) { casctof.nSigmaXiPi = (casctof.bachDeltaTimeAsXiPi - hMeanBachXiPi->Interpolate(cascade.p())) / hSigmaBachXiPi->Interpolate(cascade.p()); casctof.nSigmaOmKa = (casctof.bachDeltaTimeAsOmKa - hMeanBachOmKa->Interpolate(cascade.p())) / hSigmaBachOmKa->Interpolate(cascade.p()); + + // wrong hypothesis + casctof.nSigmaXiEl = -999.; + casctof.nSigmaXiKa = -999.; + casctof.nSigmaXiPr = -999.; + + casctof.nSigmaOmEl = -999.; + casctof.nSigmaOmPi = -999.; + casctof.nSigmaOmPr = -999.; } + } else { + casctof.nSigmaXiPi = mTOFResponse->nSigma(bTof.tofSignal - xiFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + casctof.nSigmaOmKa = mTOFResponse->nSigma(bTof.tofSignal - omFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + + // wrong hypothesis + casctof.nSigmaXiEl = mTOFResponse->nSigma(bTof.tofSignal - xiFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + casctof.nSigmaXiKa = mTOFResponse->nSigma(bTof.tofSignal - xiFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + casctof.nSigmaXiPr = mTOFResponse->nSigma(bTof.tofSignal - xiFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + + casctof.nSigmaOmEl = mTOFResponse->nSigma(bTof.tofSignal - omFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + casctof.nSigmaOmPi = mTOFResponse->nSigma(bTof.tofSignal - omFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); + casctof.nSigmaOmPr = mTOFResponse->nSigma(bTof.tofSignal - omFlight, bTof.tofExpMom, lengthBachelor, bachTrack.getP(), bachTrack.getEta(), bTof.tofEvTime, bTof.tofEvTimeErr); } // do QA histograms (calibration / QC) @@ -1360,7 +1663,10 @@ struct strangenesstofpid { return casctof; } - void processStandardData(aod::BCs const& bcs, aod::Collisions const& collisions, V0OriginalDatas const& V0s, CascOriginalDatas const& cascades, TracksWithAllExtras const& tracks, aod::BCsWithTimestamps const& /*bcs*/) + std::unordered_map mapCollisionTime; + std::unordered_map mapCollisionTimeError; + + void processStandardData(/*aod::BCs const& bcs,*/ aod::Collisions const& collisions, V0OriginalDatas const& V0s, CascOriginalDatas const& cascades, TracksWithAllExtras const& tracks, aod::BCsWithTimestamps const& bcs) { // Fire up CCDB with first collision in record. If no collisions, bypass if (useCustomRunNumber || collisions.size() < 1) { @@ -1371,21 +1677,36 @@ struct strangenesstofpid { initCCDB(bc.runNumber()); } + mTOFResponse->processSetup(bcs.iteratorAt(0)); + + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + // LOGF(info, "track.collisionId() = %d, track.tofEvTime() = %f, track.tofEvTimeErr() = %f", track.collisionId(), track.tofEvTime(), track.tofEvTimeErr()); + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + //________________________________________________________________________ // estimate event times (only necessary for original data) std::vector collisionEventTime(collisions.size(), 0.0); + std::vector collisionEventTimeErr(collisions.size(), 0.0); std::vector collisionNtracks(collisions.size(), 0); for (const auto& track : tracks) { - if (track.hasTOF() && track.has_collision()) { + if (track.hasTOF() && track.collisionId() >= 0) { collisionEventTime[track.collisionId()] += track.tofEvTime(); + // Take the average of the error instead of propagating the error as all event time error from tracks are fully correlated + collisionEventTimeErr[track.collisionId()] += track.tofEvTimeErr(); collisionNtracks[track.collisionId()]++; } } for (const auto& collision : collisions) { if (collisionNtracks[collision.globalIndex()] > 0) { collisionEventTime[collision.globalIndex()] /= static_cast(collisionNtracks[collision.globalIndex()]); + collisionEventTimeErr[collision.globalIndex()] /= static_cast(collisionNtracks[collision.globalIndex()]); } else { collisionEventTime[collision.globalIndex()] = -1e+6; // undefined + collisionEventTimeErr[collision.globalIndex()] = -1e+6; // undefined } histos.fill(HIST("hCollisionTimes"), collisionEventTime[collision.globalIndex()]); } @@ -1423,9 +1744,14 @@ struct strangenesstofpid { pTof.hasTPC = pTra.hasTPC(); pTof.hasTOF = pTra.hasTOF(); pTof.tofExpMom = pTra.tofExpMom(); + // pTof.tofEvTime = reassociateTracks ? mapCollisionTime[V0.collisionId()] : pTra.tofEvTime(); + // pTof.tofEvTimeErr = reassociateTracks ? mapCollisionTimeError[V0.collisionId()] : pTra.tofEvTimeErr(); pTof.tofEvTime = reassociateTracks ? collisionEventTime[V0.collisionId()] : pTra.tofEvTime(); - pTof.tofSignal = pTra.tofSignal() + (doBCshift ? deltaTimePos : 0.0f); + pTof.tofEvTimeErr = reassociateTracks ? collisionEventTimeErr[V0.collisionId()] : pTra.tofEvTimeErr(); + // pTof.tofSignal = pTra.tofSignal() + (doBCshift ? deltaTimePos : 0.0f); + pTof.tofSignal = doBCshift && pTra.has_collision() ? pTra.tofSignalInAnotherBC(pTra.collision().bc_as().globalBC(), V0.collision().bc_as().globalBC()) : pTra.tofSignal(); pTof.length = pTra.length(); + pTof.tpcNSigmaEl = pTra.tpcNSigmaEl(); pTof.tpcNSigmaPi = pTra.tpcNSigmaPi(); pTof.tpcNSigmaPr = pTra.tpcNSigmaPr(); @@ -1434,9 +1760,14 @@ struct strangenesstofpid { nTof.hasTPC = nTra.hasTPC(); nTof.hasTOF = nTra.hasTOF(); nTof.tofExpMom = nTra.tofExpMom(); + // nTof.tofEvTime = reassociateTracks ? mapCollisionTime[V0.collisionId()] : nTra.tofEvTime(); + // nTof.tofEvTimeErr = reassociateTracks ? mapCollisionTimeError[V0.collisionId()] : nTra.tofEvTimeErr(); nTof.tofEvTime = reassociateTracks ? collisionEventTime[V0.collisionId()] : nTra.tofEvTime(); - nTof.tofSignal = nTra.tofSignal() + (doBCshift ? deltaTimeNeg : 0.0f); + nTof.tofEvTimeErr = reassociateTracks ? collisionEventTimeErr[V0.collisionId()] : nTra.tofEvTimeErr(); + // nTof.tofSignal = nTra.tofSignal() + (doBCshift ? deltaTimeNeg : 0.0f); + nTof.tofSignal = doBCshift && nTra.has_collision() ? nTra.tofSignalInAnotherBC(nTra.collision().bc_as().globalBC(), V0.collision().bc_as().globalBC()) : nTra.tofSignal(); nTof.length = nTra.length(); + nTof.tpcNSigmaEl = nTra.tpcNSigmaEl(); nTof.tpcNSigmaPi = nTra.tpcNSigmaPi(); nTof.tpcNSigmaPr = nTra.tpcNSigmaPr(); @@ -1457,6 +1788,18 @@ struct strangenesstofpid { v0tof.nSigmaPositiveLambdaPr, v0tof.nSigmaNegativeLambdaPi, v0tof.nSigmaNegativeLambdaPr, v0tof.nSigmaPositiveLambdaPi, v0tof.nSigmaPositiveK0ShortPi, v0tof.nSigmaNegativeK0ShortPi); + + if (calculateV0sNSigmaAll.value > 0) { + v0tofnsigmasall( + v0tof.nSigmaPositivePhotonEl, v0tof.nSigmaPositiveK0ShortEl, v0tof.nSigmaPositiveLambdaEl, + v0tof.nSigmaNegativePhotonEl, v0tof.nSigmaNegativeK0ShortEl, v0tof.nSigmaNegativeLambdaEl, + v0tof.nSigmaPositivePhotonPi, v0tof.nSigmaPositiveK0ShortPi, v0tof.nSigmaPositiveLambdaPi, + v0tof.nSigmaNegativePhotonPi, v0tof.nSigmaNegativeK0ShortPi, v0tof.nSigmaNegativeLambdaPi, + v0tof.nSigmaPositivePhotonKa, v0tof.nSigmaPositiveK0ShortEl, v0tof.nSigmaPositiveLambdaEl, + v0tof.nSigmaNegativePhotonKa, v0tof.nSigmaNegativeK0ShortEl, v0tof.nSigmaNegativeLambdaEl, + v0tof.nSigmaPositivePhotonPr, v0tof.nSigmaPositiveK0ShortPr, v0tof.nSigmaPositiveLambdaPr, + v0tof.nSigmaNegativePhotonPr, v0tof.nSigmaNegativeK0ShortPr, v0tof.nSigmaNegativeLambdaPr); + } } if (calculateV0TOFPIDs.value) { v0tofpid(v0tof.deltaTimePositiveLambdaPi, v0tof.deltaTimePositiveLambdaPr, @@ -1520,7 +1863,9 @@ struct strangenesstofpid { pTof.hasTOF = pTra.hasTOF(); pTof.tofExpMom = pTra.tofExpMom(); pTof.tofEvTime = reassociateTracks ? collisionEventTime[cascade.collisionId()] : pTra.tofEvTime(); - pTof.tofSignal = pTra.tofSignal() + (doBCshift ? deltaTimePos : 0.0f); + pTof.tofEvTimeErr = reassociateTracks ? collisionEventTimeErr[cascade.collisionId()] : pTra.tofEvTimeErr(); + // pTof.tofSignal = pTra.tofSignal() + (doBCshift ? deltaTimePos : 0.0f); + pTof.tofSignal = doBCshift && pTra.has_collision() ? pTra.tofSignalInAnotherBC(pTra.collision().bc_as().globalBC(), cascade.collision().bc_as().globalBC()) : pTra.tofSignal(); pTof.length = pTra.length(); pTof.tpcNSigmaPi = pTra.tpcNSigmaPi(); pTof.tpcNSigmaPr = pTra.tpcNSigmaPr(); @@ -1531,7 +1876,9 @@ struct strangenesstofpid { nTof.hasTOF = nTra.hasTOF(); nTof.tofExpMom = nTra.tofExpMom(); nTof.tofEvTime = reassociateTracks ? collisionEventTime[cascade.collisionId()] : nTra.tofEvTime(); - nTof.tofSignal = nTra.tofSignal() + (doBCshift ? deltaTimeNeg : 0.0f); + nTof.tofEvTimeErr = reassociateTracks ? collisionEventTimeErr[cascade.collisionId()] : nTra.tofEvTimeErr(); + // nTof.tofSignal = nTra.tofSignal() + (doBCshift ? deltaTimeNeg : 0.0f); + nTof.tofSignal = doBCshift && nTra.has_collision() ? nTra.tofSignalInAnotherBC(nTra.collision().bc_as().globalBC(), cascade.collision().bc_as().globalBC()) : nTra.tofSignal(); nTof.length = nTra.length(); nTof.tpcNSigmaPi = nTra.tpcNSigmaPi(); nTof.tpcNSigmaPr = nTra.tpcNSigmaPr(); @@ -1542,7 +1889,9 @@ struct strangenesstofpid { bTof.hasTOF = bTra.hasTOF(); bTof.tofExpMom = bTra.tofExpMom(); bTof.tofEvTime = reassociateTracks ? collisionEventTime[cascade.collisionId()] : bTra.tofEvTime(); - bTof.tofSignal = bTra.tofSignal() + (doBCshift ? deltaTimeBach : 0.0f); + bTof.tofEvTimeErr = reassociateTracks ? collisionEventTimeErr[cascade.collisionId()] : bTra.tofEvTimeErr(); + // bTof.tofSignal = bTra.tofSignal() + (doBCshift ? deltaTimeBach : 0.0f); + bTof.tofSignal = doBCshift && bTra.has_collision() ? bTra.tofSignalInAnotherBC(bTra.collision().bc_as().globalBC(), cascade.collision().bc_as().globalBC()) : bTra.tofSignal(); bTof.length = bTra.length(); bTof.tpcNSigmaPi = bTra.tpcNSigmaPi(); bTof.tpcNSigmaKa = bTra.tpcNSigmaKa(); @@ -1563,6 +1912,14 @@ struct strangenesstofpid { casctofnsigmas( casctof.nSigmaXiLaPi, casctof.nSigmaXiLaPr, casctof.nSigmaXiPi, casctof.nSigmaOmLaPi, casctof.nSigmaOmLaPr, casctof.nSigmaOmKa); + + if (calculateCascadesNSigmaAll.value > 0) { + casctofnsigmasall( + casctof.nSigmaXiLaEl, casctof.nSigmaXiEl, casctof.nSigmaOmLaEl, casctof.nSigmaOmEl, + casctof.nSigmaXiLaPi, casctof.nSigmaXiPi, casctof.nSigmaOmLaPi, casctof.nSigmaOmPi, + casctof.nSigmaXiLaKa, casctof.nSigmaXiKa, casctof.nSigmaOmLaKa, casctof.nSigmaOmKa, + casctof.nSigmaXiLaPr, casctof.nSigmaXiPr, casctof.nSigmaOmLaPr, casctof.nSigmaOmPr); + } } if (calculateCascTOFPIDs.value) { casctofpids( @@ -1573,6 +1930,9 @@ struct strangenesstofpid { } } } + + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); } void processDerivedData(soa::Join const& collisions, V0DerivedDatas const& V0s, CascDerivedDatas const& cascades, dauTracks const& dauTrackTable, aod::DauTrackTOFPIDs const& dauTrackTOFPIDs) @@ -1581,12 +1941,12 @@ struct strangenesstofpid { for (const auto& collision : collisions) { histos.fill(HIST("hCollisionTimes"), collision.eventTime()); + histos.fill(HIST("hCollisionTimesError"), collision.eventTimeErr()); } // auto-determine if using old format if (dauTrackTOFPIDs.size() != 0) { - auto firstTOFPID = dauTrackTOFPIDs.rawIteratorAt(0); - isNewTOFFormat = firstTOFPID.straCollisionId() < 0 ? false : true; + isNewTOFFormat = dauTrackTable.size() == dauTrackTOFPIDs.size() ? false : true; } if (!isNewTOFFormat && calculationMethod.value > 0) { @@ -1645,6 +2005,8 @@ struct strangenesstofpid { pTof.collisionId = pTofExt.straCollisionId(); pTof.tofExpMom = pTofExt.tofExpMom(); pTof.tofEvTime = reassociateTracks.value ? collision.eventTime() : pTofExt.tofEvTime(); + pTof.tofEvTimeErr = reassociateTracks.value ? collision.eventTimeErr() : pTofExt.tofEvTimeErr(); + // pTof.tofEvTimeErr = pTofExt.tofEvTimeErr(); pTof.tofSignal = pTofExt.tofSignal() + (doBCshift.value ? deltaTimeBc : 0.0f); pTof.length = pTofExt.length(); } @@ -1670,6 +2032,8 @@ struct strangenesstofpid { nTof.collisionId = nTofExt.straCollisionId(); nTof.tofExpMom = nTofExt.tofExpMom(); nTof.tofEvTime = reassociateTracks.value ? collision.eventTime() : nTofExt.tofEvTime(); + nTof.tofEvTimeErr = reassociateTracks.value ? collision.eventTimeErr() : nTofExt.tofEvTimeErr(); + // nTof.tofEvTimeErr = nTofExt.tofEvTimeErr(); nTof.tofSignal = nTofExt.tofSignal() + (doBCshift.value ? deltaTimeBc : 0.0f); nTof.length = nTofExt.length(); } @@ -1737,6 +2101,8 @@ struct strangenesstofpid { pTof.collisionId = pTofExt.straCollisionId(); pTof.tofExpMom = pTofExt.tofExpMom(); pTof.tofEvTime = reassociateTracks.value ? collision.eventTime() : pTofExt.tofEvTime(); + pTof.tofEvTimeErr = reassociateTracks.value ? collision.eventTimeErr() : pTofExt.tofEvTimeErr(); + // pTof.tofEvTimeErr = pTofExt.tofEvTimeErr(); pTof.tofSignal = pTofExt.tofSignal() + (doBCshift.value ? deltaTimeBc : 0.0f); pTof.length = pTofExt.length(); } @@ -1761,6 +2127,8 @@ struct strangenesstofpid { nTof.collisionId = nTofExt.straCollisionId(); nTof.tofExpMom = nTofExt.tofExpMom(); nTof.tofEvTime = reassociateTracks.value ? collision.eventTime() : nTofExt.tofEvTime(); + nTof.tofEvTimeErr = reassociateTracks.value ? collision.eventTime() : nTofExt.tofEvTimeErr(); + // nTof.tofEvTimeErr = nTofExt.tofEvTimeErr(); nTof.tofSignal = nTofExt.tofSignal() + (doBCshift.value ? deltaTimeBc : 0.0f); nTof.length = nTofExt.length(); } @@ -1785,6 +2153,8 @@ struct strangenesstofpid { bTof.collisionId = bTofExt.straCollisionId(); bTof.tofExpMom = bTofExt.tofExpMom(); bTof.tofEvTime = reassociateTracks.value ? collision.eventTime() : bTofExt.tofEvTime(); + bTof.tofEvTimeErr = reassociateTracks.value ? collision.eventTimeErr() : bTofExt.tofEvTimeErr(); + // bTof.tofEvTimeErr = bTofExt.tofEvTimeErr(); bTof.tofSignal = bTofExt.tofSignal() + (doBCshift.value ? deltaTimeBc : 0.0f); bTof.length = bTofExt.length(); } @@ -1814,6 +2184,7 @@ struct strangenesstofpid { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); return WorkflowSpec{ adaptAnalysisTask(cfgc)}; } From d0aac9cc76ddd331e3a5a95d2f214b11036c1e90 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Mon, 1 Jun 2026 11:09:23 +0200 Subject: [PATCH 369/449] [PWGDQ] add efficiency type for random plane test (#16481) Co-authored-by: ALICE Action Bot --- PWGDQ/Core/VarManager.cxx | 20 ++++++++++++++++++++ PWGDQ/Core/VarManager.h | 1 + 2 files changed, 21 insertions(+) diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index f9c0105dbd5..cf3c7a4b1b2 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -427,6 +427,26 @@ void VarManager::FillEfficiency(float* values) // get the efficiency value from the histogram values[kPairEfficiency] = efficiencyHist->GetBinContent(binPt, binCent, binCosThetaStarFT0c); values[kPairWeight] = 1.0 / (values[kPairEfficiency] > 0 ? values[kPairEfficiency] : 1.0); // set the weight as the inverse of the efficiency, but avoid division by zero + } else if (fgEfficiencyType == kPairPtCentFT0cCosThetaStarRandom) { + if (!fgEfficiencyHist) { + LOG(fatal) << "efficiency histogram not set"; + return; + } + TH3F* efficiencyHist = reinterpret_cast(fgEfficiencyHist); + // Get the bin indices for the efficiency histogram + int binPt = efficiencyHist->GetXaxis()->FindBin(values[kPt]); + binPt = (binPt == 0 ? 1 : binPt); + binPt = (binPt > efficiencyHist->GetXaxis()->GetNbins() ? efficiencyHist->GetXaxis()->GetNbins() : binPt); + int binCent = efficiencyHist->GetYaxis()->FindBin(values[kCentFT0C]); + binCent = (binCent == 0 ? 1 : binCent); + binCent = (binCent > efficiencyHist->GetYaxis()->GetNbins() ? efficiencyHist->GetYaxis()->GetNbins() : binCent); + int binCosThetaStarRandom = efficiencyHist->GetZaxis()->FindBin(values[kCosThetaStarRandom]); + binCosThetaStarRandom = (binCosThetaStarRandom == 0 ? 1 : binCosThetaStarRandom); + binCosThetaStarRandom = (binCosThetaStarRandom > efficiencyHist->GetZaxis()->GetNbins() ? efficiencyHist->GetZaxis()->GetNbins() : binCosThetaStarRandom); + + // get the efficiency value from the histogram + values[kPairEfficiency] = efficiencyHist->GetBinContent(binPt, binCent, binCosThetaStarRandom); + values[kPairWeight] = 1.0 / (values[kPairEfficiency] > 0 ? values[kPairEfficiency] : 1.0); // set the weight as the inverse of the efficiency, but avoid division by zero } else { LOG(warning) << "FillEfficiency: unknown efficiency type " << fgEfficiencyType << ", using default efficiency = 1"; values[kPairEfficiency] = 1; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 7dfb955aaa6..453c0e65860 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1130,6 +1130,7 @@ class VarManager : public TObject enum EfficiencyType { kNone = 0, kPairPtCentFT0cCosThetaStarFT0c, + kPairPtCentFT0cCosThetaStarRandom, // Add more efficiency types as needed kNEfficiencyTypes }; From 6a04ab6b6b36388c55c5912910f2058778dd8535 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 1 Jun 2026 11:22:12 +0200 Subject: [PATCH 370/449] [PWGEM/Dilepton] add hTPCdEdxMC (#16480) --- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 18c35af06ab..746cc1eb84e 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -333,6 +333,7 @@ struct SingleTrackQCMC { if (cfgFillQA) { fRegistry.add("Track/PID/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/PID/positive/hTPCdEdxMC", "TPC dE/dx MC;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/PID/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); // fRegistry.add("Track/PID/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/PID/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", o2::framework::HistType::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); @@ -684,6 +685,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); fRegistry.fill(HIST("Track/PID/positive/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/PID/positive/hTPCdEdxMC"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Track/PID/positive/hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/PID/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/positive/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); @@ -730,6 +732,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); fRegistry.fill(HIST("Track/PID/negative/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/PID/negative/hTPCdEdxMC"), track.tpcInnerParam(), track.mcTunedTPCSignal()); fRegistry.fill(HIST("Track/PID/negative/hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/PID/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/negative/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); From 048e92bc0b0ef8d2f6014aabebc7fcb23c11b7cd Mon Sep 17 00:00:00 2001 From: swapneshkhade <107178389+swapneshkhade@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:05:11 +0530 Subject: [PATCH 371/449] [PWGHF] add offline event mixing tables for MC reco and MC gen (#16479) --- .../HFC/TableProducer/correlatorD0Hadrons.cxx | 124 +++++++++++++++++- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index 23161549f4f..d5e8a924fc8 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -266,6 +266,9 @@ struct HfCorrelatorD0Hadrons { ConfigurableAxis binsPosZ{"binsPosZ", {100, -10., 10.}, "primary vertex z coordinate"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; ConfigurableAxis binsCentFt0m{"binsCentFt0m", {100, 0., 100.}, "Centrality percentile (FT0M)"}; + ConfigurableAxis binsBdtScoreBkg{"binsBdtScoreBkg", {500, 0., 1.}, "Bdt score background"}; + ConfigurableAxis binsBdtScorePrompt{"binsBdtScorePrompt", {200, 0., 1.}, "Bdt score prompt"}; + ConfigurableAxis binsBdtScoreNonPrompt{"binsBdtScoreNonPrompt", {200, 0., 1.}, "Bdt score non-prompt"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -285,9 +288,9 @@ struct HfCorrelatorD0Hadrons { AxisSpec const axisSignalStatus = {200, 0., 200., "Signal status"}; AxisSpec axisEvtCount = {1, -0.5, 0.5}; AxisSpec const axisTrkCount = {5, 0., 5.}; - AxisSpec axisBdtScoreBkg = {500, 0., 1., "Bdt score background"}; - AxisSpec axisBdtScorePrompt = {200, 0., 1., "Bdt score prompt"}; - AxisSpec axisBdtScoreNonPrompt = {200, 0., 1., "Bdt score Nonprompt"}; + AxisSpec axisBdtScoreBkg = {binsBdtScoreBkg, "Bdt score background"}; + AxisSpec axisBdtScorePrompt = {binsBdtScorePrompt, "Bdt score prompt"}; + AxisSpec axisBdtScoreNonPrompt = {binsBdtScoreNonPrompt, "Bdt score Nonprompt"}; AxisSpec axisOrigin = {10, 0., 10., "Candidate origin"}; AxisSpec axisCent = {binsCentFt0m, "Centrality"}; @@ -322,9 +325,11 @@ struct HfCorrelatorD0Hadrons { registry.add("hYRec", "D0,D0bar candidates - MC reco", {HistType::kTH1F, {axisRapidity}}); registry.add("hMassD0RecSig", "D0 signal candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0RecRef", "D0 reflection candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassD0RecRefAfterRejectBoth", "D0 reflection candidates after rejecting D0 and D0bar candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0RecBg", "D0 background candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0barRecSig", "D0bar signal candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0barRecRef", "D0bar reflection candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassD0barRecRefAfterRejectBoth", "D0bar reflection candidates after rejecting D0 and D0bar candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0barRecBg", "D0bar background candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hPtCandRecSigPrompt", "D0,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); registry.add("hPtVsMLScoresVsEtaRecSigPrompt", "Prompt D0-D0bar signal candidates MLVsPtVsEta - MC reco", {HistType::kTHnSparseD, {{axisBdtScoreBkg}, {axisBdtScorePrompt}, {axisBdtScoreNonPrompt}, {axisPtD}, {axisEta}}}); @@ -583,9 +588,15 @@ struct HfCorrelatorD0Hadrons { void processMcRec(SelectedCollisions::iterator const& collision, SelectedTracksMcRec const& tracks, SelectedCandidatesMcRecMl const& candidates, - aod::McParticles const& mcParticles) + aod::McParticles const& mcParticles, + aod::BCsWithTimestamps const&) { BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; + + auto bc = collision.bc_as(); + int gCollisionId = collision.globalIndex(); + int64_t timeStamp = bc.timestamp(); + // find leading particle if (correlateD0WithLeadingParticle) { leadingIndex = findLeadingParticle(tracks, etaTrackMax.value); @@ -625,6 +636,30 @@ struct HfCorrelatorD0Hadrons { std::vector outputMlD0 = {-1., -1., -1.}; std::vector outputMlD0bar = {-1., -1., -1.}; + std::vector softPionTrackIdsForOfflineMixing; + std::vector softPionStatusesForOfflineMixing; + bool hasAcceptedD0ForOfflineMixing = false; + + auto addSoftPionTrackForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId, int softPiStatus) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + softPionStatusesForOfflineMixing[iTrack] |= softPiStatus; + return; + } + } + softPionTrackIdsForOfflineMixing.push_back(trackId); + softPionStatusesForOfflineMixing.push_back(softPiStatus); + }; + + auto getSoftPionStatusForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + return softPionStatusesForOfflineMixing[iTrack]; + } + } + return static_cast(aod::hf_d0_assoc_tracks::NotSoftPi); + }; + for (const auto& candidate : candidates) { bool isD0Prompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; bool isD0NonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; @@ -646,6 +681,10 @@ struct HfCorrelatorD0Hadrons { const auto invMassD0 = HfHelper::invMassD0ToPiK(candidate); const auto invMassD0bar = HfHelper::invMassD0barToKPi(candidate); + if (candidate.isSelD0() >= selectionFlagD0 || candidate.isSelD0bar() >= selectionFlagD0bar) { + hasAcceptedD0ForOfflineMixing = true; + } + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandRec"), candidate.pt()); @@ -671,6 +710,9 @@ struct HfCorrelatorD0Hadrons { } } else if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0RecRef"), invMassD0, candidate.pt(), efficiencyWeight); + if (candidate.isSelD0bar() < selectionFlagD0bar) { + registry.fill(HIST("hMassD0RecRefAfterRejectBoth"), invMassD0, candidate.pt(), efficiencyWeight); + } } else { registry.fill(HIST("hMassD0RecBg"), invMassD0, candidate.pt(), efficiencyWeight); } @@ -678,6 +720,7 @@ struct HfCorrelatorD0Hadrons { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); + entryD0(candidate.phi(), candidate.eta(), candidate.pt(), invMassD0, poolBin, gCollisionId, timeStamp, (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar @@ -693,6 +736,9 @@ struct HfCorrelatorD0Hadrons { } } else if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0barRecRef"), invMassD0bar, candidate.pt(), efficiencyWeight); + if (candidate.isSelD0() < selectionFlagD0) { + registry.fill(HIST("hMassD0barRecRefAfterRejectBoth"), invMassD0bar, candidate.pt(), efficiencyWeight); + } } else { registry.fill(HIST("hMassD0barRecBg"), invMassD0bar, candidate.pt(), efficiencyWeight); } @@ -700,6 +746,7 @@ struct HfCorrelatorD0Hadrons { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); + entryD0(candidate.phi(), candidate.eta(), candidate.pt(), invMassD0bar, poolBin, gCollisionId, timeStamp, (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); entryD0CandGenInfo(isD0Prompt); @@ -740,12 +787,14 @@ struct HfCorrelatorD0Hadrons { if (candidate.isSelD0() >= selectionFlagD0) { if ((std::abs(invMassDstar1 - invMassD0) - softPiMass) < ptSoftPionMax) { + addSoftPionTrackForOfflineMixing(track.globalIndex(), aod::hf_d0_assoc_tracks::SoftPiD0); continue; } } if (candidate.isSelD0bar() >= selectionFlagD0bar) { if ((std::abs(invMassDstar2 - invMassD0bar) - softPiMass) < ptSoftPionMax) { + addSoftPionTrackForOfflineMixing(track.globalIndex(), aod::hf_d0_assoc_tracks::SoftPiD0bar); continue; } } @@ -806,6 +855,20 @@ struct HfCorrelatorD0Hadrons { entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); } // end inner loop (Tracks) } // end of outer loop (D0) + + // loop to save tables for offline event mixing + if (hasAcceptedD0ForOfflineMixing) { + for (const auto& track : tracks) { + const auto softPiStatus = getSoftPionStatusForOfflineMixing(track.globalIndex()); + + registry.fill(HIST("hTracksBeforeSoftMix"), track.pt()); + if (softPiStatus == aod::hf_d0_assoc_tracks::NotSoftPi) { + registry.fill(HIST("hTracksAfterSoftMix"), track.pt()); + } + + entryD0Hadron(track.phi(), track.eta(), track.pt(), poolBin, gCollisionId, timeStamp, softPiStatus); + } + } } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcRec, "Process MC Reco mode", true); @@ -817,6 +880,8 @@ struct HfCorrelatorD0Hadrons { { BinningTypeMcGen const corrBinningMcGen{{zPoolBins, multPoolBinsMcGen}, true}; int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); + int gCollisionId = mcCollision.globalIndex(); + int64_t timeStamp = 0; registry.fill(HIST("hCollisionPoolBin"), poolBin); registry.fill(HIST("hEvtCountGen"), 0); // MC gen level @@ -828,6 +893,29 @@ struct HfCorrelatorD0Hadrons { bool isD0NonPrompt = false; int trackOrigin = -1; float cent = 100.; // Centrality Placeholder: will be updated later + std::vector softPionTrackIdsForOfflineMixing; + std::vector softPionStatusesForOfflineMixing; + bool hasAcceptedD0ForOfflineMixing = false; + + auto addSoftPionTrackForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId, int softPiStatus) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + softPionStatusesForOfflineMixing[iTrack] |= softPiStatus; + return; + } + } + softPionTrackIdsForOfflineMixing.push_back(trackId); + softPionStatusesForOfflineMixing.push_back(softPiStatus); + }; + + auto getSoftPionStatusForOfflineMixing = [&softPionTrackIdsForOfflineMixing, &softPionStatusesForOfflineMixing](int64_t trackId) { + for (auto iTrack = 0u; iTrack < softPionTrackIdsForOfflineMixing.size(); ++iTrack) { + if (softPionTrackIdsForOfflineMixing[iTrack] == trackId) { + return softPionStatusesForOfflineMixing[iTrack]; + } + } + return static_cast(aod::hf_d0_assoc_tracks::NotSoftPi); + }; for (const auto& particleTrigg : mcParticles) { if (std::abs(particleTrigg.pdgCode()) != Pdg::kD0) { @@ -841,6 +929,7 @@ struct HfCorrelatorD0Hadrons { if (ptCandMin >= 0. && particleTrigg.pt() < ptCandMin) { continue; } + hasAcceptedD0ForOfflineMixing = true; registry.fill(HIST("hD0PoolBin"), poolBin); registry.fill(HIST("hPtCandGen"), particleTrigg.pt()); @@ -860,6 +949,7 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hPtCandGenNonPrompt"), particleTrigg.pt()); registry.fill(HIST("hPtVsEtaCandGenSigNonPrompt"), particleTrigg.pt(), particleTrigg.eta()); } + entryD0(particleTrigg.phi(), particleTrigg.eta(), particleTrigg.pt(), MassD0, poolBin, gCollisionId, timeStamp, (particleTrigg.pdgCode() == Pdg::kD0) ? o2::aod::hf_correlation_d0_hadron::D0Only : o2::aod::hf_correlation_d0_hadron::D0barOnly); // =============== D-h correlation dedicated section ===================== for (const auto& particleAssoc : mcParticles) { @@ -884,6 +974,7 @@ struct HfCorrelatorD0Hadrons { auto indexMotherD0 = RecoDecay::getMother(mcParticles, particleTrigg, Pdg::kDStar, true, nullptr, 1); bool correlationStatus = false; if (std::abs(particleAssoc.pdgCode()) == kPiPlus && indexMotherPi >= 0 && indexMotherD0 >= 0 && indexMotherPi == indexMotherD0) { + addSoftPionTrackForOfflineMixing(particleAssoc.globalIndex(), (particleTrigg.pdgCode() == Pdg::kD0) ? aod::hf_d0_assoc_tracks::SoftPiD0 : aod::hf_d0_assoc_tracks::SoftPiD0bar); if (!storeAutoCorrelationFlag) { continue; } @@ -911,6 +1002,31 @@ struct HfCorrelatorD0Hadrons { } // end inner loop (Tracks) } } // end outer loop (D0) + + if (hasAcceptedD0ForOfflineMixing) { + for (const auto& particleAssoc : mcParticles) { + if (std::abs(particleAssoc.eta()) > etaTrackMax) { + continue; + } + if (particleAssoc.pt() < ptTrackMin) { + continue; + } + if ((std::abs(particleAssoc.pdgCode()) != kElectron) && (std::abs(particleAssoc.pdgCode()) != kMuonMinus) && (std::abs(particleAssoc.pdgCode()) != kPiPlus) && (std::abs(particleAssoc.pdgCode()) != kKPlus) && (std::abs(particleAssoc.pdgCode()) != kProton)) { + continue; + } + if (!particleAssoc.isPhysicalPrimary()) { + continue; + } + const auto softPiStatus = getSoftPionStatusForOfflineMixing(particleAssoc.globalIndex()); + + registry.fill(HIST("hTracksBeforeSoftMix"), particleAssoc.pt()); + if (softPiStatus == aod::hf_d0_assoc_tracks::NotSoftPi) { + registry.fill(HIST("hTracksAfterSoftMix"), particleAssoc.pt()); + } + + entryD0Hadron(particleAssoc.phi(), particleAssoc.eta(), particleAssoc.pt(), poolBin, gCollisionId, timeStamp, softPiStatus); + } + } } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcGen, "Process MC Gen mode", false); From 971106e6c2930551f977fad3f3d6db4f58830fd4 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Mon, 1 Jun 2026 13:46:00 +0200 Subject: [PATCH 372/449] [PWGCF] Update in femto framework (#16483) --- PWGCF/Femto/Core/collisionBuilder.h | 31 ++++++++++----------- PWGCF/Femto/TableProducer/femtoProducer.cxx | 8 +++--- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 19fb00b8abe..74307f62f13 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -569,23 +569,22 @@ class CollisionBuilder if (mProducedSphericities) { collisionProducts.producedSphericities(mCollisionSelection.getSphericity()); } - if (mProducedMultiplicities) { - collisionProducts.producedMultiplicityEstimators( - col.multFT0A(), - col.multFT0C(), - col.multNTracksPVeta1(), - col.multNTracksPVetaHalf(), - col.trackOccupancyInTimeRange(), - col.ft0cOccupancyInTimeRange()); - } - if (mProducedCentralities) { - collisionProducts.producedCentralityEstimators( - col.centFT0A(), - col.centFT0C()); - } - + // TODO: enable later for better QA + // if (mProducedMultiplicities) { + // collisionProducts.producedMultiplicityEstimators( + // col.multFT0A(), + // col.multFT0C(), + // col.multNTracksPVeta1(), + // col.multNTracksPVetaHalf(), + // col.trackOccupancyInTimeRange(), + // col.ft0cOccupancyInTimeRange()); + // } + // if (mProducedCentralities) { + // collisionProducts.producedCentralityEstimators( + // col.centFT0A(), + // col.centFT0C()); + // } // PbPb specific columns - // TODO: enable later update // if constexpr (modes::isFlagSet(system, modes::System::kPbPb)) { // if (mProduceQns) { // collisionProducts.producedQns(utils::qn(col)); diff --git a/PWGCF/Femto/TableProducer/femtoProducer.cxx b/PWGCF/Femto/TableProducer/femtoProducer.cxx index 3f1bef7f42f..bf18ec255bd 100644 --- a/PWGCF/Femto/TableProducer/femtoProducer.cxx +++ b/PWGCF/Femto/TableProducer/femtoProducer.cxx @@ -52,14 +52,14 @@ namespace o2::analysis::femto { namespace consumeddata { -using Run3PpCollisions = o2::soa::Join; +using Run3PpCollisions = o2::soa::Join; using Run3PpMcRecoCollisions = o2::soa::Join; -using Run3PpMcGenCollisions = o2::soa::Join; +using Run3PpMcGenCollisions = o2::soa::Join; -using Run3PbPbCollisions = o2::soa::Join; +using Run3PbPbCollisions = o2::soa::Join; using Run3PbPbMcRecoCollisions = o2::soa::Join; -using Run3PbPbMcGenCollisions = o2::soa::Join; +using Run3PbPbMcGenCollisions = o2::soa::Join; using Run3FullPidTracks = soa::Join Date: Mon, 1 Jun 2026 15:51:56 +0200 Subject: [PATCH 373/449] [DPG] Fix includes (#16409) --- DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx | 5 +++++ DPG/Tasks/FIT/fitAll.cxx | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx index 58438690781..7e4cb37c9ef 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx @@ -24,8 +24,13 @@ #include #include #include +#include #include +#include #include +#include +#include +#include #include #include diff --git a/DPG/Tasks/FIT/fitAll.cxx b/DPG/Tasks/FIT/fitAll.cxx index 63b6c630230..48084c73e94 100644 --- a/DPG/Tasks/FIT/fitAll.cxx +++ b/DPG/Tasks/FIT/fitAll.cxx @@ -18,13 +18,16 @@ #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include #include #include +#include #include +#include #include -#include - +#include +#include #include #include #include From 8ceaac1d4aa75ce46b2f0bce0e5d46697ac06fee Mon Sep 17 00:00:00 2001 From: lauraser <45659867+lauraser@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:12:31 +0200 Subject: [PATCH 374/449] =?UTF-8?q?[Infrastructure]=20Adding=20rights=20fo?= =?UTF-8?q?r=20the=20new=20PWG-CF=20convener=20(me)=20and=20new=20femtosco?= =?UTF-8?q?py=20PAG=E2=80=A6=20(#16488)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CODEOWNERS | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 23e54377bb6..87f1d20c1e2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -31,23 +31,23 @@ /EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @raymondEhlers @mpuccio @lietava @fgrosa @ariedel-cern /EventFiltering/PWGEM @alibuild @dsekihat @nstrangm @mpuccio @lietava @fgrosa @ariedel-cern -/PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye -/PWGCF/Core @alibuild @jgrosseo -/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye -/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye -/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye -/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye -/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye -/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye -/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye -/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye -/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye -/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye -/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye -/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye -/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye -/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye -/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @otonvd @shouqiye +/PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/Core @alibuild @jgrosseo @lauraser +/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN +/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN +/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN +/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN +/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN +/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @otonvd @shouqiye @lauraser /PWGDQ @alibuild @iarsene @mcoquet642 @lucamicheletti93 @XiaozhiBai /PWGEM @alibuild @feisenhu @dsekihat @jokonig @hscheid From 4a5a9f3be34f6cd4cb95f86bad776f3abd827d2a Mon Sep 17 00:00:00 2001 From: Jseo <47848181+JinjooSeo@users.noreply.github.com> Date: Mon, 1 Jun 2026 16:14:15 +0200 Subject: [PATCH 375/449] [PWGDQ] add process for multExtra without Qvector (#16485) --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index ecd68a04327..c1048c21c2c 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -222,6 +222,7 @@ DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", // Declarations of various short names using MyEvents = soa::Join; using MyEventsBasic = soa::Join; +using MyEventsMultExtraNoQvector = soa::Join; using MyEventsMultExtra = soa::Join; using MyEventsMultExtraQVector = soa::Join; using MyEventsZdc = soa::Join; @@ -337,7 +338,7 @@ struct AnalysisEventSelection { void init(o2::framework::InitContext& context) { - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedBasic") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); + bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedBasic") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraNoQvector") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); bool isDummyEnabled = context.mOptions.get("processDummy"); if (isDummyEnabled) { @@ -579,6 +580,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedWithMultExtraNoQvector(MyEventsMultExtraNoQvector const& events) + { + runEventSelection(events); + publishSelections(events); + } void processSkimmedWithMultExtraZdc(MyEventsMultExtraZdc const& events) { runEventSelection(events); @@ -616,6 +622,7 @@ struct AnalysisEventSelection { PROCESS_SWITCH(AnalysisEventSelection, processSkimmedBasic, "Run event selection on DQ skimmed events with basic tables", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithZdc, "Run event selection on DQ skimmed events, with ZDC", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtra, "Run event selection on DQ skimmed events, with mult extra", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraNoQvector, "Run event selection on DQ skimmed events, with mult extra and without Q-vector", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraZdc, "Run event selection on DQ skimmed events, with mult extra and ZDC", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraZdcFit, "Run event selection on DQ skimmed events, with mult extra, ZDC and FIT", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithQvectorCentr, "Run event selection on DQ skimmed events, with Q-vector", false); From b42c8a817068fc8b6ad5828f67ac6fc39ac591e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Mart=C3=ADnez=20Garc=C3=ADa?= Date: Mon, 1 Jun 2026 08:53:56 -0600 Subject: [PATCH 376/449] [PWGUD] Adding PID checks (#16443) Co-authored-by: rolavick --- PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx | 116 +++++++++++++++++---- 1 file changed, 96 insertions(+), 20 deletions(-) diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index 0ae2035f93a..25b8213263e 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -50,7 +50,7 @@ namespace tree DECLARE_SOA_COLUMN(GapSide, gapSide, float); DECLARE_SOA_COLUMN(GapSideTimeZN, gapSideTimeZN, float); DECLARE_SOA_COLUMN(Sbp, sbp, int); -DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); +DECLARE_SOA_COLUMN(ItsRofB, itsRofB, int); DECLARE_SOA_COLUMN(VtxITSTPCCut, vtxITSTPCCut, int); DECLARE_SOA_COLUMN(ZVtxFT0vsPvCut, zVtxFT0vsPvCut, int); DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); @@ -59,9 +59,12 @@ DECLARE_SOA_COLUMN(EnergyZNA, energyZNA, float); DECLARE_SOA_COLUMN(EnergyZNC, energyZNC, float); DECLARE_SOA_COLUMN(AmplitudeFV0A, amplitudeFV0A, float); DECLARE_SOA_COLUMN(Occupancy, occupancy, float); -DECLARE_SOA_COLUMN(UPCMode, upcMode, float); +DECLARE_SOA_COLUMN(UpcMode, upcMode, float); +DECLARE_SOA_COLUMN(Pvz, pvz, float); DECLARE_SOA_COLUMN(PtSideA, ptSideA, std::vector); -DECLARE_SOA_COLUMN(RapSideA, rapSideA, std::vector); +DECLARE_SOA_COLUMN(PSideA, pSideA, std::vector); +DECLARE_SOA_COLUMN(ChargeSideA, chargeSideA, std::vector); +DECLARE_SOA_COLUMN(PseudorapSideA, pseudorapSideA, std::vector); DECLARE_SOA_COLUMN(PhiSideA, phiSideA, std::vector); DECLARE_SOA_COLUMN(TpcSignalSideA, tpcSignalSideA, std::vector); DECLARE_SOA_COLUMN(TofSignalSideA, tofSignalSideA, std::vector); @@ -69,8 +72,14 @@ DECLARE_SOA_COLUMN(TpcNSigmaPiSideA, tpcNSigmaPiSideA, std::vector); DECLARE_SOA_COLUMN(TofNSigmaPiSideA, tofNSigmaPiSideA, std::vector); DECLARE_SOA_COLUMN(TpcNSigmaKaSideA, tpcNSigmaKaSideA, std::vector); DECLARE_SOA_COLUMN(TofNSigmaKaSideA, tofNSigmaKaSideA, std::vector); +DECLARE_SOA_COLUMN(TpcNSigmaProSideA, tpcNSigmaProSideA, std::vector); +DECLARE_SOA_COLUMN(TofNSigmaProSideA, tofNSigmaProSideA, std::vector); +DECLARE_SOA_COLUMN(TofBetaSideA, tofBetaSideA, std::vector); +DECLARE_SOA_COLUMN(TofBetaErrorSideA, tofBetaErrorSideA, std::vector); DECLARE_SOA_COLUMN(PtSideC, ptSideC, std::vector); -DECLARE_SOA_COLUMN(RapSideC, rapSideC, std::vector); +DECLARE_SOA_COLUMN(PSideC, pSideC, std::vector); +DECLARE_SOA_COLUMN(ChargeSideC, chargeSideC, std::vector); +DECLARE_SOA_COLUMN(PseudorapSideC, pseudorapSideC, std::vector); DECLARE_SOA_COLUMN(PhiSideC, phiSideC, std::vector); DECLARE_SOA_COLUMN(TpcSignalSideC, tpcSignalSideC, std::vector); DECLARE_SOA_COLUMN(TofSignalSideC, tofSignalSideC, std::vector); @@ -78,6 +87,10 @@ DECLARE_SOA_COLUMN(TpcNSigmaPiSideC, tpcNSigmaPiSideC, std::vector); DECLARE_SOA_COLUMN(TofNSigmaPiSideC, tofNSigmaPiSideC, std::vector); DECLARE_SOA_COLUMN(TpcNSigmaKaSideC, tpcNSigmaKaSideC, std::vector); DECLARE_SOA_COLUMN(TofNSigmaKaSideC, tofNSigmaKaSideC, std::vector); +DECLARE_SOA_COLUMN(TpcNSigmaProSideC, tpcNSigmaProSideC, std::vector); +DECLARE_SOA_COLUMN(TofNSigmaProSideC, tofNSigmaProSideC, std::vector); +DECLARE_SOA_COLUMN(TofBetaSideC, tofBetaSideC, std::vector); +DECLARE_SOA_COLUMN(TofBetaErrorSideC, tofBetaErrorSideC, std::vector); DECLARE_SOA_COLUMN(NchSideA, nchSideA, int); DECLARE_SOA_COLUMN(MultiplicitySideA, multiplicitySideA, int); DECLARE_SOA_COLUMN(NchSideC, nchSideC, int); @@ -87,7 +100,7 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::GapSide, tree::GapSideTimeZN, tree::Sbp, - tree::ITSROFb, + tree::ItsRofB, tree::VtxITSTPCCut, tree::ZVtxFT0vsPvCut, tree::TimeZNA, @@ -96,9 +109,12 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::EnergyZNC, tree::AmplitudeFV0A, tree::Occupancy, - tree::UPCMode, + tree::UpcMode, + tree::Pvz, tree::PtSideA, - tree::RapSideA, + tree::PSideA, + tree::ChargeSideA, + tree::PseudorapSideA, tree::PhiSideA, tree::TpcSignalSideA, tree::TofSignalSideA, @@ -106,8 +122,14 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::TofNSigmaPiSideA, tree::TpcNSigmaKaSideA, tree::TofNSigmaKaSideA, + tree::TpcNSigmaProSideA, + tree::TofNSigmaProSideA, + tree::TofBetaSideA, + tree::TofBetaErrorSideA, tree::PtSideC, - tree::RapSideC, + tree::PSideC, + tree::ChargeSideC, + tree::PseudorapSideC, tree::PhiSideC, tree::TpcSignalSideC, tree::TofSignalSideC, @@ -115,6 +137,10 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::TofNSigmaPiSideC, tree::TpcNSigmaKaSideC, tree::TofNSigmaKaSideC, + tree::TpcNSigmaProSideC, + tree::TofNSigmaProSideC, + tree::TofBetaSideC, + tree::TofBetaErrorSideC, tree::NchSideA, tree::MultiplicitySideA, tree::NchSideC, @@ -122,7 +148,8 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", } // namespace o2::aod static constexpr float CFGPairCutDefaults[1][5] = {{-1, -1, -1, -1, -1}}; -constexpr float kThreeHalfPi = 1.5f * PI; +constexpr float KThreeHalfPi = 1.5f * PI; +constexpr float KMaxInSigmaPID = 9.0f; struct UpcPhotonuclearAnalysisJMG { @@ -200,7 +227,7 @@ struct UpcPhotonuclearAnalysisJMG { "Pair cuts on various particles"}; Configurable cfgTwoTrackCut{"cfgTwoTrackCut", -1, {"Two track cut"}}; ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; - ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {32, -PIHalf, kThreeHalfPi}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {32, -PIHalf, KThreeHalfPi}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {32, -1.6, 1.6}, "delta eta axis for histograms"}; ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pt associated axis for histograms"}; @@ -286,6 +313,8 @@ struct UpcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideA/hTrackPhi", "#it{#phi} distribution; #it{#phi}; counts", kTH1F, {axisPhi}); histos.add("Tracks/SGsideA/hTrackEta", "#it{#eta} distribution; #it{#eta}; counts", kTH1F, {axisEta}); histos.add("Tracks/SGsideA/hTrackTPCSignnalP", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideA/hTrackTPCSignnalPPiones", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideA/hTrackTPCSignnalPKaones", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideA/hTrackTOFSignnalP", "#it{TOF signal vs p}; #it{p*charge}; #it{TOF signal}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideA/hTrackITSNCls", "#it{N Clusters ITS} distribution; #it{N Clusters ITS}; counts", kTH1F, {axisNCls}); histos.add("Tracks/SGsideA/hTrackITSChi2NCls", "#it{N Clusters Chi2 ITS} distribution; #it{N Clusters Chi2 ITS}; counts", kTH1F, {axisChi2NCls}); @@ -318,6 +347,8 @@ struct UpcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideC/hTrackPhi", "#it{#phi} distribution; #it{#phi}; counts", kTH1F, {axisPhi}); histos.add("Tracks/SGsideC/hTrackEta", "#it{#eta} distribution; #it{#eta}; counts", kTH1F, {axisEta}); histos.add("Tracks/SGsideC/hTrackTPCSignnalP", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideC/hTrackTPCSignnalPPiones", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideC/hTrackTPCSignnalPKaones", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideC/hTrackTOFSignnalP", "#it{TOF signal vs p}; #it{p*charge}; #it{TOF signal}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideC/hTrackITSNCls", "#it{N Clusters ITS} distribution; #it{N Clusters ITS}; counts", kTH1F, {axisNCls}); histos.add("Tracks/SGsideC/hTrackITSChi2NCls", "#it{N Clusters Chi2 ITS} distribution; #it{N Clusters Chi2 ITS}; counts", kTH1F, {axisChi2NCls}); @@ -627,8 +658,8 @@ struct UpcPhotonuclearAnalysisJMG { int nchPVGapSideC = 0; int nchGapSideA = 0; int nchGapSideC = 0; - std::vector vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA; - std::vector vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideC, vTrackTOFSignalSideC, vTrackTPCNSigmaPiSideC, vTrackTOFNSigmaPiSideC, vTrackTPCNSigmaKaSideC, vTrackTOFNSigmaKaSideC; + std::vector vTrackPtSideA, vTrackPSideA, vTrackChargeSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, vTrackTPCNSigmaProSideA, vTrackTOFNSigmaProSideA, vTrackTOFBetaSideA, vTrackTOFBetaErrorSideA; + std::vector vTrackPtSideC, vTrackPSideC, vTrackChargeSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideC, vTrackTOFSignalSideC, vTrackTPCNSigmaPiSideC, vTrackTOFNSigmaPiSideC, vTrackTPCNSigmaKaSideC, vTrackTOFNSigmaKaSideC, vTrackTPCNSigmaProSideC, vTrackTOFNSigmaProSideC, vTrackTOFBetaSideC, vTrackTOFBetaErrorSideC; int nTracksChargedSideA(-222), nTracksChargedSideC(-222); int multiplicitySideA(-222), multiplicitySideC(-222); @@ -675,13 +706,25 @@ struct UpcPhotonuclearAnalysisJMG { nTracksCharged++; sumPt += track.pt(); float phiVal = RecoDecay::constrainAngle(phi(track.px(), track.py()), 0.f); + float pTotal = momentum(track.px(), track.py(), track.pz()) * track.sign(); + float etaVal = eta(track.px(), track.py(), track.pz()); histos.fill(HIST("Tracks/SGsideA/hTrackPt"), track.pt()); histos.fill(HIST("Tracks/SGsideA/hTrackPhi"), phiVal); - histos.fill(HIST("Tracks/SGsideA/hTrackEta"), eta(track.px(), track.py(), track.pz())); - histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); - histos.fill(HIST("Tracks/SGsideA/hTrackTOFSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tofSignal()); + histos.fill(HIST("Tracks/SGsideA/hTrackEta"), etaVal); + histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalP"), pTotal, track.tpcSignal()); + float nSigmaPi2 = track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi(); + float nSigmaKa2 = track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa(); + if (nSigmaPi2 < KMaxInSigmaPID && nSigmaKa2 > KMaxInSigmaPID) { + histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalPPiones"), pTotal, track.tpcSignal()); + } + if (nSigmaKa2 < KMaxInSigmaPID && nSigmaPi2 > KMaxInSigmaPID) { + histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalPKaones"), pTotal, track.tpcSignal()); + } + histos.fill(HIST("Tracks/SGsideA/hTrackTOFSignnalP"), pTotal, track.tofSignal()); vTrackPtSideA.push_back(track.pt()); - vTrackEtaSideA.push_back(eta(track.px(), track.py(), track.pz())); + vTrackPSideA.push_back(pTotal); + vTrackChargeSideA.push_back(track.sign()); + vTrackEtaSideA.push_back(etaVal); vTrackPhiSideA.push_back(phiVal); vTrackTPCSignalSideA.push_back(track.tpcSignal()); vTrackTOFSignalSideA.push_back(track.tofSignal()); @@ -689,6 +732,10 @@ struct UpcPhotonuclearAnalysisJMG { vTrackTOFNSigmaPiSideA.push_back(track.tofNSigmaPi()); vTrackTPCNSigmaKaSideA.push_back(track.tpcNSigmaKa()); vTrackTOFNSigmaKaSideA.push_back(track.tofNSigmaKa()); + vTrackTPCNSigmaProSideA.push_back(track.tpcNSigmaPr()); + vTrackTOFNSigmaProSideA.push_back(track.tofNSigmaPr()); + vTrackTOFBetaSideA.push_back(track.beta()); + vTrackTOFBetaErrorSideA.push_back(track.betaerror()); histos.fill(HIST("Tracks/SGsideA/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideA/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -735,13 +782,25 @@ struct UpcPhotonuclearAnalysisJMG { nTracksCharged++; sumPt += track.pt(); float phiVal = RecoDecay::constrainAngle(phi(track.px(), track.py()), 0.f); + float pTotal = momentum(track.px(), track.py(), track.pz()) * track.sign(); + float etaVal = eta(track.px(), track.py(), track.pz()); histos.fill(HIST("Tracks/SGsideC/hTrackPt"), track.pt()); histos.fill(HIST("Tracks/SGsideC/hTrackPhi"), phiVal); - histos.fill(HIST("Tracks/SGsideC/hTrackEta"), eta(track.px(), track.py(), track.pz())); - histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); - histos.fill(HIST("Tracks/SGsideC/hTrackTOFSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tofSignal()); + histos.fill(HIST("Tracks/SGsideC/hTrackEta"), etaVal); + histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalP"), pTotal, track.tpcSignal()); + float nSigmaPi2 = track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi(); + float nSigmaKa2 = track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa(); + if (nSigmaPi2 < KMaxInSigmaPID && nSigmaKa2 > KMaxInSigmaPID) { + histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalPPiones"), pTotal, track.tpcSignal()); + } + if (nSigmaKa2 < KMaxInSigmaPID && nSigmaPi2 > KMaxInSigmaPID) { + histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalPKaones"), pTotal, track.tpcSignal()); + } + histos.fill(HIST("Tracks/SGsideC/hTrackTOFSignnalP"), pTotal, track.tofSignal()); vTrackPtSideC.push_back(track.pt()); - vTrackEtaSideC.push_back(eta(track.px(), track.py(), track.pz())); + vTrackPSideC.push_back(pTotal); + vTrackChargeSideC.push_back(track.sign()); + vTrackEtaSideC.push_back(etaVal); vTrackPhiSideC.push_back(phiVal); vTrackTPCSignalSideC.push_back(track.tpcSignal()); vTrackTOFSignalSideC.push_back(track.tofSignal()); @@ -749,6 +808,10 @@ struct UpcPhotonuclearAnalysisJMG { vTrackTOFNSigmaPiSideC.push_back(track.tofNSigmaPi()); vTrackTPCNSigmaKaSideC.push_back(track.tpcNSigmaKa()); vTrackTOFNSigmaKaSideC.push_back(track.tofNSigmaKa()); + vTrackTPCNSigmaProSideC.push_back(track.tpcNSigmaPr()); + vTrackTOFNSigmaProSideC.push_back(track.tofNSigmaPr()); + vTrackTOFBetaSideC.push_back(track.beta()); + vTrackTOFBetaErrorSideC.push_back(track.betaerror()); histos.fill(HIST("Tracks/SGsideC/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideC/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -787,7 +850,10 @@ struct UpcPhotonuclearAnalysisJMG { reconstructedCollision.totalFV0AmplitudeA(), reconstructedCollision.occupancyInTime(), reconstructedCollision.flags(), + reconstructedCollision.posZ(), vTrackPtSideA, + vTrackPSideA, + vTrackChargeSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, @@ -796,7 +862,13 @@ struct UpcPhotonuclearAnalysisJMG { vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, + vTrackTPCNSigmaProSideA, + vTrackTOFNSigmaProSideA, + vTrackTOFBetaSideA, + vTrackTOFBetaErrorSideA, vTrackPtSideC, + vTrackPSideC, + vTrackChargeSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideA, @@ -805,6 +877,10 @@ struct UpcPhotonuclearAnalysisJMG { vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, + vTrackTPCNSigmaProSideA, + vTrackTOFNSigmaProSideA, + vTrackTOFBetaSideA, + vTrackTOFBetaErrorSideA, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, From a7b995be66af3e1858f85fed9ce1f74c9fabc8b0 Mon Sep 17 00:00:00 2001 From: Kai Cui <129373281+kcui1@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:27:42 +0200 Subject: [PATCH 377/449] [PWGLF] Bug Fix in hStrangeCorrelation.cxx (#16487) --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 00ec57541a0..edb043a9746 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -2807,6 +2807,8 @@ struct HStrangeCorrelation { histos.fill(HIST("Generated/hPositive") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); else if (i == IndexPion && mcParticle.pdgCode() < Neutral) histos.fill(HIST("Generated/hNegative") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); + else if (mcParticle.pdgCode() == PdgCodes[i]) + histos.fill(HIST("Generated/h") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); }); } if (collisions.size() < 1) From 8269b39e6ef942644defd267e552c09eb573c0ab Mon Sep 17 00:00:00 2001 From: lauraser <45659867+lauraser@users.noreply.github.com> Date: Mon, 1 Jun 2026 18:36:40 +0200 Subject: [PATCH 378/449] [Infrastructure] Delete old convener (#16491) Co-authored-by: Laura Serksnyte --- CODEOWNERS | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 87f1d20c1e2..9d2f8840bf1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -31,23 +31,23 @@ /EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @raymondEhlers @mpuccio @lietava @fgrosa @ariedel-cern /EventFiltering/PWGEM @alibuild @dsekihat @nstrangm @mpuccio @lietava @fgrosa @ariedel-cern -/PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF @alibuild @victor-gonzalez @shouqiye @lauraser /PWGCF/Core @alibuild @jgrosseo @lauraser -/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN -/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN -/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN -/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN -/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye @wrzesaCERN -/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye @lauraser -/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @otonvd @shouqiye @lauraser +/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @shouqiye @lauraser +/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @shouqiye @lauraser +/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @shouqiye @lauraser +/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @shouqiye @lauraser +/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @shouqiye @wrzesaCERN +/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @shouqiye @wrzesaCERN +/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @shouqiye @wrzesaCERN +/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @shouqiye @wrzesaCERN +/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @shouqiye @wrzesaCERN +/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @shouqiye @lauraser +/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @shouqiye @lauraser +/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @shouqiye @lauraser +/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @shouqiye @lauraser +/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @shouqiye @lauraser +/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @shouqiye @lauraser /PWGDQ @alibuild @iarsene @mcoquet642 @lucamicheletti93 @XiaozhiBai /PWGEM @alibuild @feisenhu @dsekihat @jokonig @hscheid From 6034ef723a2532ad5fe855f7697fcc2aa57a14b1 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Mon, 1 Jun 2026 20:00:37 +0300 Subject: [PATCH 379/449] [Common] Remove workaround for trigger bc shift (#16489) --- Common/Tools/EventSelectionModule.h | 128 +++++++++++++--------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/Common/Tools/EventSelectionModule.h b/Common/Tools/EventSelectionModule.h index 76e4cde6bd5..5e44ffe226b 100644 --- a/Common/Tools/EventSelectionModule.h +++ b/Common/Tools/EventSelectionModule.h @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file EventSelectionModule.h -/// \brief +/// \brief Event selection modeule /// \author ALICE #ifndef COMMON_TOOLS_EVENTSELECTIONMODULE_H_ @@ -59,8 +59,8 @@ #include #include -#define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) -#define bitcheck64(var, nbit) ((var) & (static_cast(1) << (nbit))) +#define BITCHECK(var, nbit) ((var) & (static_cast(1) << (nbit))) +#define BITCHECK64(var, nbit) ((var) & (static_cast(1) << (nbit))) //__________________________________________ // MultModule @@ -77,7 +77,7 @@ static const int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; // for providing temporary buffer // FIXME ideally cursors could be readable // to avoid duplicate memory allocation but ok -struct bcselEntry { +struct bcselEntry { // o2-linter: disable=name/struct (temporary fix) uint32_t alias{0}; uint64_t selection{0}; uint32_t rct{0}; @@ -88,23 +88,22 @@ struct bcselEntry { }; // bc selection configurables -struct bcselConfigurables : o2::framework::ConfigurableGroup { +struct bcselConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) std::string prefix = "bcselOpts"; o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confTriggerBcShift{"triggerBcShift", 0, "set either custom shift or 999 for apass2/apass3 in LHC22o-t"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confTimeFrameStartBorderMargin{"TimeFrameStartBorderMargin", -1, "Number of bcs to cut at the start of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confTimeFrameEndBorderMargin{"TimeFrameEndBorderMargin", -1, "Number of bcs to cut at the end of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable> confMaxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; + o2::framework::Configurable> confMaxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) }; // event selection configurables -struct evselConfigurables : o2::framework::ConfigurableGroup { +struct evselConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) std::string prefix = "evselOpts"; - bool isMC_metadata = false; + bool isMC_metadata = false; // o2-linter: disable=name/function-variable (temporary fix) o2::framework::Configurable amIneeded{"amIneeded", -1, "run event selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable muonSelection{"muonSelection", 0, "0 - barrel, 1 - muon selection with pileup cuts, 2 - muon selection without pileup cuts"}; o2::framework::Configurable maxDiffZvtxFT0vsPV{"maxDiffZvtxFT0vsPV", 1., "maximum difference (in cm) between z-vertex from FT0 and PV"}; @@ -130,7 +129,7 @@ struct evselConfigurables : o2::framework::ConfigurableGroup { }; // luminosity configurables -struct lumiConfigurables : o2::framework::ConfigurableGroup { +struct lumiConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) std::string prefix = "lumiOpts"; o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) }; @@ -453,16 +452,6 @@ class BcSelectionModule return; // don't do anything in case configuration reported not ok int run = bcs.iteratorAt(0).runNumber(); - // map from GlobalBC to BcId needed to find triggerBc - std::map mapGlobalBCtoBcId; - for (const auto& bc : bcs) { - mapGlobalBCtoBcId[bc.globalBC()] = bc.globalIndex(); - } - - int triggerBcShift = bcselOpts.confTriggerBcShift; - if (bcselOpts.confTriggerBcShift == 999) { // o2-linter: disable=magic-number (special shift for early 2022 data) - triggerBcShift = (run <= 526766 || (run >= 526886 && run <= 527237) || (run >= 527259 && run <= 527518) || run == 527523 || run == 527734 || run >= 534091) ? 0 : 294; // o2-linter: disable=magic-number (magic list of runs) - } // bc loop for (auto bc : bcs) { // o2-linter: disable=const-ref-in-for-loop (use bc as nonconst iterator) @@ -481,11 +470,8 @@ class BcSelectionModule } uint32_t alias{0}; - // workaround for pp2022 (trigger info is shifted by -294 bcs) - int32_t triggerBcId = mapGlobalBCtoBcId[bc.globalBC() + triggerBcShift]; - if (triggerBcId && aliases) { - auto triggerBc = bcs.iteratorAt(triggerBcId); - uint64_t triggerMask = triggerBc.triggerMask(); + if (aliases) { + uint64_t triggerMask = bc.triggerMask(); for (const auto& al : aliases->GetAliasToTriggerMaskMap()) { if (triggerMask & al.second) { alias |= BIT(al.first); @@ -707,14 +693,14 @@ class EventSelectionModule float calcWeightForOccupancy(float dt) { float wOccup = 0; - if (dt >= -40 && dt < -5) // collisions in the past // o2-linter: disable=magic-number - wOccup = 1. / 1225 * (dt + 40) * (dt + 40); // o2-linter: disable=magic-number - else if (dt >= -5 && dt < 15) // collisions near a given one // o2-linter: disable=magic-number + if (dt >= -40 && dt < -5) // o2-linter: disable=magic-number (collisions in the past) + wOccup = 1. / 1225 * (dt + 40) * (dt + 40); // o2-linter: disable=magic-number (parabolic weight for past collisions) + else if (dt >= -5 && dt < 15) // o2-linter: disable=magic-number (collisions near a given one) wOccup = 1; - else if (dt >= 15 && dt < 40) // collisions from the future // o2-linter: disable=magic-number - wOccup = -0.4 / 25 * dt + 1.24; // o2-linter: disable=magic-number - else if (dt >= 40 && dt < 100) // collisions from the distant future // o2-linter: disable=magic-number - wOccup = -0.4 / 60 * dt + 0.6 + 0.8 / 3; // o2-linter: disable=magic-number + else if (dt >= 15 && dt < 40) // o2-linter: disable=magic-number (collisions from the future) + wOccup = -0.4 / 25 * dt + 1.24; // o2-linter: disable=magic-number (linear weight for future collisions) + else if (dt >= 40 && dt < 100) // o2-linter: disable=magic-number (collisions from the distant future) + wOccup = -0.4 / 60 * dt + 0.6 + 0.8 / 3; // o2-linter: disable=magic-number (linear weight for distant future collisions) return wOccup; } @@ -794,7 +780,7 @@ class EventSelectionModule LOGP(debug, "ITS ROF Offset={} ITS ROF Length={}", rofOffset, rofLength); // special treatment of light ion runs - if (lastRun >= 564356 && lastRun <= 564472) { + if (lastRun >= 564356 && lastRun <= 564472) { // o2-linter: disable=magic-number (light ion run range) for (uint32_t i = 0; i < sizeof(runListLightIons) / sizeof(*runListLightIons); i++) { if (runListLightIons[i] == lastRun) { runLightIons = lastRun; @@ -804,9 +790,9 @@ class EventSelectionModule diffVzParMean = *parMeans; diffVzParSigma = *parSigmas; LOGP(info, ">>> special treatment for diffVz for light ion run {}", runLightIons); - for (int j = 0; j < 5; j++) + for (int j = 0; j < 5; j++) // o2-linter: disable=magic-number (5 parameters) LOGP(info, " mean par {} = {}", j, diffVzParMean[j]); - for (int j = 0; j < 5; j++) + for (int j = 0; j < 5; j++) // o2-linter: disable=magic-number (5 parameters) LOGP(info, " sigma par {} = {}", j, diffVzParSigma[j]); break; } @@ -877,18 +863,18 @@ class EventSelectionModule } // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bitcheck64(selection, aod::evsel::kIsBBT0A) && bitcheck64(selection, aod::evsel::kIsBBT0C); // TODO apply other cuts for sel8 - bool sel1 = bitcheck64(selection, aod::evsel::kIsINT1); - sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoBGV0A); - sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoBGV0C); - sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoTPCLaserWarmUp); - sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoTPCHVdip); + bool sel8 = BITCHECK64(selection, aod::evsel::kIsBBT0A) && BITCHECK64(selection, aod::evsel::kIsBBT0C); // TODO apply other cuts for sel8 + bool sel1 = BITCHECK64(selection, aod::evsel::kIsINT1); + sel1 = sel1 && BITCHECK64(selection, aod::evsel::kNoBGV0A); + sel1 = sel1 && BITCHECK64(selection, aod::evsel::kNoBGV0C); + sel1 = sel1 && BITCHECK64(selection, aod::evsel::kNoTPCLaserWarmUp); + sel1 = sel1 && BITCHECK64(selection, aod::evsel::kNoTPCHVdip); // INT1 (SPDFO>0 | V0A | V0C) minimum bias trigger logic used in pp2010 and pp2011 bool isINT1period = bc.runNumber() <= 136377 || (bc.runNumber() >= 144871 && bc.runNumber() <= 159582); // o2-linter: disable=magic-number (magic run numbers) // fill counters - if (evselOpts.isMC == 1 || (!isINT1period && bitcheck(alias, kINT7)) || (isINT1period && bitcheck(alias, kINT1))) { + if (evselOpts.isMC == 1 || (!isINT1period && BITCHECK(alias, kINT7)) || (isINT1period && BITCHECK(alias, kINT1))) { histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); if ((!isINT1period && sel7) || (isINT1period && sel1)) { histos.template get(HIST("eventselection/hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); @@ -927,7 +913,7 @@ class EventSelectionModule } auto selection = bcselbuffer[bc.globalIndex()].selection; - if (bitcheck64(selection, aod::evsel::kIsTriggerTVX)) { + if (BITCHECK64(selection, aod::evsel::kIsTriggerTVX)) { mapGlobalBcWithTVX[globalBC] = bc.globalIndex(); mapGlobalBcVtxZ[globalBC] = bc.has_ft0() ? bc.ft0().posZ() : 0; } @@ -1036,7 +1022,7 @@ class EventSelectionModule int32_t localBC = globalBC % nBCsPerOrbit; int32_t bcFromPattern = bcsPattern.at(i); int64_t bcDiff = bcFromPattern - localBC; - if (std::abs(bcDiff) <= 20) { + if (std::abs(bcDiff) <= 20) { // o2-linter: disable=magic-number (max BC difference to match pattern) foundGlobalBC = (globalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPattern; break; // the bc in pattern is found } @@ -1073,7 +1059,7 @@ class EventSelectionModule for (uint32_t j = 0; j < bcsPattern.size(); j++) { int32_t bcFromPatternBest = bcsPattern.at(j); int64_t bcDiff = bcFromPatternBest - (bestGlobalBC % nBCsPerOrbit); - if (std::abs(bcDiff) <= 20) { + if (std::abs(bcDiff) <= 20) { // o2-linter: disable=magic-number (max BC difference to match pattern) foundGlobalBC = (bestGlobalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPatternBest; break; // the bc in pattern is found } @@ -1177,12 +1163,12 @@ class EventSelectionModule auto bcselEntry = bcselbuffer[foundBC]; // check if we are close to ITS ROF borders => N ITS tracks is not reliable, and FT0C ampl can be used for occupancy estimation // denominator for vAmpFT0CperColl is the approximate conversion factor b/n FT0C ampl and number of PV tracks after cuts - vProxyForCollNtracks[colIndex] = bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder) ? vTracksITS567perColl[colIndex] : vAmpFT0CperColl[colIndex] / 10.; + vProxyForCollNtracks[colIndex] = BITCHECK64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder) ? vTracksITS567perColl[colIndex] : vAmpFT0CperColl[colIndex] / 10.; - if (!bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder)) { + if (!BITCHECK64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder)) { vIsCollRejectedByTFborderCut[colIndex] = true; } - if (nBCsPerTF - bcInTF < 4000 * 2) { + if (nBCsPerTF - bcInTF < 4000 * 2) { // o2-linter: disable=magic-number (BCs within last drift time window) vCanHaveAssocCollsWithinLastDriftTime[colIndex] = true; } } @@ -1381,7 +1367,7 @@ class EventSelectionModule nITS567tracksForVetoStrict += vProxyForCollNtracks[thisColIndex]; // veto on high-mult collisions nearby, where artificial structures in the dt-occupancy plots are observed - if (dt > -4.0 && dt < 2.0 && vAmpFT0CperColl[thisColIndex] > evselOpts.confFT0CamplCutVetoOnCollInTimeRange) { // dt in us // o2-linter: disable=magic-number + if (dt > -4.0 && dt < 2.0 && vAmpFT0CperColl[thisColIndex] > evselOpts.confFT0CamplCutVetoOnCollInTimeRange) { // o2-linter: disable=magic-number (dt in us, time window for high-mult veto) nCollsWithFT0CAboveVetoStandard++; } @@ -1428,7 +1414,7 @@ class EventSelectionModule if (evselOpts.confUseWeightsForOccupancyVariable) { wOccup = calcWeightForOccupancy(dt / 1e3); // ns -> us } - if (multT0C > 50.) // multiplicity in TVX is non-negligible, take it into occupancy calc + if (multT0C > 50.) // o2-linter: disable=magic-number (multiplicity threshold for occupancy calc) { nITS567tracksInFullTimeWindow += wOccup * multT0C / 10.; sumAmpFT0CInFullTimeWindow += wOccup * multT0C; @@ -1472,13 +1458,13 @@ class EventSelectionModule } else { // special treatment of light ion runs float multT0A = bc.ft0().sumAmpA(); float multT0C = bc.ft0().sumAmpC(); - float T0M = multT0A + multT0C; + float multT0M = multT0A + multT0C; // calc mean at this T0 ampl. - float x = (T0M < 50 ? 50 : T0M); - double diffMean = diffVzParMean[0] + diffVzParMean[1] * pow(x, diffVzParMean[2]) + diffVzParMean[3] * pow(x, diffVzParMean[4]); + float x = (multT0M < 50 ? 50 : multT0M); // o2-linter: disable=magic-number (min T0M for mean parametrization) + double diffMean = diffVzParMean[0] + diffVzParMean[1] * std::pow(x, diffVzParMean[2]) + diffVzParMean[3] * std::pow(x, diffVzParMean[4]); // calc sigma at this T0 ampl. - x = (T0M < 20 ? 20 : (T0M > 1.2e4 ? 1.2e4 : T0M)); - double diffSigma = diffVzParSigma[0] + diffVzParSigma[1] * pow(x, diffVzParSigma[2]) + diffVzParSigma[3] * pow(x, diffVzParSigma[4]); + x = (multT0M < 20 ? 20 : (multT0M > 1.2e4 ? 1.2e4 : multT0M)); // o2-linter: disable=magic-number (min/max T0M for sigma parametrization) + double diffSigma = diffVzParSigma[0] + diffVzParSigma[1] * std::pow(x, diffVzParSigma[2]) + diffVzParSigma[3] * std::pow(x, diffVzParSigma[4]); float nSigma = evselOpts.confLightIonsNsigmaOnVzDiff; float margin = evselOpts.confLightIonsMarginVzDiff; isGoodZvtxFT0vsPV = (diffVz > diffMean - nSigma * diffSigma - margin && diffVz < diffMean + nSigma * diffSigma + margin); @@ -1519,14 +1505,14 @@ class EventSelectionModule // TODO apply other cuts for sel8? // TODO introduce array of sel[0]... sel[8] or similar? bool sel8 = false; - if (lastRun < 568873) // pre-2026 data & MC: require all three bits: TVX, TF and ROF border cuts - sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + if (lastRun < 568873) // o2-linter: disable=magic-number (pre-2026 data & MC: require all three bits: TVX, TF and ROF border cuts) + sel8 = BITCHECK64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && BITCHECK64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && BITCHECK64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); else // for pp 2026: sel8 without kNoITSROFrameBorder bit, because the cross-ROF reconstruction for ITS will be On (the switch by a runNumber is a temporary solution) - sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder); + sel8 = BITCHECK64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && BITCHECK64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder); // fill counters histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); - if (bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX)) { + if (BITCHECK64(bcselEntry.selection, aod::evsel::kIsTriggerTVX)) { histos.template get(HIST("eventselection/hColCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); } if (sel8) { @@ -1672,11 +1658,11 @@ class LumiModule csZEM = -1; csZNC = -1; // Temporary workaround to get visible cross section. TODO: store run-by-run visible cross sections in CCDB - if (beamZ1 == 8 && beamZ2 == 1) { + if (beamZ1 == 8 && beamZ2 == 1) { // o2-linter: disable=magic-number (O beam on p, Z=8 and Z=1) csTVX = 0.3874e6; // eff(TVX) = 0.807 (based on LHC25e6f); sigma(INEL)=0.48b; arxiv:2507.05853 - } else if (beamZ1 == 8 && beamZ2 == 8) { + } else if (beamZ1 == 8 && beamZ2 == 8) { // o2-linter: disable=magic-number (O-O collisions, Z=8) csTVX = 1.2050e6; // eff(TVX) = 0.886 (based on LHC25e6b); sigma(INEL)=1.36b; arxiv:2507.05853 - } else if (beamZ1 == 10 && beamZ2 == 10) { + } else if (beamZ1 == 10 && beamZ2 == 10) { // o2-linter: disable=magic-number (Ne-Ne collisions, Z=10) csTVX = 1.5411e6; // eff(TVX) = 0.896 (based on LHC25e6g); sigma(INEL)=1.72b; arxiv:2507.05853 } else if (beamZ1 == 1 && beamZ2 == 1) { if (std::fabs(sqrts - 900.) < 100.) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) @@ -1771,15 +1757,17 @@ class LumiModule double perBcRateTCE = static_cast(mCounterTCE[i + 1] - mCounterTCE[i]) / nOrbits / nCollidingBCs; double perBcRateZNC = static_cast(mCounterZNC[i + 1] - mCounterZNC[i]) / nOrbits / nCollidingBCs; double perBcRateZEM = static_cast(mCounterZEM[i + 1] - mCounterZEM[i]) / nOrbits / nCollidingBCs; - double muTVX = (perBcRateTVX < 1 && perBcRateTVX > 1e-10) ? -std::log(1 - perBcRateTVX) : 0; - double muTCE = (perBcRateTCE < 1 && perBcRateTCE > 1e-10) ? -std::log(1 - perBcRateTCE) : 0; - double muZNC = (perBcRateZNC < 1 && perBcRateZNC > 1e-10) ? -std::log(1 - perBcRateZNC) : 0; - double muZEM = (perBcRateZEM < 1 && perBcRateZEM > 1e-10) ? -std::log(1 - perBcRateZEM) : 0; + constexpr float rateMin = 1.e-10; + double muTVX = (perBcRateTVX < 1 && perBcRateTVX > rateMin) ? -std::log(1 - perBcRateTVX) : 0; + double muTCE = (perBcRateTCE < 1 && perBcRateTCE > rateMin) ? -std::log(1 - perBcRateTCE) : 0; + double muZNC = (perBcRateZNC < 1 && perBcRateZNC > rateMin) ? -std::log(1 - perBcRateZNC) : 0; + double muZEM = (perBcRateZEM < 1 && perBcRateZEM > rateMin) ? -std::log(1 - perBcRateZEM) : 0; LOGP(debug, "orbit={} muTVX={} muTCE={} muZNC={} muZEM={}", mOrbits[i], muTVX, muTCE, muZNC, muZEM); - mPileupCorrectionTVX.push_back(muTVX > 1e-10 ? muTVX / (1 - std::exp(-muTVX)) : 1); - mPileupCorrectionTCE.push_back(muTCE > 1e-10 ? muTCE / (1 - std::exp(-muTCE)) : 1); - mPileupCorrectionZNC.push_back(muZNC > 1e-10 ? muZNC / (1 - std::exp(-muZNC)) : 1); - mPileupCorrectionZEM.push_back(muZEM > 1e-10 ? muZEM / (1 - std::exp(-muZEM)) : 1); + constexpr float muMin = 1.e-10; + mPileupCorrectionTVX.push_back(muTVX > muMin ? muTVX / (1 - std::exp(-muTVX)) : 1); + mPileupCorrectionTCE.push_back(muTCE > muMin ? muTCE / (1 - std::exp(-muTCE)) : 1); + mPileupCorrectionZNC.push_back(muZNC > muMin ? muZNC / (1 - std::exp(-muZNC)) : 1); + mPileupCorrectionZEM.push_back(muZEM > muMin ? muZEM / (1 - std::exp(-muZEM)) : 1); } // filling last orbit range using previous orbit range mPileupCorrectionTVX.push_back(mPileupCorrectionTVX.back()); From c60158dd338934a9503f277189656770c0436268 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:29:18 +0200 Subject: [PATCH 380/449] [PWGCF] Store different MFT track type info into LRTables (#16493) --- .../DataModel/LongRangeDerived.h | 10 ++- .../TableProducer/longrangeMaker.cxx | 77 ++++++++++--------- .../Tasks/longrangecorrDerived.cxx | 22 +++++- 3 files changed, 66 insertions(+), 43 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index af4916671da..583e33019c4 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -159,6 +159,8 @@ DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(IsCA, isCA, bool); +DECLARE_SOA_COLUMN(IsReassigned, isReassigned, bool); enum TrackPid { kSpCharge, @@ -226,7 +228,9 @@ DECLARE_SOA_TABLE(LRMftTracks, "AOD", "LRMFTTRACK", lrcorrtrktable::Phi, fwdtrack::NClusters, fwdtrack::BestDCAXY, - fwdtrack::BestDCAZ); + fwdtrack::BestDCAZ, + lrcorrtrktable::IsCA, + lrcorrtrktable::IsReassigned); using LRMftTrack = LRMftTracks::iterator; DECLARE_SOA_TABLE(UpcLRMidTracks, "AOD", "UPCLRMIDTRACK", @@ -281,7 +285,9 @@ DECLARE_SOA_TABLE(UpcLRMftTracks, "AOD", "UPCLRMFTTRACK", lrcorrtrktable::Phi, fwdtrack::NClusters, fwdtrack::BestDCAXY, - fwdtrack::BestDCAZ); + fwdtrack::BestDCAZ, + lrcorrtrktable::IsCA, + lrcorrtrktable::IsReassigned); using UpcLRMftTrack = UpcLRMftTracks::iterator; } // namespace o2::aod diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 61d404d5890..4dd36146ce2 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -83,7 +83,7 @@ using namespace o2::constants::math; auto static constexpr CintZero = 0; auto static constexpr KminFt0cCell = 96; auto static constexpr TotFt0Channels = 208; -AxisSpec axisEvent{15, 0.5, 15.5, "#Event", "EventAxis"}; +AxisSpec axisEvent{20, 0.5, 20.5, "#Event", "EventAxis"}; AxisSpec axisTrackSel{10, 0.5, 10.5, "#Track", "TrackAxis"}; auto static constexpr KminCharge = 3.0f; static constexpr std::string_view species[] = {"Pi", "Ka", "Pr"}; @@ -112,7 +112,9 @@ struct LongrangeMaker { Configurable isApplyBestCollIndex{"isApplyBestCollIndex", true, "bestCollIndex"}; Configurable isrejectFlangeEvent{"isrejectFlangeEvent", false, "At least one channel with -350 TDC < time < -450 TDC"}; Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, "Enable NoCollInTimeRangeStandard cut"}; + Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, "Enable NoCollInTimeRangeStrict cut"}; Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, "Enable NoCollInRofStandard cut"}; + Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, "Enable NoCollInRofStrict cut"}; Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, "Enable NoHighMultCollInPrevRof cut"}; Configurable isApplyCentFT0C{"isApplyCentFT0C", false, "Centrality based on FT0C"}; Configurable isApplyCentFV0A{"isApplyCentFV0A", false, "Centrality based on FV0A"}; @@ -142,6 +144,7 @@ struct LongrangeMaker { struct : ConfigurableGroup { Configurable cfgUseChi2Cut{"cfgUseChi2Cut", false, "Use condition on MFT track: chi2/Nclusters"}; Configurable cfgRequireCA{"cfgRequireCA", false, "Use Cellular Automaton track-finding algorithm"}; + Configurable cfgRequireLTF{"cfgRequireLTF", false, "Use LTF track-finding algorithm"}; Configurable useMftPtCut{"useMftPtCut", true, "Choose to apply MFT track pT cut"}; Configurable cfgMftCluster{"cfgMftCluster", 5, "cut on MFT Cluster"}; Configurable cfgMftEtaMax{"cfgMftEtaMax", -2.4f, "Maximum MFT eta cut"}; @@ -251,11 +254,13 @@ struct LongrangeMaker { x->SetBinLabel(6, "ApplyGoodZvtxFT0vsPV"); x->SetBinLabel(7, "ApplyGoodITSLayersAll"); x->SetBinLabel(8, "ApplyExtraCorrCut"); - x->SetBinLabel(9, "ApplyNoCollInTimeRangeStandard"); - x->SetBinLabel(10, "ApplyNoCollInRofStandard"); - x->SetBinLabel(11, "ApplyNoHighMultCollInPrevRof"); - x->SetBinLabel(12, "ApplyOccupancySelection"); - x->SetBinLabel(13, "reject flange event"); + x->SetBinLabel(9, "ApplyNoCollInRofStandard"); + x->SetBinLabel(10, "ApplyNoCollInRofStrict"); + x->SetBinLabel(11, "ApplyNoCollInTimeRangeStandard"); + x->SetBinLabel(12, "ApplyNoCollInTimeRangeStrict"); + x->SetBinLabel(13, "ApplyNoHighMultCollInPrevRof"); + x->SetBinLabel(14, "ApplyOccupancySelection"); + x->SetBinLabel(15, "reject flange event"); histos.add("hSelectionResult", "hSelectionResult", kTH1I, {{5, -0.5, 4.5}}); histos.add("hMftTrkSel", "hMftTrkSel", kTH1D, {axisTrackSel}, false); @@ -277,9 +282,6 @@ struct LongrangeMaker { xMftBestTrk->SetBinLabel(4, "DCAxy selection"); xMftBestTrk->SetBinLabel(5, "DCAz selection"); - histos.add("ReassignedMFTtrackAmbDegree", "ReassignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); - histos.add("AssignedMFTtrackAmbDegree", "AssignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); - histos.add("FT0A_Amp", "FT0A_Amp", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0A_Amp_gaincorrected", "FT0A_Amp_gaincorrected", kTH1D, {cfgAxis.axisAmplitude}); histos.add("FT0A_Channel_vs_Amp", "FT0A_Channel_vs_Amp", kTH2D, {cfgAxis.axisChannel, cfgAxis.axisAmplitude}); @@ -427,7 +429,7 @@ struct LongrangeMaker { return; } } - histos.fill(HIST("EventHist"), 13); + histos.fill(HIST("EventHist"), 15); for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { auto chanelid = ft0.channelA()[iCh]; float ampl = ft0.amplitudeA()[iCh]; @@ -483,12 +485,6 @@ struct LongrangeMaker { continue; } auto phi = itrack.phi(); - if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } - if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } o2::math_utils::bringTo02Pi(phi); lrmfttracks(lrcollision.lastIndex(), reassoMftTrack.ambDegree(), @@ -497,7 +493,9 @@ struct LongrangeMaker { phi, itrack.nClusters(), reassoMftTrack.bestDCAXY(), - reassoMftTrack.bestDCAZ()); + reassoMftTrack.bestDCAZ(), + itrack.isCA(), + itrack.collisionId() != reassoMftTrack.bestCollisionId()); } // v0 loop @@ -664,12 +662,6 @@ struct LongrangeMaker { } auto phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); - if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } - if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } upclrmfttracks(upclrcollision.lastIndex(), reassoMftTrack.ambDegree(), itrack.pt(), @@ -677,7 +669,9 @@ struct LongrangeMaker { phi, itrack.nClusters(), reassoMftTrack.bestDCAXY(), - reassoMftTrack.bestDCAZ()); + reassoMftTrack.bestDCAZ(), + itrack.isCA(), + itrack.collisionId() != reassoMftTrack.bestCollisionId()); } // v0 loop @@ -869,12 +863,6 @@ struct LongrangeMaker { } auto phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); - if (itrack.collisionId() != reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("ReassignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } - if (itrack.collisionId() == reassoMftTrack.bestCollisionId()) { - histos.fill(HIST("AssignedMFTtrackAmbDegree"), reassoMftTrack.ambDegree()); - } lrmfttracks(lrcollision.lastIndex(), reassoMftTrack.ambDegree(), itrack.pt(), @@ -882,7 +870,9 @@ struct LongrangeMaker { phi, itrack.nClusters(), reassoMftTrack.bestDCAXY(), - reassoMftTrack.bestDCAZ()); + reassoMftTrack.bestDCAZ(), + itrack.isCA(), + itrack.collisionId() != reassoMftTrack.bestCollisionId()); } for (const auto& particle : mcparticles) { @@ -1034,6 +1024,12 @@ struct LongrangeMaker { if (!isMftTrackSelected(track)) { continue; } + if (cfgmfttrksel.cfgRequireCA && !track.isCA()) { + continue; + } + if (cfgmfttrksel.cfgRequireLTF && track.isCA()) { + continue; + } if (!track.has_mcParticle()) continue; auto particle = track.mcParticle(); @@ -1096,22 +1092,30 @@ struct LongrangeMaker { return false; } histos.fill(HIST("EventHist"), 8); - if (cfgevtsel.isApplyNoCollInTimeRangeStandard && !col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (cfgevtsel.isApplyNoCollInRofStandard && !col.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } histos.fill(HIST("EventHist"), 9); - if (cfgevtsel.isApplyNoCollInRofStandard && !col.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (cfgevtsel.isApplyNoCollInRofStrict && !col.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { return false; } histos.fill(HIST("EventHist"), 10); - if (cfgevtsel.isApplyNoHighMultCollInPrevRof && !col.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (cfgevtsel.isApplyNoCollInTimeRangeStandard && !col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } histos.fill(HIST("EventHist"), 11); - if (cfgevtsel.isApplyOccuSelection && (col.trackOccupancyInTimeRange() > cfgevtsel.cfgOccuCut)) { + if (cfgevtsel.isApplyNoCollInTimeRangeStrict && !col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; } histos.fill(HIST("EventHist"), 12); + if (cfgevtsel.isApplyNoHighMultCollInPrevRof && !col.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + histos.fill(HIST("EventHist"), 13); + if (cfgevtsel.isApplyOccuSelection && (col.trackOccupancyInTimeRange() > cfgevtsel.cfgOccuCut)) { + return false; + } + histos.fill(HIST("EventHist"), 14); return true; } @@ -1247,9 +1251,6 @@ struct LongrangeMaker { if constexpr (fillHis) { histos.fill(HIST("hMftTrkSel"), 5); } - if (cfgmfttrksel.cfgRequireCA && !track.isCA()) { - return false; - } if constexpr (fillHis) { histos.fill(HIST("hMftTrkSel"), 6); } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 866fcdeba90..79b3b67238c 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -76,6 +76,8 @@ struct LongrangecorrDerived { Configurable cfgMftDcaz{"cfgMftDcaz", 2.0f, "cut on DCA z for MFT tracks"}; Configurable cfgRejectAmbTrk{"cfgRejectAmbTrk", false, "Condition to reject Ambiguous tracks"}; Configurable cfgRejectNonAmbTrk{"cfgRejectNonAmbTrk", false, "Condition to reject Non-Ambiguous tracks"}; + Configurable cfgRequireCA{"cfgRequireCA", false, "Use Cellular Automaton track-finding algorithm"}; + Configurable cfgRequireLTF{"cfgRequireLTF", false, "Use LTF track-finding algorithm"}; } cfgSel; struct : ConfigurableGroup { @@ -203,10 +205,12 @@ struct LongrangecorrDerived { histos.add("TPCChi2NCl", "TPCChi2NCl", kTH1D, {cfgAxis.axisTPCChi2NCl}); histos.add("TPCdcaZ", "TPCdcaZ", kTH1D, {cfgAxis.axisTPCdcaZ}); - histos.add("MFTAmbDegree", "MFTAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); histos.add("MFTNClusters", "MFTNClusters", kTH1D, {cfgAxis.axisMFTNClusters}); histos.add("MFTbestDCAXY", "MFTbestDCAXY", kTH1D, {cfgAxis.axisMFTbestDCAXY}); histos.add("MFTbestDCAZ", "MFTbestDCAZ", kTH1D, {cfgAxis.axisMFTbestDCAZ}); + + histos.add("ReassignedMFTtrackAmbDegree", "ReassignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); + histos.add("AssignedMFTtrackAmbDegree", "AssignedMFTtrackAmbDegree", kTH1D, {cfgAxis.axisMFTAmbDegree}); } template @@ -233,6 +237,10 @@ struct LongrangecorrDerived { return false; if (cfgSel.cfgRejectNonAmbTrk && track.ambDegree() == 1) return false; + if (cfgSel.cfgRequireCA && !track.isCA()) + return false; + if (cfgSel.cfgRequireLTF && track.isCA()) + return false; return true; } else { return true; @@ -274,7 +282,11 @@ struct LongrangecorrDerived { histos.fill(HIST("MFTNClusters"), track.nClusters()); histos.fill(HIST("MFTbestDCAXY"), track.bestDCAXY()); histos.fill(HIST("MFTbestDCAZ"), track.bestDCAZ()); - histos.fill(HIST("MFTAmbDegree"), track.ambDegree()); + if (track.isReassigned()) { + histos.fill(HIST("ReassignedMFTtrackAmbDegree"), track.ambDegree()); + } else { + histos.fill(HIST("AssignedMFTtrackAmbDegree"), track.ambDegree()); + } } } @@ -292,7 +304,11 @@ struct LongrangecorrDerived { histos.fill(HIST("MFTNClusters"), track.nClusters()); histos.fill(HIST("MFTbestDCAXY"), track.bestDCAXY()); histos.fill(HIST("MFTbestDCAZ"), track.bestDCAZ()); - histos.fill(HIST("MFTAmbDegree"), track.ambDegree()); + if (track.isReassigned()) { + histos.fill(HIST("ReassignedMFTtrackAmbDegree"), track.ambDegree()); + } else { + histos.fill(HIST("AssignedMFTtrackAmbDegree"), track.ambDegree()); + } } } From a2f585d346b9cd610b0c487261bd7b035f77479e Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Tue, 2 Jun 2026 12:51:02 +0800 Subject: [PATCH 381/449] [PWGCF] flowDirectedFlowTask.cxx: fix acceptance correction, add resolution histogram (#16495) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx index 530e528badc..a48bb41bbe4 100644 --- a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx +++ b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx @@ -164,7 +164,8 @@ struct flowDirectedFlowTask { histos.add("hQyCvscent", "Qy C vs centrality", kTH2F, {{centAxis}, {qAxis}}); histos.add("hpResCosAC", "cos(#Psi_{A}-#Psi_{C}) vs centrality", kTH3F, {{centAxis}, {resAxis}, {q1Axis}}); - histos.add("hpResDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH3F, {{centAxis}, {resAxis}, {q1Axis}}); + histos.add("hpDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH3F, {{centAxis}, {qAxis}, {q1Axis}}); + histos.add("hpResDotAC", "Q_{A}#upoint Q_{C} vs centrality", kTH3F, {{centAxis}, {qAxis}, {q1Axis}}); histos.add("hpQxAQxC", "QxA QxC", kTH2F, {{centAxis}, {resAxis}}); histos.add("hpQyAQyC", "QyA QyC", kTH2F, {{centAxis}, {resAxis}}); histos.add("hpQxAQyC", "QxA QyC", kTH2F, {{centAxis}, {resAxis}}); @@ -394,7 +395,7 @@ struct flowDirectedFlowTask { if (acc <= 0.0 || !std::isfinite(acc)) { return 1.0; } - return 1.0 / acc; + return acc; } template @@ -525,6 +526,7 @@ struct flowDirectedFlowTask { float resDot = dotAC / (magA * magC); histos.fill(HIST("hpResCosAC"), centrality, std::cos(psiA - psiC), q1); + histos.fill(HIST("hpDotAC"), centrality, dotAC, q1); histos.fill(HIST("hpResDotAC"), centrality, resDot, q1); histos.fill(HIST("hpQxAQxC"), centrality, qxA * qxC); histos.fill(HIST("hpQyAQyC"), centrality, qyA * qyC); From 08813044dd552be7b3c0f13bc2bb714f51f085c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 2 Jun 2026 08:44:28 +0200 Subject: [PATCH 382/449] [PWGCF] Fix includes (#16410) --- PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx | 1 + PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx | 3 --- .../FemtoNuclei/TableProducer/HadNucleiFemto.cxx | 1 - .../femtoUniversePairTaskTrackCascadeExtended.cxx | 2 -- PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx | 11 +---------- PWGCF/Flow/Tasks/flowEseTask.cxx | 1 + PWGCF/Flow/Tasks/flowEventPlane.cxx | 2 ++ PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 4 +++- .../Tasks/multiharmonicCorrelations.cxx | 4 +++- .../DataModel/LongRangeDerived.h | 2 -- .../Tasks/lambdaR2Correlation.cxx | 3 ++- 11 files changed, 13 insertions(+), 21 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index 035f457193f..f01ce200c9b 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index 3241efacbc6..1fd39ebf2fc 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -38,11 +37,9 @@ #include #include -#include #include #include #include -#include #include #include #include diff --git a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx index 97708e877e2..e8249c71141 100644 --- a/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx +++ b/PWGCF/Femto/FemtoNuclei/TableProducer/HadNucleiFemto.cxx @@ -56,7 +56,6 @@ #include #include -#include #include #include diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 9b9ddbb7d64..f8520957e86 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -19,12 +19,10 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" #include #include diff --git a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx index a48bb41bbe4..834bbc2177b 100644 --- a/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx +++ b/PWGCF/Flow/Tasks/flowDirectedFlowTask.cxx @@ -14,13 +14,11 @@ /// \brief Task for q1-dependent directed flow and global polarization /// \since May 2026 -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/SPCalibrationTables.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -28,7 +26,6 @@ #include "Common/DataModel/TrackSelectionTables.h" #include -#include #include #include #include @@ -37,19 +34,14 @@ #include #include #include -#include #include #include #include -#include -#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include -#include -#include #include -#include #include #include @@ -57,7 +49,6 @@ #include #include #include -#include #include using namespace o2; diff --git a/PWGCF/Flow/Tasks/flowEseTask.cxx b/PWGCF/Flow/Tasks/flowEseTask.cxx index 4f6ee235114..5b091a8c200 100644 --- a/PWGCF/Flow/Tasks/flowEseTask.cxx +++ b/PWGCF/Flow/Tasks/flowEseTask.cxx @@ -58,6 +58,7 @@ #include #include #include +#include #include #include diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index 09e4caa8a0a..43459c95606 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -47,7 +47,9 @@ #include #include +#include #include +#include #include #include #include diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 983b3ef07bc..d3afbfe1963 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -44,14 +44,16 @@ #include #include -#include #include #include +#include #include #include +#include #include +#include #include #include diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx index 37529852836..3dffbefed98 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiharmonicCorrelations.cxx @@ -31,11 +31,13 @@ #include #include #include +#include #include #include #include -#include +#include + #include #include #include diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index 583e33019c4..62f906a38ae 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -21,9 +21,7 @@ #include "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include #include #include diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 45e9d661d4d..ffeeeb323c9 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -16,12 +16,12 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -46,6 +46,7 @@ #include #include +#include #include #include #include From d54ecb30d6f576f9cb7206de9d90dc27eb32fc3d Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:00:36 +0200 Subject: [PATCH 383/449] [PWGCF] Fix in femto framework (#16496) --- PWGCF/Femto/Core/collisionBuilder.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 74307f62f13..7eababf75a5 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -569,16 +569,17 @@ class CollisionBuilder if (mProducedSphericities) { collisionProducts.producedSphericities(mCollisionSelection.getSphericity()); } + if (mProducedMultiplicities) { + collisionProducts.producedMultiplicityEstimators( + col.multFT0A(), + col.multFT0C(), + col.multNTracksPVeta1(), + col.multNTracksPVetaHalf(), + col.trackOccupancyInTimeRange(), + col.ft0cOccupancyInTimeRange()); + } + // TODO: enable later for better QA - // if (mProducedMultiplicities) { - // collisionProducts.producedMultiplicityEstimators( - // col.multFT0A(), - // col.multFT0C(), - // col.multNTracksPVeta1(), - // col.multNTracksPVetaHalf(), - // col.trackOccupancyInTimeRange(), - // col.ft0cOccupancyInTimeRange()); - // } // if (mProducedCentralities) { // collisionProducts.producedCentralityEstimators( // col.centFT0A(), From 25d6fdb31fecc99217759cab8f716195681210d4 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:47:31 +0200 Subject: [PATCH 384/449] [PWGLF] moved to unordered_set (#16482) --- PWGLF/TableProducer/QC/nucleiQC.cxx | 199 +++++++++++++--------------- 1 file changed, 95 insertions(+), 104 deletions(-) diff --git a/PWGLF/TableProducer/QC/nucleiQC.cxx b/PWGLF/TableProducer/QC/nucleiQC.cxx index eb35cb15ec6..6e8c7569bb9 100644 --- a/PWGLF/TableProducer/QC/nucleiQC.cxx +++ b/PWGLF/TableProducer/QC/nucleiQC.cxx @@ -61,6 +61,7 @@ #include #include #include +#include #include using namespace o2; @@ -156,6 +157,7 @@ struct nucleiQC { std::shared_ptr mHistTrackTunedTracks = mHistograms.get(HIST("hTrackTunedTracks")); std::vector mSpeciesToProcess; + std::array mFillSpecies{false}; Produces mNucleiTableRed; Produces mNucleiTableExt; @@ -169,6 +171,7 @@ struct nucleiQC { o2::dataformats::VertexBase mVtx; o2::track::TrackParametrizationWithError mTrackParCov; std::array(nuclei::Species::kNspecies)> mPidManagers; + bool mAnyTrackTuner = false; void init(o2::framework::InitContext&) { @@ -177,22 +180,24 @@ struct nucleiQC { mCcdb->setCaching(true); mCcdb->setLocalObjectValidityChecking(); mCcdb->setFatalWhenNull(false); - nuclei::lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(mCcdb->get("GLO/Param/MatLUT")); + // nuclei::lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(mCcdb->get("GLO/Param/MatLUT")); for (int iSel = 0; iSel < nuclei::evSel::kNevSels; iSel++) { mHistograms.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(iSel + 1, nuclei::eventSelectionLabels[iSel].c_str()); } for (int iSpecies = 0; iSpecies < static_cast(nuclei::Species::kNspecies); iSpecies++) { - if (cfgSpeciesToProcess->get(iSpecies) == 1) + if (cfgSpeciesToProcess->get(iSpecies) == 1) { mSpeciesToProcess.emplace_back(iSpecies); + mFillSpecies[iSpecies] = true; + } } static_for<0, nuclei::kNspecies - 1>([&](auto iSpecies) { constexpr int kSpeciesCt = decltype(iSpecies)::value; const int kSpeciesRt = kSpeciesCt; - if (std::find(mSpeciesToProcess.begin(), mSpeciesToProcess.end(), kSpeciesCt) == mSpeciesToProcess.end()) + if (!mFillSpecies[kSpeciesCt]) return; float tpcBetheBlochParams[6]; @@ -214,12 +219,12 @@ struct nucleiQC { }); /// TrackTuner initialization - bool anyTrackTuner = false; + mAnyTrackTuner = false; for (int iSpecies = 0; iSpecies < static_cast(nuclei::Species::kNspecies); iSpecies++) { - anyTrackTuner = anyTrackTuner || cfgUseTrackTuner->get(iSpecies); + mAnyTrackTuner = mAnyTrackTuner || cfgUseTrackTuner->get(iSpecies); } - if (anyTrackTuner) { + if (mAnyTrackTuner) { std::string outputStringParams = ""; switch (cfgTrackTunerConfigSource) { case aod::track_tuner::InputString: @@ -251,13 +256,17 @@ struct nucleiQC { o2::parameters::GRPMagField* grpmag = mCcdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); o2::base::Propagator::initFieldFromGRP(grpmag); - o2::base::Propagator::Instance()->setMatLUT(nuclei::lut); + // o2::base::Propagator::Instance()->setMatLUT(nuclei::lut); + if (!o2::base::Propagator::Instance()->getMatLUT()) { + nuclei::lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(mCcdb->get("GLO/Param/MatLUT")); + o2::base::Propagator::Instance()->setMatLUT(nuclei::lut); + } mBz = static_cast(grpmag->getNominalL3Field()); LOGF(info, "Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG", timestamp, mRunNumber, mBz); } - template - bool trackSelection(const Ttrack& track, const Tcollision& collision) + template + bool trackSelection(const Ttrack& track) { mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNoCuts); @@ -289,13 +298,24 @@ struct nucleiQC { return false; mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kItsChi2Cut); - const o2::math_utils::Point3D collisionVertex{collision.posX(), collision.posY(), collision.posZ()}; mDcaInfoCov.set(999, 999, 999, 999, 999); setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); - std::array dcaInfo; - o2::base::Propagator::Instance()->propagateToDCA(collisionVertex, mTrackParCov, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfo); - if (std::abs(dcaInfo[0]) > cfgCutDCAxy || std::abs(dcaInfo[1]) > cfgCutDCAz) + + if constexpr (isMc) { + if (track.has_mcParticle() && cfgUseTrackTuner->get(iSpecies)) { + const auto& particle = track.mcParticle(); + mHistTrackTunedTracks->Fill(1.); + mTrackTuner.tuneTrackParams(particle, mTrackParCov, mMatCorr, &mDcaInfoCov, mHistTrackTunedTracks); + } + } else { + mMatCorr = static_cast(cfgMaterialCorrection.value); + } + + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, mTrackParCov, 2.f, mMatCorr, &mDcaInfoCov); + mDcaInfo[0] = mDcaInfoCov.getY(); + mDcaInfo[1] = mDcaInfoCov.getZ(); + if (std::abs(mDcaInfo[0]) > cfgCutDCAxy || std::abs(mDcaInfo[1]) > cfgCutDCAz) return false; mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kDcaCuts); @@ -365,9 +385,9 @@ struct nucleiQC { } template - void fillCollisionFlag(const Tparticle& particle, nuclei::SlimCandidate& candidate, const std::vector& reconstructedCollision) + void fillCollisionFlag(const Tparticle& particle, nuclei::SlimCandidate& candidate, const std::unordered_set& reconstructedCollision) { - if (reconstructedCollision[particle.mcCollisionId()]) { + if (reconstructedCollision.count(particle.mcCollisionId()) > 0) { candidate.flags |= nuclei::QcFlags::kQcHasReconstructedCollision; } } @@ -396,31 +416,6 @@ struct nucleiQC { candidate.phiGenerated = particle.phi(); } - template - void fillDcaInformation(const int iSpecies, const Tcollision& collision, const Ttrack& track, nuclei::SlimCandidate& candidate, const aod::McParticles::iterator& particle) - { - - mDcaInfoCov.set(999, 999, 999, 999, 999); - setTrackParCov(track, mTrackParCov); - mTrackParCov.setPID(track.pidForTracking()); - - if constexpr (isMc) { - if (track.has_mcParticle() && cfgUseTrackTuner->get(iSpecies)) { - mHistTrackTunedTracks->Fill(1.); - mTrackTuner.tuneTrackParams(particle, mTrackParCov, mMatCorr, &mDcaInfoCov, mHistTrackTunedTracks); - } - } else { - mMatCorr = static_cast(cfgMaterialCorrection.value); - } - - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, mTrackParCov, 2.f, mMatCorr, &mDcaInfoCov); - - candidate.DCAxy = mDcaInfoCov.getY(); - candidate.DCAz = mDcaInfoCov.getZ(); - } - template nuclei::SlimCandidate fillCandidate(const int iSpecies, Tcollision const& collision, Ttrack const& track) { @@ -434,8 +429,8 @@ struct nucleiQC { .clusterSizesITS = track.itsClusterSizes(), .TPCsignal = track.tpcSignal(), .beta = mPidManagers[iSpecies].getBetaTOF(track), - .DCAxy = 0.f, - .DCAz = 0.f, + .DCAxy = mDcaInfo[0], // set in the track selection function + .DCAz = mDcaInfo[1], // set in the track selection function .flags = 0, .pdgCode = 0, .motherPdgCode = 0, @@ -450,19 +445,15 @@ struct nucleiQC { fillNucleusFlagsPdgs(collision, track, candidate); - aod::McParticles::iterator particle; - if constexpr (isMc) { if (track.has_mcParticle()) { - particle = track.mcParticle(); + const auto& particle = track.mcParticle(); fillNucleusFlagsPdgsMc(particle, candidate); fillNucleusGeneratedVariables(particle, candidate); } } - fillDcaInformation(iSpecies, collision, track, candidate, particle); - return candidate; } @@ -510,12 +501,36 @@ struct nucleiQC { } } - void processMc(const Collisions& collisions, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles, const aod::McCollisions& mcCollisions) + void writeCandidate(const nuclei::SlimCandidate& candidate) + { + if (!cfgFillTable) + return; + + mNucleiTableRed( + candidate.pt, + candidate.eta, + candidate.phi, + candidate.tpcInnerParam, + candidate.clusterSizesITS, + candidate.TPCsignal, + candidate.beta, + candidate.DCAxy, + candidate.DCAz, + candidate.flags, + candidate.ptGenerated, + candidate.mcProcess, + candidate.pdgCode, + candidate.motherPdgCode); + mNucleiTableExt( + candidate.nsigmaTpc, + candidate.nsigmaTof); + } + + void processMc(const Collisions& collisions, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles, const aod::McCollisions& /*mcCollisions*/) { gRandom->SetSeed(67); - mNucleiCandidates.clear(); - std::vector reconstructedMcParticles(mcParticles.size(), false); - std::vector reconstructedCollisions(mcCollisions.size(), false); + std::unordered_set reconstructedMcParticles; + std::unordered_set reconstructedCollisions; for (const auto& collision : collisions) { @@ -525,13 +540,11 @@ struct nucleiQC { if (!nuclei::eventSelection(collision, mHistograms, cfgEventSelections, cfgCutVertex)) continue; mHistograms.fill(HIST("hCentrality"), nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality)); - reconstructedCollisions[collision.mcCollisionId()] = true; + reconstructedCollisions.insert(collision.mcCollisionId()); + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - bool anyTrackTuner = false; - for (int iSpecies = 0; iSpecies < static_cast(nuclei::Species::kNspecies); iSpecies++) { - anyTrackTuner = anyTrackTuner || cfgUseTrackTuner->get(iSpecies); - } - if (anyTrackTuner && mTrackTuner.autoDetectDcaCalib && !mTrackTuner.areGraphsConfigured) { + if (mAnyTrackTuner && mTrackTuner.autoDetectDcaCalib && !mTrackTuner.areGraphsConfigured) { mTrackTuner.setRunNumber(mRunNumber); @@ -544,38 +557,41 @@ struct nucleiQC { auto tracksThisCollision = tracks.sliceBy(mTracksPerCollision, collision.globalIndex()); for (const auto& track : tracksThisCollision) { - static_for<0, nuclei::kNspecies - 1>([&](auto iSpecies) { - constexpr int kSpeciesCt = decltype(iSpecies)::value; - const int kSpeciesRt = kSpeciesCt; + // selections shared among all species + if (!track.has_mcParticle()) + continue; - if (std::find(mSpeciesToProcess.begin(), mSpeciesToProcess.end(), kSpeciesRt) == mSpeciesToProcess.end()) - return; + if (track.mcParticleId() < -1 || track.mcParticleId() >= mcParticles.size()) + continue; + const auto& particle = mcParticles.iteratorAt(track.mcParticleId()); - if (!track.has_mcParticle()) - return; + if (cfgRapidityToggle && ((particle.y() - cfgRapidityCenterMass) < cfgRapidityMin || (particle.y() - cfgRapidityCenterMass) > cfgRapidityMax)) + continue; + + if (cfgFillOnlyPhysicalPrimaries && !particle.isPhysicalPrimary()) + continue; - if (track.mcParticleId() < -1 || track.mcParticleId() >= mcParticles.size()) + // species-specific selections and filling + static_for<0, nuclei::kNspecies - 1>([&](auto iSpecies) { + constexpr int kSpeciesCt = decltype(iSpecies)::value; + const int kSpeciesRt = kSpeciesCt; + if (!mFillSpecies[kSpeciesCt]) return; - const auto& particle = mcParticles.iteratorAt(track.mcParticleId()); if (cfgDoCheckPdgCode) { if (std::abs(particle.pdgCode()) != nuclei::pdgCodes[kSpeciesRt]) return; } + mDcaInfo = {-999.f, -999.f}; + if (cfgDownscalingFactor->get(kSpeciesRt) < 1.) { if ((gRandom->Uniform()) > cfgDownscalingFactor->get(kSpeciesRt)) return; } - if (cfgRapidityToggle && ((particle.y() - cfgRapidityCenterMass) < cfgRapidityMin || (particle.y() - cfgRapidityCenterMass) > cfgRapidityMax)) - return; - - if (cfgFillOnlyPhysicalPrimaries && !particle.isPhysicalPrimary()) - return; - mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kNoCuts); - if (!trackSelection(track, collision)) + if (!trackSelection(track)) return; mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kTrackCuts); @@ -587,8 +603,8 @@ struct nucleiQC { candidate = fillCandidate(kSpeciesCt, collision, track); fillCollisionFlag(particle, candidate, reconstructedCollisions); - mNucleiCandidates.emplace_back(candidate); - reconstructedMcParticles[particle.globalIndex()] = true; + writeCandidate(candidate); + reconstructedMcParticles.insert(particle.globalIndex()); dispatchFillHistograms(kSpeciesRt, candidate); dispatchFillHistograms(kSpeciesRt, candidate); @@ -600,15 +616,14 @@ struct nucleiQC { for (const auto& particle : mcParticles) { mcIndex++; - int iSpecies = nuclei::getSpeciesFromPdg(particle.pdgCode()); - if (std::find(mSpeciesToProcess.begin(), mSpeciesToProcess.end(), iSpecies) == mSpeciesToProcess.end()) + if (!mFillSpecies[iSpecies]) continue; - if ((particle.y() - cfgRapidityCenterMass) < cfgRapidityMin || (particle.y() - cfgRapidityCenterMass) > cfgRapidityMax) + if (reconstructedMcParticles.count(mcIndex) > 0) continue; - if (reconstructedMcParticles[mcIndex]) + if ((particle.y() - cfgRapidityCenterMass) < cfgRapidityMin || (particle.y() - cfgRapidityCenterMass) > cfgRapidityMax) continue; if (cfgFillOnlyPhysicalPrimaries && !particle.isPhysicalPrimary()) @@ -626,34 +641,10 @@ struct nucleiQC { fillNucleusFlagsPdgsMc(particle, candidate); fillNucleusGeneratedVariables(particle, candidate); - mNucleiCandidates.emplace_back(candidate); + writeCandidate(candidate); mFilledMcParticleIds.emplace_back(particle.globalIndex()); dispatchFillHistograms(iSpecies, candidate); } - - if (!cfgFillTable) - return; - - for (const auto& candidate : mNucleiCandidates) { - mNucleiTableRed( - candidate.pt, - candidate.eta, - candidate.phi, - candidate.tpcInnerParam, - candidate.clusterSizesITS, - candidate.TPCsignal, - candidate.beta, - candidate.DCAxy, - candidate.DCAz, - candidate.flags, - candidate.ptGenerated, - candidate.mcProcess, - candidate.pdgCode, - candidate.motherPdgCode); - mNucleiTableExt( - candidate.nsigmaTpc, - candidate.nsigmaTof); - } } PROCESS_SWITCH(nucleiQC, processMc, "Mc analysis", false); }; From 084fc6f66d5861bf3ec903371c4f13807c789261 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 2 Jun 2026 10:20:37 +0200 Subject: [PATCH 385/449] [PWGDQ] use chi2 in match features analysis (#16498) --- PWGDQ/Tasks/qaMatching.cxx | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index 44e003bfa85..e7de1e7f2b0 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -679,14 +679,14 @@ struct QaMatching { o2::framework::HistPtr hDeltaEta; o2::framework::HistPtr hRabs; - MatchFeaturesHistos(std::string path, HistogramRegistry* registry, int numCandidates) + MatchFeaturesHistos(std::string path, HistogramRegistry* registry, int numCandidates, double scoreMax) { AxisSpec indexAxis = {numCandidates, 0, static_cast(numCandidates), "ranking index"}; - AxisSpec scoreAxis = {100, 0, 1, "match score"}; int matchTypeMax = static_cast(kMatchTypeUndefined) + 1; AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; AxisSpec taggedAxis = {2, 0, 2.0, "is tagged"}; - AxisSpec scoreGapAxis = {100, 0, 1.0, "match score gap"}; + AxisSpec scoreAxis = {100, 0, scoreMax, "match score"}; + AxisSpec scoreGapAxis = {100, 0, scoreMax, "match score gap"}; AxisSpec logpAxis = {16, -1, 3, "log_{10}(p)"}; AxisSpec dxAxis = {100, -20, 20, "#Deltax (cm)"}; AxisSpec dyAxis = {100, -20, 20, "#Deltay (cm)"}; @@ -818,7 +818,7 @@ struct QaMatching { std::string histName; std::string histTitle; - fMatchFeaturesGoodMCH = std::make_unique(path + "matchFeaturesGoodMCH", registry, numCandidates); + fMatchFeaturesGoodMCH = std::make_unique(path + "matchFeaturesGoodMCH", registry, numCandidates, 100); if (isMc) { fMatchRanking = std::make_unique(path + "matchRanking", "True match ranking", registry, mftMultMax, numCandidates); @@ -2179,13 +2179,13 @@ struct QaMatching { isTagged = 1; } - float scoreGap = 0; + float chi2Gap = 0; if (globalTracksVector.size() > 1) { // we have at least two candidates, so we can check the score difference // between the leading and the sub-leading - auto leadingScore = globalTracksVector[0].matchScore; - auto subleadingScore = globalTracksVector[1].matchScore; - scoreGap = leadingScore - subleadingScore; + auto leadingChi2 = globalTracksVector[0].matchChi2; + auto subleadingChi2 = globalTracksVector[1].matchChi2; + chi2Gap = subleadingChi2 - leadingChi2; } for (const auto& candidate : globalTracksVector) { @@ -2198,14 +2198,14 @@ struct QaMatching { double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); int matchType = static_cast(candidate.matchType); int ranking = candidate.matchRanking - 1; - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); } } @@ -2344,13 +2344,13 @@ struct QaMatching { isTagged = 1; } - float scoreGap = 0; - if (globalTracksVector.size()) { - // we have a matchable pair with at least two candidates, so we can check the score difference + float chi2Gap = 0; + if (globalTracksVector.size() > 1) { + // we have at least two candidates, so we can check the score difference // between the leading and the sub-leading - auto leadingScore = globalTracksVector[0].matchScore; - auto subleadingScore = globalTracksVector[1].matchScore; - scoreGap = leadingScore - subleadingScore; + auto leadingChi2 = globalTracksVector[0].matchChi2; + auto subleadingChi2 = globalTracksVector[1].matchChi2; + chi2Gap = subleadingChi2 - leadingChi2; } for (const auto& candidate : globalTracksVector) { @@ -2363,14 +2363,14 @@ struct QaMatching { double deta = candidate.mchTrackProp.getEta() - candidate.mftTrackProp.getEta(); int matchType = static_cast(candidate.matchType); int ranking = candidate.matchRanking - 1; - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); - std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchScore, scoreGap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaP)->Fill(dp, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPt)->Fill(dpt, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaX)->Fill(dx, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaY)->Fill(dy, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaPhi)->Fill(dphi, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaTanl)->Fill(dtanl, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hDeltaEta)->Fill(deta, logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); + std::get>(plotter->fMatchFeaturesGoodMCH->hRabs)->Fill(mchTrack.rAtAbsorberEnd(), logp, candidate.matchChi2, chi2Gap, ranking, matchType, isTagged); } } From a92188d9c640ecb1796dab48b41bc03d0291fe5d Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:47:05 +0200 Subject: [PATCH 386/449] [PWGCF] Changes to resonance efficiencies (#16466) --- .../Tasks/flowGenericFramework.cxx | 219 +++++++++++------- 1 file changed, 129 insertions(+), 90 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 6f25a702eea..25b4ef4d963 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -161,8 +161,10 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFractionWeights, bool, false, "Enable or disable the use of multiplicity-based event weighting for the spectral fraction"); } cfgEventWeight; - O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgUsePIDEfficiencies, bool, false, "Use species dependent efficiencies") + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUsePIDEfficiencies, bool, false, "Use species dependent efficiencies") + O2_DEFINE_CONFIGURABLE(cfgUse2DEfficiency, bool, false, "Toggle the use of 2D (pt, centrality) efficiency versus centrality integrated efficiency")} cfgEfficiency; O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)"); @@ -175,7 +177,8 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); - O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0105 + 0.0350/(x^1.1))", "Functional form of pt-dependent 7 sigma DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAxyPtDep, std::string, "(0.0105 + 0.0350/(x^1.1))", "Functional form of pt-dependent 7 sigma DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzPtDep, std::string, "(0.0105 + 0.0350/(x^1.1))", "Functional form of pt-dependent DCAz cut"); O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 50, "Cut on number of TPC clusters found"); O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); @@ -259,8 +262,8 @@ struct FlowGenericFramework { o2::aod::ITSResponse itsResponse; struct Config { - TH1D* mEfficiency = nullptr; - std::vector mPIDEfficiencies; + TH1* mEfficiency = nullptr; + std::vector mPIDEfficiencies; std::vector mAcceptance; bool correctionsLoaded = false; } cfg; @@ -451,8 +454,9 @@ struct FlowGenericFramework { TF1* fPhiCutLow = nullptr; TF1* fPhiCutHigh = nullptr; - // Track selection - DCA xy function + // Track selection - DCA functions TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; void init(InitContext const&) { @@ -571,9 +575,14 @@ struct FlowGenericFramework { registryQA.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); registryQA.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registryQA.addClone("MCGen/before/", "MCGen/after/"); + registry.add("MCGen/after/pt_centrality_K0_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("MCGen/after/pt_centrality_K0_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("MCGen/after/pt_centrality_Lambda_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_Lambda_proton_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_Lambda_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_ch_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("MCGen/after/pt_centrality_pion_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("MCGen/after/pt_centrality_kaon_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("MCGen/after/pt_centrality_proton_gen", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); if (doprocessOnTheFly) registryQA.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); @@ -599,9 +608,14 @@ struct FlowGenericFramework { registryQA.add("trackQA/after/etaPtPt", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); registryQA.add("trackQA/after/etaV0Daughters", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); if (doprocessMCReco) { + registry.add("trackQA/after/pt_centrality_K0", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("trackQA/after/pt_centrality_K0_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_Lambda", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("trackQA/after/pt_centrality_Lambda_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_ch", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_Lambda_proton", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("trackQA/after/pt_centrality_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("trackQA/after/pt_centrality_kaon", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("trackQA/after/pt_centrality_proton", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); } if (!cfgFill.cfgFillRunByRunQA) { @@ -780,9 +794,13 @@ struct FlowGenericFramework { fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); fFCpt->initialiseSubevent(multAxis, cfgMpar, o2::analysis::gfw::etagapsPtPt.size(), cfgNbootstrap); - fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgTrackCuts.cfgDCAxy->c_str()), 0.001, 100); + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgTrackCuts.cfgDCAxyPtDep->c_str()), 0.001, 100); fPtDepDCAxy->SetParameter(0, cfgTrackCuts.cfgDCAxyNSigma / 7.); - LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgTrackCuts.cfgDCAxy->c_str())); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgTrackCuts.cfgDCAxyPtDep->c_str())); + if (!cfgTrackCuts.cfgDCAzPtDep.value.empty()) { + fPtDepDCAz = new TF1("ptDepDCAz", Form("%s", cfgTrackCuts.cfgDCAzPtDep->c_str()), 0.001, 100); + LOGF(info, "DCAz pt-dependence function: %s", Form("%s", cfgTrackCuts.cfgDCAzPtDep->c_str())); + } // Multiplicity correlation cuts if (cfgMultCut) { @@ -979,20 +997,26 @@ struct FlowGenericFramework { // Run-by-run efficiencies are not supported at the moment if (cfg.correctionsLoaded) return; - if (!cfgEfficiency.value.empty()) { - if (!cfgUsePIDEfficiencies) { - cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (!cfgEfficiency.cfgEfficiencyPath.value.empty()) { + if (!cfgEfficiency.cfgUsePIDEfficiencies) { + if (cfgEfficiency.cfgUse2DEfficiency) + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency.cfgEfficiencyPath, timestamp); + else + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency.cfgEfficiencyPath, timestamp); if (cfg.mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.cfgEfficiencyPath.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.cfgEfficiencyPath.value.c_str(), (void*)cfg.mEfficiency); } else { - std::vector species = {"ch", "pi", "ka", "pr"}; + std::vector species = {"ch", "pi", "ka", "pr", "k0", "lambda"}; for (const auto& sp : species) { - cfg.mPIDEfficiencies.push_back(ccdb->getForTimeStamp(cfgEfficiency.value + "/" + sp, timestamp)); + if (cfgEfficiency.cfgUse2DEfficiency) + cfg.mPIDEfficiencies.push_back(ccdb->getForTimeStamp(cfgEfficiency.cfgEfficiencyPath.value + "/" + sp, timestamp)); + else + cfg.mPIDEfficiencies.push_back(ccdb->getForTimeStamp(cfgEfficiency.cfgEfficiencyPath.value + "/" + sp, timestamp)); if (cfg.mPIDEfficiencies.back() == nullptr) - LOGF(fatal, "Could not load PID efficiency histograms from %s", cfgEfficiency.value + "/" + sp); - LOGF(info, "Loaded PID efficiency histogram from %s", cfgEfficiency.value + "/" + sp); + LOGF(fatal, "Could not load PID efficiency histograms from %s", cfgEfficiency.cfgEfficiencyPath.value + "/" + sp); + LOGF(info, "Loaded PID efficiency histogram from %s", cfgEfficiency.cfgEfficiencyPath.value + "/" + sp); } } } @@ -1009,14 +1033,19 @@ struct FlowGenericFramework { } template - double getEfficiency(TTrack track, int pidIndex = 0) - { //-1 ref, 0 ch, 1 pi, 2 ka, 3 pr + double getEfficiency(TTrack track, const float& centrality, int pidIndex = 0) + { //-1 ref, 0 ch, 1 pi, 2 ka, 3 pr, 4 k0, 5 lambda double eff = 1.; - if (!cfgUsePIDEfficiencies) { - if (cfg.mEfficiency) - eff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + if (!cfgEfficiency.cfgUsePIDEfficiencies) { + if (cfgEfficiency.cfgUse2DEfficiency) + eff = dynamic_cast(cfg.mEfficiency)->GetBinContent(dynamic_cast(cfg.mEfficiency)->FindBin(track.pt(), centrality)); + else + eff = dynamic_cast(cfg.mEfficiency)->GetBinContent(dynamic_cast(cfg.mEfficiency)->FindBin(track.pt())); } else { - eff = cfg.mPIDEfficiencies[pidIndex]->GetBinContent(cfg.mPIDEfficiencies[pidIndex]->FindBin(track.pt())); + if (cfgEfficiency.cfgUse2DEfficiency) + eff = dynamic_cast(cfg.mPIDEfficiencies[pidIndex])->GetBinContent(dynamic_cast(cfg.mPIDEfficiencies[pidIndex])->FindBin(track.pt(), centrality)); + else + eff = dynamic_cast(cfg.mPIDEfficiencies[pidIndex])->GetBinContent(dynamic_cast(cfg.mPIDEfficiencies[pidIndex])->FindBin(track.pt())); } if (eff == 0) return -1.; @@ -1211,6 +1240,8 @@ struct FlowGenericFramework { } if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > fPtDepDCAxy->Eval(track.pt()))) return false; + if (!cfgTrackCuts.cfgDCAzPtDep.value.empty() && std::fabs(track.dcaZ() > fPtDepDCAz->Eval(track.pt()))) + return false; return ((track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgNTPCXrows) && (track.tpcNClsFound() >= cfgTrackCuts.cfgNTPCCls) && (track.itsNCls() >= cfgTrackCuts.cfgMinNITSCls)); } @@ -1221,6 +1252,8 @@ struct FlowGenericFramework { const float defaultNsigma = 7; if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > defaultNsigma / cfgTrackCuts.cfgDCAxyNSigma * fPtDepDCAxy->Eval(track.pt()))) return false; + if (!cfgTrackCuts.cfgDCAzPtDep.value.empty() && std::fabs(track.dcaZ() > fPtDepDCAz->Eval(track.pt()))) + return false; int tpcNClsCrossedRowsDefault = 70; int tpcNClsFoundDefault = 50; int itsNclsDefault = 5; @@ -1504,7 +1537,7 @@ struct FlowGenericFramework { for (const auto& h : histosNpt) h->Reset("ICESM"); for (const auto& track : tracks) { - processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); + processTrack(track, vtxz, field, run, densitycorrections, centrality, acceptedTracks); } if (dt != Gen && cfgFill.cfgFillQA) { registryQA.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); @@ -1541,7 +1574,16 @@ struct FlowGenericFramework { for (const auto& v0 : v0s) { if (resoSwitchVals[UseParticle][K0]) { double weff = 1; - if (selectK0(collision, v0, tracks, centrality, weff)) { + if (selectK0(collision, v0, tracks, centrality)) { + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("K0/hK0s"), 0.5, 1); + if (cfgEfficiency.cfgUsePIDEfficiencies) { + weff = getEfficiency(v0, centrality, 4); + if (weff < 0) + continue; + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); + } if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) histosResoNpt[K0Sideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) @@ -1552,7 +1594,16 @@ struct FlowGenericFramework { } if (resoSwitchVals[UseParticle][Lambda]) { double weff = 1.; - if (selectLambda(collision, v0, tracks, centrality, weff)) { + if (selectLambda(collision, v0, tracks, centrality)) { + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("Lambda/hLambdas"), 0.5, 1); + if (cfgEfficiency.cfgUsePIDEfficiencies) { + weff = getEfficiency(v0, centrality, 5); + if (weff < 0) + continue; + if (cfgFill.cfgFillQA) + registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); + } if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) histosResoNpt[LambdaSideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) @@ -1564,6 +1615,8 @@ struct FlowGenericFramework { } } else { for (const auto& particle : tracks) { + if (!particle.isPhysicalPrimary()) + continue; if (!particle.has_daughters()) continue; @@ -1573,10 +1626,14 @@ struct FlowGenericFramework { if (!isK0 && !isLambda) continue; - if (isK0) + if (isK0) { histosResoNpt[K0Signal]->Fill(particle.pt(), 1.0); - if (isLambda) + registry.fill(HIST("MCGen/after/pt_centrality_K0_gen"), particle.pt(), centrality); + } + if (isLambda) { histosResoNpt[LambdaSignal]->Fill(particle.pt(), 1.0); + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_gen"), particle.pt(), centrality); + } // For efficiency for (const auto& d : particle.template daughters_as()) { @@ -1585,10 +1642,9 @@ struct FlowGenericFramework { registry.fill(HIST("MCGen/after/pt_centrality_K0_pion_gen"), d.pt(), centrality); if (isLambda) registry.fill(HIST("MCGen/after/pt_centrality_Lambda_pion_gen"), d.pt(), centrality); - registry.fill(HIST("MCGen/after/pt_centrality_pion_gen"), d.pt(), centrality); } if (std::abs(d.pdgCode()) == PDG_t::kProton) - registry.fill(HIST("MCGen/after/pt_centrality_proton_gen"), d.pt(), centrality); + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_proton_gen"), d.pt(), centrality); } } } @@ -1676,26 +1732,22 @@ struct FlowGenericFramework { } template - inline void processTrack(TTrack const& track, const float& vtxz, const int field, const int run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) + inline void processTrack(TTrack const& track, const float& vtxz, const int field, const int run, DensityCorr densitycorrections, const float& centrality, AcceptedTracks& acceptedTracks) { if constexpr (framework::has_type_v) { if (track.mcParticleId() < 0 || !(track.has_mcParticle())) return; - auto mcParticle = track.mcParticle(); if (!mcParticle.isPhysicalPrimary()) return; if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); - if (mcParticle.eta() < o2::analysis::gfw::etalow || mcParticle.eta() > o2::analysis::gfw::etaup || mcParticle.pt() < o2::analysis::gfw::ptlow || mcParticle.pt() > o2::analysis::gfw::ptup) return; - // Select tracks with nominal cuts always if (!nchSelected(track)) return; - - double weffCh = getEfficiency(track, 0); + double weffCh = getEfficiency(track, centrality, 0); if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { if (weffCh > 0) acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; @@ -1704,17 +1756,23 @@ struct FlowGenericFramework { if (!trackSelected(track, field)) return; + registry.fill(HIST("trackQA/after/pt_centrality_ch"), track.pt(), centrality); int pidIndex = 0; - if (std::abs(mcParticle.pdgCode()) == kPiPlus) + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { pidIndex = PionID; - if (std::abs(mcParticle.pdgCode()) == kKPlus) + registry.fill(HIST("trackQA/after/pt_centrality_pion"), track.pt(), centrality); + } + if (std::abs(mcParticle.pdgCode()) == kKPlus) { pidIndex = KaonID; - if (std::abs(mcParticle.pdgCode()) == kProton) + registry.fill(HIST("trackQA/after/pt_centrality_kaon"), track.pt(), centrality); + } + if (std::abs(mcParticle.pdgCode()) == kProton) { pidIndex = ProtonID; - + registry.fill(HIST("trackQA/after/pt_centrality_proton"), track.pt(), centrality); + } if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { - double weff = getEfficiency(track, pidIndex); + double weff = getEfficiency(track, centrality, pidIndex); if (weffCh > 0) histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); @@ -1725,14 +1783,12 @@ struct FlowGenericFramework { if (pidIndex == ProtonID && weff > 0) histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); } - if (cfgFill.cfgFillWeights) { fillWeights(mcParticle, vtxz, 0, run); } else { - fillPtSums(track, vtxz); - fillGFW(mcParticle, vtxz, pidIndex, densitycorrections); + fillPtSums(track, centrality, vtxz); + fillGFW(mcParticle, centrality, vtxz, pidIndex, densitycorrections); } - if (cfgFill.cfgFillQA) { fillTrackQA(track, vtxz); if (cfgFill.cfgFillRunByRunQA) { @@ -1748,13 +1804,21 @@ struct FlowGenericFramework { fillTrackQA(track, vtxz); if (track.eta() < o2::analysis::gfw::etalow || track.eta() > o2::analysis::gfw::etaup || track.pt() < o2::analysis::gfw::ptlow || track.pt() > o2::analysis::gfw::ptup) return; + + registry.fill(HIST("MCGen/after/pt_centrality_ch_gen"), track.pt(), centrality); int pidIndex = 0; - if (std::abs(track.pdgCode()) == kPiPlus) + if (std::abs(track.pdgCode()) == kPiPlus) { pidIndex = PionID; - if (std::abs(track.pdgCode()) == kKPlus) + registry.fill(HIST("MCGen/after/pt_centrality_pion_gen"), track.pt(), centrality); + } + if (std::abs(track.pdgCode()) == kKPlus) { pidIndex = KaonID; - if (std::abs(track.pdgCode()) == kProton) + registry.fill(HIST("MCGen/after/pt_centrality_kaon_gen"), track.pt(), centrality); + } + if (std::abs(track.pdgCode()) == kProton) { pidIndex = ProtonID; + registry.fill(HIST("MCGen/after/pt_centrality_proton_gen"), track.pt(), centrality); + } if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { ++acceptedTracks.total; @@ -1769,8 +1833,8 @@ struct FlowGenericFramework { histosNpt[ProtonID]->Fill(track.pt()); } - fillPtSums(track, vtxz); - fillGFW(track, vtxz, pidIndex, densitycorrections); + fillPtSums(track, centrality, vtxz); + fillGFW(track, centrality, vtxz, pidIndex, densitycorrections); if (cfgFill.cfgFillQA) fillTrackQA(track, vtxz); @@ -1781,7 +1845,7 @@ struct FlowGenericFramework { if (!nchSelected(track)) return; - double weffCh = getEfficiency(track, 0); + double weffCh = getEfficiency(track, centrality, 0); if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { if (weffCh > 0) acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; @@ -1795,7 +1859,7 @@ struct FlowGenericFramework { int pidIndex = getNsigmaPID(track); if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { - double weff = getEfficiency(track, pidIndex); + double weff = getEfficiency(track, centrality, pidIndex); if (weffCh > 0) histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); @@ -1810,8 +1874,8 @@ struct FlowGenericFramework { if (cfgFill.cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { - fillPtSums(track, vtxz); - fillGFW(track, vtxz, pidIndex, densitycorrections); + fillPtSums(track, centrality, vtxz); + fillGFW(track, centrality, vtxz, pidIndex, densitycorrections); } if (cfgFill.cfgFillQA) { fillTrackQA(track, vtxz); @@ -1858,7 +1922,7 @@ struct FlowGenericFramework { } template - bool selectK0(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality, double& weff) + bool selectK0(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality) { using V0TrackTable = std::decay_t; @@ -1920,22 +1984,13 @@ struct FlowGenericFramework { registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); registryQA.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); - registryQA.fill(HIST("K0/hK0s"), 0.5, 1); - if (cfgUsePIDEfficiencies) { - double weffDaughter1 = getEfficiency(postrack, 1); - double weffDaughter2 = getEfficiency(negtrack, 1); - weff = weffDaughter1 * weffDaughter2; - if (weff > 0) - registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); - } } if (doprocessMCReco) { if (cfgFill.cfgFillQA) { + registry.fill(HIST("trackQA/after/pt_centrality_K0"), v0.pt(), centrality); registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); } } @@ -1943,7 +1998,7 @@ struct FlowGenericFramework { } template - bool selectLambda(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality, double& weff) + bool selectLambda(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality) { using V0TrackTable = std::decay_t; bool isL = false; // Is lambda candidate @@ -2028,18 +2083,10 @@ struct FlowGenericFramework { registryQA.fill(HIST("Lambda/PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); registryQA.fill(HIST("Lambda/PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); - registryQA.fill(HIST("Lambda/hLambdas"), 0.5, 1); - if (cfgUsePIDEfficiencies) { - double weffDaughter1 = getEfficiency(postrack, 3); - double weffDaughter2 = getEfficiency(negtrack, 1); - weff = weffDaughter1 * weffDaughter2; - if (weff > 0) - registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); - } if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), negtrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), negtrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_proton"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), postrack.pt(), centrality); } } if (isAL && cfgFill.cfgFillQA) { @@ -2051,18 +2098,10 @@ struct FlowGenericFramework { registryQA.fill(HIST("Lambda/PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); registryQA.fill(HIST("Lambda/PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); - registryQA.fill(HIST("Lambda/hLambdas"), 0.5, 1); - if (cfgUsePIDEfficiencies) { - double weffDaughter1 = getEfficiency(postrack, 1); - double weffDaughter2 = getEfficiency(negtrack, 3); - weff = weffDaughter1 * weffDaughter2; - if (weff > 0) - registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); - } if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_proton"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), negtrack.pt(), centrality); } } @@ -2070,10 +2109,10 @@ struct FlowGenericFramework { } template - inline void fillPtSums(TTrack track, const double& vtxz) + inline void fillPtSums(TTrack track, const float& centrality, const double& vtxz) { double wacc = (dt == Gen) ? 1. : getAcceptance(track, vtxz, 0); - double weff = (dt == Gen) ? 1. : getEfficiency(track); + double weff = (dt == Gen) ? 1. : getEfficiency(track, centrality); if (weff < 0) return; @@ -2098,7 +2137,7 @@ struct FlowGenericFramework { } template - inline void fillGFW(TTrack track, const double& vtxz, int pid_index, DensityCorr densitycorrections) + inline void fillGFW(TTrack track, const float& centrality, const double& vtxz, int pid_index, DensityCorr densitycorrections) { if (cfgUsePID) { // Analysing POI flow with id'ed particles double ptmins[] = {o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoilow, 0.3, 0.5}; @@ -2129,7 +2168,7 @@ struct FlowGenericFramework { bool withinPtPOI = (track.pt() > o2::analysis::gfw::ptpoilow && track.pt() < o2::analysis::gfw::ptpoiup); if (!withinPtPOI && !withinPtRef) return; - double weff = (dt == Gen) ? 1. : getEfficiency(track, 0); + double weff = (dt == Gen) ? 1. : getEfficiency(track, centrality, 0); if (weff < 0) return; if (cfgUseDensityDependentCorrection && withinPtRef && dt != Gen) { From 85cd2f87b742e8c8d07b1ea2b6cade16eb78862b Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:51:19 +0200 Subject: [PATCH 387/449] [PWGCF,PWGDQ,PWGLF] Add new version of StraEvSels table (#16486) Co-authored-by: Romain Schotter Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowEfficiencyCasc.cxx | 4 +- PWGDQ/Tasks/quarkoniaToHyperons.cxx | 8 +-- PWGLF/DataModel/LFStrangenessTables.h | 66 ++++++++++++++++--- .../Strangeness/Converters/CMakeLists.txt | 17 ++++- .../Converters/straevselextrasconverter.cxx | 66 +++++++++++++++++++ .../Converters/straevselextrasconverter2.cxx | 66 +++++++++++++++++++ .../Converters/straevselsconverter6.cxx | 52 +++++++++++++++ .../TableProducer/Strangeness/cascadeflow.cxx | 20 +++--- .../Strangeness/sigma0builder.cxx | 20 +++--- .../Strangeness/strangederivedbuilder.cxx | 40 +++++------ PWGLF/Tasks/QC/strderivedGenQA.cxx | 10 +-- .../Tasks/Resonances/higherMassResonances.cxx | 2 +- PWGLF/Tasks/Resonances/k892hadronphoton.cxx | 8 +-- .../Strangeness/derivedcascadeanalysis.cxx | 8 +-- .../derivedlambdakzeroanalysis.cxx | 8 +-- PWGLF/Tasks/Strangeness/lambdapolsp.cxx | 6 +- PWGLF/Tasks/Strangeness/sigmaanalysis.cxx | 16 ++--- .../strangenessderivedbinnedinfo.cxx | 4 +- .../Tasks/Strangeness/taskLambdaSpinCorr.cxx | 4 +- 19 files changed, 335 insertions(+), 90 deletions(-) create mode 100644 PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx create mode 100644 PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter2.cxx create mode 100644 PWGLF/TableProducer/Strangeness/Converters/straevselsconverter6.cxx diff --git a/PWGCF/Flow/Tasks/flowEfficiencyCasc.cxx b/PWGCF/Flow/Tasks/flowEfficiencyCasc.cxx index 246e811614f..9a67d39f461 100644 --- a/PWGCF/Flow/Tasks/flowEfficiencyCasc.cxx +++ b/PWGCF/Flow/Tasks/flowEfficiencyCasc.cxx @@ -89,7 +89,7 @@ struct FlowEfficiencyCasc { AxisSpec axisK0sMass = {400, 0.4f, 0.6f, "Inv. Mass (GeV)"}; AxisSpec axisLambdaMass = {160, 1.08f, 1.16f, "Inv. Mass (GeV)"}; - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; using MyMcCollisions = soa::Join; using CascMCCandidates = soa::Join; using V0MCCandidates = soa::Join; @@ -345,7 +345,7 @@ struct FlowEfficiencyCasc { } PROCESS_SWITCH(FlowEfficiencyCasc, processRec, "process reconstructed information", true); - void processGen(MyMcCollisions::iterator const&, soa::SmallGroups> const& coll, const soa::SmallGroups>& cascMCs, const soa::SmallGroups>& v0MCs) + void processGen(MyMcCollisions::iterator const&, soa::SmallGroups> const& coll, const soa::SmallGroups>& cascMCs, const soa::SmallGroups>& v0MCs) { registry.fill(HIST("mcEventCounter"), 0.5); int rectracknum = 0; diff --git a/PWGDQ/Tasks/quarkoniaToHyperons.cxx b/PWGDQ/Tasks/quarkoniaToHyperons.cxx index d4601569e86..7012a6a6f12 100644 --- a/PWGDQ/Tasks/quarkoniaToHyperons.cxx +++ b/PWGDQ/Tasks/quarkoniaToHyperons.cxx @@ -378,7 +378,7 @@ struct QuarkoniaToHyperons { Service pdgDB; // For manual sliceBy - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; enum Selection : uint64_t { selCosPA = 0, selRadius, @@ -935,7 +935,7 @@ struct QuarkoniaToHyperons { histos.print(); } - template // TCollision should be of the type: soa::Join::iterator or so + template // TCollision should be of the type: soa::Join::iterator or so void initCCDB(TCollision const& collision) { if (mRunNumber == collision.runNumber() || (ccdbConfigurations.useCustomRunNumber && mRunNumber == ccdbConfigurations.customRunNumber)) { @@ -2497,7 +2497,7 @@ struct QuarkoniaToHyperons { // ______________________________________________________ // Real data processing - no MC subscription - void processRealData(soa::Join const& collisions, V0Candidates const& fullV0s, CascadeCandidates const& fullCascades, DauTracks const&) + void processRealData(soa::Join const& collisions, V0Candidates const& fullV0s, CascadeCandidates const& fullCascades, DauTracks const&) { // Custom grouping v0sGrouped.clear(); @@ -2674,7 +2674,7 @@ struct QuarkoniaToHyperons { // ______________________________________________________ // Simulated processing (subscribes to MC information too) - void processMonteCarlo(soa::Join const& collisions, V0MCCandidates const& fullV0s, CascadeMCCandidates const& fullCascades, DauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/, soa::Join const&, soa::Join const&) + void processMonteCarlo(soa::Join const& collisions, V0MCCandidates const& fullV0s, CascadeMCCandidates const& fullCascades, DauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/, soa::Join const&, soa::Join const&) { // Custom grouping v0sGrouped.clear(); diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index dc2f4846058..4eb92b3d43a 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -280,15 +280,60 @@ DECLARE_SOA_TABLE_VERSIONED(StraEvSels_005, "AOD", "STRAEVSELS", 5, //! // stracollision::EnergyCommonZNC, stracollision::IsUPC); -DECLARE_SOA_TABLE(StraEvSelExtras, "AOD", "STRAEVSELEXTRAS", //! debug information - udzdc::TimeZNA, // UPC info: re-assigned ZN-A time, in case of SG event, from the most active bc - udzdc::TimeZNC, // UPC info: re-assigned ZN-C time, in case of SG event, from the most active bc - udcollision::TimeFDDA, // Average A-side time (ns) - udcollision::TimeFDDC, // Average C-side time (ns) - udcollision::TimeFV0A, // Average A-side time (ns) - udcollision::TimeFT0A, // Average A-side time (ns) - udcollision::TimeFT0C, // Average C-side time (ns) - udcollision::TriggerMaskFT0); // 8 trigger bits: OrA, OrC, Semi-central, Central, Vertex, IsActiveA, IsActiveC, IsFlangeEvent +DECLARE_SOA_TABLE_VERSIONED(StraEvSels_006, "AOD", "STRAEVSELS", 6, //! debug information + evsel::Sel8, evsel::Selection, //! event selection: sel8 + mult::MultFT0A, mult::MultFT0C, mult::MultFV0A, // FIT detectors + mult::MultFDDA, mult::MultFDDC, + mult::MultNTracksPVeta1, // track multiplicities with eta cut for INEL>0 + mult::MultPVTotalContributors, // number of PV contribs total + mult::MultNTracksGlobal, // global track multiplicities + collision::Flags, // Contains Vertex::Flags, with most notably the UPCMode to know whether the vertex has been found using UPC settings + evsel::Alias, // trigger aliases (e.g. kTVXinTRD for v2) + evsel::Rct); // Bitmask of RCT flags + +DECLARE_SOA_TABLE(StraEvSelExtras_000, "AOD", "STRAEVSELEXTRAS", //! debug information + udzdc::TimeZNA, // UPC info: re-assigned ZN-A time, in case of SG event, from the most active bc + udzdc::TimeZNC, // UPC info: re-assigned ZN-C time, in case of SG event, from the most active bc + udcollision::TimeFDDA, // Average A-side time (ns) + udcollision::TimeFDDC, // Average C-side time (ns) + udcollision::TimeFV0A, // Average A-side time (ns) + udcollision::TimeFT0A, // Average A-side time (ns) + udcollision::TimeFT0C, // Average C-side time (ns) + udcollision::TriggerMaskFT0); // 8 trigger bits: OrA, OrC, Semi-central, Central, Vertex, IsActiveA, IsActiveC, IsFlangeEvent + +DECLARE_SOA_TABLE_VERSIONED(StraEvSelExtras_001, "AOD", "STRAEVSELEXTRAS", 1, //! debug information + mult::MultZNA, mult::MultZNC, mult::MultZEM1, // ZDC signals + mult::MultZEM2, mult::MultZPA, mult::MultZPC, + mult::MultNTracksITSTPC, // track multiplicities, PV contribs, no eta cut + mult::MultAllTracksTPCOnly, // TPConly track multiplicities, all, no eta cut + mult::MultAllTracksITSTPC, // ITSTPC track multiplicities, all, no eta cut + evsel::NumTracksInTimeRange, // add occupancy in specified time interval by a number of tracks from nearby collisions + evsel::SumAmpFT0CInTimeRange, // add occupancy in specified time interval by a sum of FT0C amplitudes from nearby collisions + udcollision::TimeFDDA, // Average A-side time (ns) + udcollision::TimeFDDC, // Average C-side time (ns) + udcollision::TimeFV0A, // Average A-side time (ns) + udcollision::TimeFT0A, // Average A-side time (ns) + udcollision::TimeFT0C, // Average C-side time (ns) + udcollision::TriggerMaskFT0, // 8 trigger bits: OrA, OrC, Semi-central, Central, Vertex, IsActiveA, IsActiveC, IsFlangeEvent + udcollision::GapSide, // UPC info: 0 for side A, 1 for side C, 2 for both sides, 3 neither A or C, 4 not enough or too many pv contributors + udcollision::TotalFT0AmplitudeA, // UPC info: re-assigned FT0-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFT0AmplitudeC, // UPC info: re-assigned FT0-C amplitude, in case of SG event, from the most active bc + udcollision::TotalFV0AmplitudeA, // UPC info: re-assigned FV0-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFDDAmplitudeA, // UPC info: re-assigned FDD-A amplitude, in case of SG event, from the most active bc + udcollision::TotalFDDAmplitudeC, // UPC info: re-assigned FDD-C amplitude, in case of SG event, from the most active bc + udzdc::TimeZNA, // UPC info: re-assigned ZN-A time, in case of SG event, from the most active bc + udzdc::TimeZNC, // UPC info: re-assigned ZN-C time, in case of SG event, from the most active bc + udzdc::EnergyCommonZNA, // UPC info: re-assigned ZN-A amplitude, in case of SG event, from the most active bc + udzdc::EnergyCommonZNC, // UPC info: re-assigned ZN-C amplitude, in case of SG event, from the most active bc + // Dynamic columns for manipulating information + // stracollision::TotalFV0AmplitudeA, + // stracollision::TotalFT0AmplitudeA, + // stracollision::TotalFT0AmplitudeC, + // stracollision::TotalFDDAmplitudeA, + // stracollision::TotalFDDAmplitudeC, + // stracollision::EnergyCommonZNA, + // stracollision::EnergyCommonZNC, + stracollision::IsUPC); DECLARE_SOA_TABLE(StraEvSelsRun2, "AOD", "STRAEVSELSRUN2", //! debug information evsel::Sel8, evsel::Sel7, evsel::Selection, //! event selection: sel8 @@ -334,7 +379,8 @@ DECLARE_SOA_TABLE_VERSIONED(StraEvTimes_001, "AOD", "STRAEVTIMES", 1, //! event using StraRawCents = StraRawCents_004; using StraCents = StraCents_002; -using StraEvSels = StraEvSels_005; +using StraEvSels = StraEvSels_006; +using StraEvSelExtras = StraEvSelExtras_001; using StraStamps = StraStamps_001; using StraEvTimes = StraEvTimes_001; using StraCollision = StraCollisions::iterator; diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 175a7c852bd..2cd12ee97b1 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -36,7 +36,7 @@ o2physics_add_dpl_workflow(stradautrackstofpidconverter3 o2physics_add_dpl_workflow(stradautracksextraconverter SOURCES stradautracksextraconverter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(stradautracksextraconverter2 @@ -84,6 +84,21 @@ o2physics_add_dpl_workflow(straevselsconverter5 PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(straevselsconverter6 + SOURCES straevselsconverter6.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(straevselextrasconverter + SOURCES straevselextrasconverter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(straevselextrasconverter2 + SOURCES straevselextrasconverter2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(straevselsconverter2rawcents SOURCES straevselsconverter2rawcents.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx new file mode 100644 index 00000000000..27e7d930ebc --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx @@ -0,0 +1,66 @@ +// 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. + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::evsel; + +// Converts straevselsextrasconverter1 converts StraEvSelExtras_000 into StraEvSelExtras_001 +struct straevselextrasconverter { + Produces straEvSelExtras_001; + + void process(soa::Join const& straEvSels_005) + { + for (auto& values : straEvSels_005) { + straEvSelExtras_001(values.multZNA(), + values.multZNC(), + values.multZEM1(), + values.multZEM2(), + values.multZPA(), + values.multZPC(), + values.multNTracksITSTPC(), + values.multAllTracksTPCOnly(), + values.multAllTracksITSTPC(), + values.trackOccupancyInTimeRange(), + values.ft0cOccupancyInTimeRange(), + values.timeFDDA(), + values.timeFDDC(), + values.timeFV0A(), + values.timeFT0A(), + values.timeFT0C(), + values.triggerMaskFT0(), + values.gapSide(), + values.totalFT0AmplitudeA(), + values.totalFT0AmplitudeC(), + values.totalFV0AmplitudeA(), + values.totalFDDAmplitudeA(), + values.totalFDDAmplitudeC(), + values.timeZNA(), + values.timeZNC(), + values.energyCommonZNA(), + values.energyCommonZNC()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter2.cxx new file mode 100644 index 00000000000..0d06b2cd1df --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter2.cxx @@ -0,0 +1,66 @@ +// 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. + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::evsel; + +// Produce dummy StraEvSelExtras for analysis subscribing to StraEvSelExtras but not saved in the strangeness derived data (typically when running over pp strangeness derived data) +struct straevselextrasconverter2 { + Produces straEvSelExtras; + + void process(aod::StraEvSels const& straEvSels) + { + for (int ii = 0; ii < straEvSels.size(); ii++) { + straEvSelExtras(-999., // dummy multZNA, + -999., // dummy multZNC, + -999., // dummy multZEM1, + -999., // dummy multZEM2, + -999., // dummy multZPA, + -999., // dummy multZPC, + -999., // dummy multNTracksITSTPC, + -999., // dummy multAllTracksTPCOnly, + -999., // dummy multAllTracksITSTPC, + -999., // dummy trackOccupancyInTimeRange, + -999., // dummy ft0cOccupancyInTimeRange, + -999., // dummy timeFDDA, + -999., // dummy timeFDDC, + -999., // dummy timeFV0A, + -999., // dummy timeFT0A, + -999., // dummy timeFT0C, + 0, // dummy triggerMaskFT0, + -999, // dummy gapSide, + -999., // dummy totalFT0AmplitudeA, + -999., // dummy totalFT0AmplitudeC, + -999., // dummy totalFV0AmplitudeA, + -999., // dummy totalFDDAmplitudeA, + -999., // dummy totalFDDAmplitudeC, + -999., // dummy timeZNA, + -999., // dummy timeZNC, + -999., // dummy energyCommonZNA, + -999.); // dummy energyCommonZNC); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter6.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter6.cxx new file mode 100644 index 00000000000..148d892eda5 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter6.cxx @@ -0,0 +1,52 @@ +// 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. + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::evsel; + +// Converts Stra Event selections from 005 to 006 +struct straevselsconverter6 { + Produces straEvSels_006; + + void process(aod::StraEvSels_005 const& straEvSels_005) + { + for (auto& values : straEvSels_005) { + straEvSels_006(values.sel8(), + values.selection_raw(), + values.multFT0A(), + values.multFT0C(), + values.multFT0A(), + values.multFDDA(), + values.multFDDC(), + values.multNTracksPVeta1(), + values.multPVTotalContributors(), + values.multNTracksGlobal(), + values.flags(), + values.alias_raw(), + values.rct_raw()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index 98d86a0c471..f5cac87074d 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -67,11 +67,11 @@ using namespace o2::framework::expressions; using std::array; using DauTracks = soa::Join; -using CollEventPlane = soa::Join::iterator; -using CollEventPlaneCentralFW = soa::Join::iterator; -using CollEventPlaneCentralFWOnlyFT0C = soa::Join::iterator; -using CollEventAndSpecPlane = soa::Join::iterator; -using CollEventAndSpecPlaneCentralFW = soa::Join::iterator; +using CollEventPlane = soa::Join::iterator; +using CollEventPlaneCentralFW = soa::Join::iterator; +using CollEventPlaneCentralFWOnlyFT0C = soa::Join::iterator; +using CollEventAndSpecPlane = soa::Join::iterator; +using CollEventAndSpecPlaneCentralFW = soa::Join::iterator; using MCCollisionsStra = soa::Join; using V0Candidates = soa::Join; using V0MCCandidates = soa::Join; @@ -1213,7 +1213,7 @@ struct cascadeFlow { } } - void processTrainingBackground(soa::Join::iterator const& coll, soa::Join const& Cascades, DauTracks const&) + void processTrainingBackground(soa::Join::iterator const& coll, soa::Join const& Cascades, DauTracks const&) { int counter = 0; @@ -1269,7 +1269,7 @@ struct cascadeFlow { } } - void processTrainingSignal(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) + void processTrainingSignal(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) { if (!AcceptEvent(coll, 1)) { @@ -2489,7 +2489,7 @@ struct cascadeFlow { } } - void processAnalyseMC(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) + void processAnalyseMC(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) { if (!AcceptEvent(coll, 1)) { @@ -2644,7 +2644,7 @@ struct cascadeFlow { } } - void processMCGen(MCCollisionsStra::iterator const& mcCollision, const soa::SmallGroups>& collisions, const soa::SmallGroups>& v0MC, const soa::SmallGroups>& cascMC) + void processMCGen(MCCollisionsStra::iterator const& mcCollision, const soa::SmallGroups>& collisions, const soa::SmallGroups>& v0MC, const soa::SmallGroups>& cascMC) { histosMCGen.fill(HIST("hZvertexGen"), mcCollision.posZ()); @@ -2773,7 +2773,7 @@ struct cascadeFlow { } } - void processMCPrimaryLambdaFraction(soa::Join::iterator const& coll, V0MCCandidates const& V0s, DauTracks const&, soa::Join const&) + void processMCPrimaryLambdaFraction(soa::Join::iterator const& coll, V0MCCandidates const& V0s, DauTracks const&, soa::Join const&) { Float_t collisionCentrality = 0; diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx index 3888e00f8e5..86bf8e6172d 100644 --- a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -3128,32 +3128,32 @@ struct sigma0builder { } // Sigma0 processing part - void processRealData(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) + void processRealData(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) { dataProcess(collisions, fullV0s, nullptr, nullptr, nullptr); } - void processRealDataWithTOF(soa::Join const& collisions, V0TOFStandardDerivedDatas const& fullV0s, dauTracks const&) + void processRealDataWithTOF(soa::Join const& collisions, V0TOFStandardDerivedDatas const& fullV0s, dauTracks const&) { dataProcess(collisions, fullV0s, nullptr, nullptr, nullptr); } - void processRealDataWithEMCal(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&, aod::EMCALClusters const& fullEMCalClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) + void processRealDataWithEMCal(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&, aod::EMCALClusters const& fullEMCalClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) { dataProcess(collisions, fullV0s, fullEMCalClusters, emcmatchedtracks, nullptr); } - void processMonteCarlo(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) + void processMonteCarlo(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { dataProcess(collisions, fullV0s, nullptr, nullptr, mcParticles); } - void processMonteCarloWithTOF(soa::Join const& collisions, V0TOFDerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) + void processMonteCarloWithTOF(soa::Join const& collisions, V0TOFDerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { dataProcess(collisions, fullV0s, nullptr, nullptr, mcParticles); } - void processMonteCarloWithEMCal(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) + void processMonteCarloWithEMCal(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) { dataProcess(collisions, fullV0s, fullEMCalMCClusters, emcmatchedtracks, mcParticles); } @@ -3164,22 +3164,22 @@ struct sigma0builder { } // Photon and lambda-specific part (QA) - void processV0QA(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) + void processV0QA(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) { runV0QA(collisions, fullV0s); } - void processV0MCQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) + void processV0MCQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { runV0QA(collisions, fullV0s); } - void processV0Generated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& collisions) + void processV0Generated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& collisions) { runGenV0QA(mcCollisions, V0MCCores, collisions); } - void processPCMVsEMCalQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) + void processPCMVsEMCalQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) { runPCMVsEMCalQA(collisions, fullV0s, fullEMCalMCClusters, emcmatchedtracks, mcParticles); } diff --git a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx index 1878aaa9135..45992de95e8 100644 --- a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx @@ -573,30 +573,30 @@ struct strangederivedbuilder { collision.multNTracksPVeta1() * static_cast(fillTruncationOptions.fillRawNTracksEta1), collision.multPVTotalContributors() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), collision.multNTracksGlobal() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), - collision.multNTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), - collision.multAllTracksTPCOnly() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), - collision.multAllTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), - collision.multZNA() * static_cast(fillTruncationOptions.fillRawZDC), - collision.multZNC() * static_cast(fillTruncationOptions.fillRawZDC), - collision.multZEM1() * static_cast(fillTruncationOptions.fillRawZDC), - collision.multZEM2() * static_cast(fillTruncationOptions.fillRawZDC), - collision.multZPA() * static_cast(fillTruncationOptions.fillRawZDC), - collision.multZPC() * static_cast(fillTruncationOptions.fillRawZDC), - collision.trackOccupancyInTimeRange(), - collision.ft0cOccupancyInTimeRange(), - // UPC info - gapSide, - totalFT0AmplitudeA, totalFT0AmplitudeC, totalFV0AmplitudeA, - totalFDDAmplitudeA, totalFDDAmplitudeC, - energyCommonZNA, energyCommonZNC, // Collision flags collision.flags(), collision.alias_raw(), collision.rct_raw()); - products.strangeEvSelExtras(timeZNA, timeZNC, // ZDC info - timeFDDA, timeFDDC, // FDD info - timeFV0A, // FV0A info - timeFT0A, timeFT0C, ft0TriggerMask); // FT0 info + products.strangeEvSelExtras(collision.multZNA() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZNC() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZEM1() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZEM2() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZPA() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZPC() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multNTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multAllTracksTPCOnly() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multAllTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange(), + timeFDDA, timeFDDC, // FDD info + timeFV0A, // FV0A info + timeFT0A, timeFT0C, ft0TriggerMask, // FT0 info + // UPC info + gapSide, + totalFT0AmplitudeA, totalFT0AmplitudeC, totalFV0AmplitudeA, + totalFDDAmplitudeA, totalFDDAmplitudeC, + timeZNA, timeZNC, // ZDC info + energyCommonZNA, energyCommonZNC); } else { // We are in Run 2 products.strangeCentsRun2(collision.centRun2V0M(), collision.centRun2V0A(), collision.centRun2SPDTracklets(), collision.centRun2SPDClusters()); diff --git a/PWGLF/Tasks/QC/strderivedGenQA.cxx b/PWGLF/Tasks/QC/strderivedGenQA.cxx index 7fa8d57ed56..4d1c2878d26 100644 --- a/PWGLF/Tasks/QC/strderivedGenQA.cxx +++ b/PWGLF/Tasks/QC/strderivedGenQA.cxx @@ -53,7 +53,7 @@ using namespace o2::framework::expressions; using namespace std; using std::array; using dauTracks = soa::Join; -using StrCollisionsDatas = soa::Join; +using StrCollisionsDatas = soa::Join; using V0DerivedDatas = soa::Join; using V0DerivedMCDatas = soa::Join; using CascDerivedMCDatas = soa::Join; @@ -172,7 +172,7 @@ struct strderivedGenQA { ConfigurableAxis axisTrackProperties{"axisTrackProperties", {32, -0.5, 31.5f}, "Track Properties"}; } AxisConfig; - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; void init(InitContext const&) { @@ -589,7 +589,7 @@ struct strderivedGenQA { // ______________________________________________________ // Simulated processing // Return the list of indices to the recoed collision associated to a given MC collision. - std::vector getListOfRecoCollIndices(soa::Join const& mcCollisions, soa::Join const& collisions) + std::vector getListOfRecoCollIndices(soa::Join const& mcCollisions, soa::Join const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); for (auto const& mcCollision : mcCollisions) { @@ -612,7 +612,7 @@ struct strderivedGenQA { // ______________________________________________________ // Simulated processing // Fill generated event information (for event loss/splitting estimation) - void fillGeneratedEventProperties(soa::Join const& mcCollisions, soa::Join const& collisions) + void fillGeneratedEventProperties(soa::Join const& mcCollisions, soa::Join const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); for (auto const& mcCollision : mcCollisions) { @@ -1076,7 +1076,7 @@ struct strderivedGenQA { // ______________________________________________________ // Simulated processing (subscribes to MC information too) - void processGenerated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& CascMCCores, soa::Join const& collisions) + void processGenerated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& CascMCCores, soa::Join const& collisions) { fillGeneratedEventProperties(mcCollisions, collisions); std::vector listBestCollisionIdx = getListOfRecoCollIndices(mcCollisions, collisions); diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index 0e7e636e4a6..de6dfacd7e2 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -725,7 +725,7 @@ struct HigherMassResonances { return std::sqrt(d1 * d1 + d2 * d2); } - using EventCandidatesDerivedData = soa::Join; + using EventCandidatesDerivedData = soa::Join; using V0CandidatesDerivedData = soa::Join; // using DauTracks = soa::Join; using DauTracks = soa::Join; diff --git a/PWGLF/Tasks/Resonances/k892hadronphoton.cxx b/PWGLF/Tasks/Resonances/k892hadronphoton.cxx index 875e9f3379b..e4fbc8c83f8 100644 --- a/PWGLF/Tasks/Resonances/k892hadronphoton.cxx +++ b/PWGLF/Tasks/Resonances/k892hadronphoton.cxx @@ -78,7 +78,7 @@ struct k892hadronphoton { //__________________________________________________ // For manual sliceBy // SliceCache cache; - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -1241,18 +1241,18 @@ struct k892hadronphoton { } } - void processRealData(soa::Join const& collisions, KStars const& fullKStars) + void processRealData(soa::Join const& collisions, KStars const& fullKStars) { analyzeRecoeKStars(collisions, fullKStars); } - void processMonteCarlo(soa::Join const& collisions, MCKStars const& fullKStars) + void processMonteCarlo(soa::Join const& collisions, MCKStars const& fullKStars) { analyzeRecoeKStars(collisions, fullKStars); } // Simulated processing in Run 3 - void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& KStarGens) + void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& KStarGens) { analyzeGenerated(mcCollisions, collisions, KStarGens); } diff --git a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx index 0beb0bd3a46..93e3aafbb6b 100644 --- a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx @@ -252,7 +252,7 @@ struct Derivedcascadeanalysis { // For manual sliceBy // Preslice> perMcCollision = aod::v0data::straMCCollisionId; - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; PresliceUnsorted> perMcCollisionRun2 = aod::v0data::straMCCollisionId; void init(InitContext const&) @@ -1622,7 +1622,7 @@ struct Derivedcascadeanalysis { return listBestCollisionIdx; } - void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, DauTracks const&) + void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, DauTracks const&) { analyseCascades(coll, Cascades); } @@ -1631,7 +1631,7 @@ struct Derivedcascadeanalysis { analyseCascades(coll, Cascades); } - void processCascadesMCrec(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) + void processCascadesMCrec(soa::Join::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join const&) { analyseCascades(coll, Cascades); } @@ -1640,7 +1640,7 @@ struct Derivedcascadeanalysis { analyseCascades(coll, Cascades); } - void processCascadesMCforEff(soa::Join const& mcCollisions, soa::Join const& Cascades, soa::Join const& collisions) + void processCascadesMCforEff(soa::Join const& mcCollisions, soa::Join const& Cascades, soa::Join const& collisions) { analyseCascadesMCforEff(mcCollisions, Cascades, collisions); } diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index bb4241a513e..1d293c9c620 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -384,7 +384,7 @@ struct derivedlambdakzeroanalysis { // For manual sliceBy // Preslice> perMcCollision = aod::v0data::straMCCollisionId; - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; PresliceUnsorted> perMcCollisionRun2 = aod::v0data::straMCCollisionId; enum Selection : uint64_t { selCosPA = 0, @@ -3140,7 +3140,7 @@ struct derivedlambdakzeroanalysis { // ______________________________________________________ // Real data processing in Run 3 - no MC subscription - void processRealDataRun3(soa::Join::iterator const& collision, V0Candidates const& fullV0s, DauTracks const&) + void processRealDataRun3(soa::Join::iterator const& collision, V0Candidates const& fullV0s, DauTracks const&) { analyzeRecoedV0sInRealData(collision, fullV0s); } @@ -3154,7 +3154,7 @@ struct derivedlambdakzeroanalysis { // ______________________________________________________ // Simulated processing in Run 3 (subscribes to MC information too) - void processMonteCarloRun3(soa::Join::iterator const& collision, V0McCandidates const& fullV0s, DauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/, soa::Join const&) + void processMonteCarloRun3(soa::Join::iterator const& collision, V0McCandidates const& fullV0s, DauTracks const&, aod::MotherMCParts const&, soa::Join const& /*mccollisions*/, soa::Join const&) { analyzeRecoedV0sInMonteCarlo(collision, fullV0s); } @@ -3168,7 +3168,7 @@ struct derivedlambdakzeroanalysis { // ______________________________________________________ // Simulated processing in Run 3 (subscribes to MC information too) - void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& CascMCCores, soa::Join const& collisions) + void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& CascMCCores, soa::Join const& collisions) { analyzeGeneratedV0s(mcCollisions, V0MCCores, CascMCCores, collisions); } diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index d2d3064d37e..3a44c100cdf 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -1347,7 +1347,7 @@ struct lambdapolsp { PROCESS_SWITCH(lambdapolsp, processData, "Process data", true); // process function for derived data - mimics the functionality of the original data - void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) + void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) { //___________________________________________________________________________________________________ // event selection @@ -1778,7 +1778,7 @@ struct lambdapolsp { BinningType colBinning{{meGrp.axisVertex, meGrp.axisMultiplicityClass}, true}; Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only - void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) { TRandom3 randGen(0); @@ -1913,7 +1913,7 @@ struct lambdapolsp { PROCESS_SWITCH(lambdapolsp, processDerivedDataMixed, "Process mixed event using derived data", false); - void processDerivedDataMixed2(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + void processDerivedDataMixed2(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) { TRandom3 randGen(0); diff --git a/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx index b41281dedcf..c7bff11c752 100644 --- a/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx @@ -1835,45 +1835,45 @@ struct sigmaanalysis { } } - void processRealData(soa::Join const& collisions, Sigma0s const& fullSigma0s) + void processRealData(soa::Join const& collisions, Sigma0s const& fullSigma0s) { analyzeRecoeSigma0s(collisions, fullSigma0s); } - void processRealDataWithEMCal(soa::Join const& collisions, Sigma0sWithEMCal const& fullSigma0s) + void processRealDataWithEMCal(soa::Join const& collisions, Sigma0sWithEMCal const& fullSigma0s) { analyzeRecoeSigma0s(collisions, fullSigma0s); } - void processMonteCarlo(soa::Join const& collisions, MCSigma0s const& fullSigma0s) + void processMonteCarlo(soa::Join const& collisions, MCSigma0s const& fullSigma0s) { analyzeRecoeSigma0s(collisions, fullSigma0s); } - void processMonteCarloWithEMCal(soa::Join const& collisions, MCSigma0sWithEMCal const& fullSigma0s) + void processMonteCarloWithEMCal(soa::Join const& collisions, MCSigma0sWithEMCal const& fullSigma0s) { analyzeRecoeSigma0s(collisions, fullSigma0s); } // Simulated processing in Run 3 - void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& Sigma0Gens) + void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& Sigma0Gens) { analyzeGenerated(mcCollisions, collisions, Sigma0Gens); } // _____________________________________________________ // Pi0 QA - void processPi0RealData(soa::Join const& collisions, soa::Join const& fullPi0s) + void processPi0RealData(soa::Join const& collisions, soa::Join const& fullPi0s) { analyzeRecoePi0s(collisions, fullPi0s); } - void processPi0MonteCarlo(soa::Join const& collisions, soa::Join const& fullPi0s) + void processPi0MonteCarlo(soa::Join const& collisions, soa::Join const& fullPi0s) { analyzeRecoePi0s(collisions, fullPi0s); } - void processPi0GeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& Pi0Gens) + void processPi0GeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& Pi0Gens) { analyzeGenerated(mcCollisions, collisions, Pi0Gens); } diff --git a/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx b/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx index 240e0b0922e..3dea781c798 100644 --- a/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx @@ -331,7 +331,7 @@ struct strangenessderivedbinnedinfo { histos.print(); } - template // TCollision should be of the type: soa::Join::iterator or so + template // TCollision should be of the type: soa::Join::iterator or so void initCCDB(TCollision const& collision) { if (mRunNumber == collision.runNumber()) { @@ -769,7 +769,7 @@ struct strangenessderivedbinnedinfo { // ______________________________________________________ // Real data processing - no MC subscription - void process(soa::Join::iterator const& collision, V0Candidates const& fullV0s, CascadeCandidates const& fullCascades, DauTracks const&) + void process(soa::Join::iterator const& collision, V0Candidates const& fullV0s, CascadeCandidates const& fullCascades, DauTracks const&) { // Fire up CCDB if (cfgSkimmedProcessing) { diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 3bf53942f44..9fcac3ab845 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -804,7 +804,7 @@ struct LfTaskLambdaSpinCorr { using v0Cand = soa::Filtered; // void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) - void processDerivedData(soa::Join::iterator const& collision, v0Cand const& V0s, dauTracks const&) + void processDerivedData(soa::Join::iterator const& collision, v0Cand const& V0s, dauTracks const&) { histos.fill(HIST("hEvtSelInfo"), 0.5); if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { @@ -926,7 +926,7 @@ struct LfTaskLambdaSpinCorr { // Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only // void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) - void processDerivedDataMixed(soa::Join const& collisions, v0Cand const& V0s, dauTracks const&) + void processDerivedDataMixed(soa::Join const& collisions, v0Cand const& V0s, dauTracks const&) { From 20de66970cea9e584c40d7b628e9106a7873035d Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 2 Jun 2026 12:22:19 +0200 Subject: [PATCH 388/449] [Common] Update centralityQa task (#16490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ALICE Action Bot Co-authored-by: Vít Kučera <26327373+vkucera@users.noreply.github.com> --- Common/Tasks/centralityQa.cxx | 651 +++++++++++++++++++++++++++++----- 1 file changed, 558 insertions(+), 93 deletions(-) diff --git a/Common/Tasks/centralityQa.cxx b/Common/Tasks/centralityQa.cxx index 2fc8ed715a3..895cf3db5dc 100644 --- a/Common/Tasks/centralityQa.cxx +++ b/Common/Tasks/centralityQa.cxx @@ -8,6 +8,7 @@ // 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. +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" @@ -28,60 +29,354 @@ using namespace o2; using namespace o2::framework; struct CentralityQa { + HistogramRegistry histos{"histos"}; + + bool isRun2 = false; + bool isMC = false; + Configurable nBins{"nBins", 1050, "number of bins"}; - Configurable INELgtZERO{"INELgtZERO", 1, "0 - no, 1 - yes"}; - Configurable vertexZcut{"vertexZcut", 10, "vertex-Z position cut (absolute value in cm)"}; - OutputObj hCentRun2V0M{TH1F("hCentRun2V0M", "V0M", nBins, 0, 105.)}; - OutputObj hCentRun2V0A{TH1F("hCentRun2V0A", "V0A", nBins, 0, 105.)}; - OutputObj hCentRun2SPDTks{TH1F("hCentRun2SPDTks", "SPD Tracklets", nBins, 0, 105.)}; - OutputObj hCentRun2SPDCls{TH1F("hCentRun2SPDCls", "SPD Clusters", nBins, 0, 105.)}; - OutputObj hCentRun2CL0{TH1F("hCentRun2CL0", "CL0", nBins, 0, 105.)}; - OutputObj hCentRun2CL1{TH1F("hCentRun2CL1", "CL1", nBins, 0, 105.)}; - OutputObj hCentFV0A{TH1F("hCentFV0A", "FV0A", nBins, 0, 105.)}; - OutputObj hCentFT0M{TH1F("hCentFT0M", "FT0M", nBins, 0, 105.)}; - OutputObj hCentFT0A{TH1F("hCentFT0A", "FT0A", nBins, 0, 105.)}; - OutputObj hCentFT0C{TH1F("hCentFT0C", "FT0C", nBins, 0, 105.)}; - OutputObj hCentFDDM{TH1F("hCentFDDM", "FDDM", nBins, 0, 105.)}; - OutputObj hCentNTPV{TH1F("hCentNTPV", "NTPV", nBins, 0, 105.)}; - - // profiles of midrapidity multiplicity density - OutputObj hCentProfileFV0A{TProfile("hCentProfileFV0A", "FV0A", nBins, 0, 105.)}; - OutputObj hCentProfileFT0M{TProfile("hCentProfileFT0M", "FT0M", nBins, 0, 105.)}; - OutputObj hCentProfileFT0A{TProfile("hCentProfileFT0A", "FT0A", nBins, 0, 105.)}; - OutputObj hCentProfileFT0C{TProfile("hCentProfileFT0C", "FT0C", nBins, 0, 105.)}; - OutputObj hCentProfileFDDM{TProfile("hCentProfileFDDM", "FDDM", nBins, 0, 105.)}; - OutputObj hCentProfileNTPV{TProfile("hCentProfileNTPV", "NTPV", nBins, 0, 105.)}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {1000, 0, 1000}, "Multiplicity"}; + ConfigurableAxis axisMultiplicityPV{"axisMultiplicityPV", {1000, 0, 1000}, "Multiplicity PV"}; - void processRun2PP(soa::Join::iterator const& col) + struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // JSON group name + Configurable requireSel8{"requireSel8", true, "require sel8 event selection"}; + Configurable requireTriggerTVX{"requireTriggerTVX", true, "require FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border (Run 3 only)"}; + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border (Run 3 only)"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track (Run 3 only)"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", true, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference (Run 3 only)"}; + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF (Run 3 only)"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD (Run 3 only)"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds (Run 3 only)"}; + Configurable requireNoCollInROFStd{"requireNoCollInROFStd", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF with mult. above a certain threshold (Run 3 only)"}; + Configurable requireNoCollInROFStrict{"requireNoCollInROFStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF (Run 3 only)"}; + Configurable requireINEL0{"requireINEL0", true, "require INEL>0 event selection"}; + Configurable requireINEL1{"requireINEL1", false, "require INEL>1 event selection"}; + + Configurable maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position"}; + + Configurable useFT0CbasedOccupancy{"useFT0CbasedOccupancy", false, "Use sum of FT0-C amplitudes for estimating occupancy? (if not, use track-based definition)"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + + Configurable requireIsBBT0A{"requireIsBBT0A", false, "Require beam-beam collisions based on timing information in FT0A"}; + Configurable requireIsBBT0C{"requireIsBBT0C", false, "Require beam-beam collisions based on timing information in FT0C"}; + + Configurable rejectMismatchedBCs{"rejectMismatchedBCs", false, "Reject collision with BC different from MC BC"}; + Configurable rejectMismatchedFoundBCs{"rejectMismatchedFoundBCs", false, "Reject collision with found BC different from MC BC"}; + + // Run 2 specific event selections + Configurable requireSel7{"requireSel7", true, "require sel7 event selection (Run 2 only: event selection decision based on V0A & V0C)"}; + Configurable requireINT7{"requireINT7", true, "require INT7 trigger selection (Run 2 only)"}; + Configurable rejectIncompleteDAQ{"rejectIncompleteDAQ", true, "reject events with incomplete DAQ (Run 2 only)"}; + Configurable requireConsistentSPDAndTrackVtx{"requireConsistentSPDAndTrackVtx", true, "reject events with inconsistent in SPD and Track vertices (Run 2 only)"}; + Configurable rejectPileupFromSPD{"rejectPileupFromSPD", true, "reject events with pileup according to SPD vertexer (Run 2 only)"}; + Configurable rejectV0PFPileup{"rejectV0PFPileup", false, "reject events tagged as OOB pileup according to V0 past-future info (Run 2 only)"}; + Configurable rejectPileupInMultBins{"rejectPileupInMultBins", true, "reject events tagged as pileup according to multiplicity-differential pileup checks (Run 2 only)"}; + Configurable rejectPileupMV{"rejectPileupMV", true, "reject events tagged as pileup according to according to multi-vertexer (Run 2 only)"}; + Configurable rejectTPCPileup{"rejectTPCPileup", false, "reject events tagged as pileup according to pileup in TPC (Run 2 only)"}; + Configurable requireNoV0MOnVsOffPileup{"requireNoV0MOnVsOffPileup", false, "reject events tagged as OOB pileup according to online-vs-offline VOM correlation (Run 2 only)"}; + Configurable requireNoSPDOnVsOffPileup{"requireNoSPDOnVsOffPileup", false, "reject events tagged as pileup according to online-vs-offline SPD correlation (Run 2 only)"}; + Configurable requireNoSPDClsVsTklBG{"requireNoSPDClsVsTklBG", true, "reject events tagged as beam-gas and pileup according to cluster-vs-tracklet correlation (Run 2 only)"}; + } eventSelections; + + void init(o2::framework::InitContext& /*initContext*/) { - if (!col.alias_bit(kINT7)) { - return; + if (doprocessRun2PP || + doprocessRun2PPb || + doprocessRun2PbPb) { + isRun2 = true; + } else { + isRun2 = false; } - if (!col.sel7()) { - return; + + if (doprocessMonteCarloRun3_FV0A || + doprocessMonteCarloRun3_FT0M || + doprocessMonteCarloRun3_FT0A || + doprocessMonteCarloRun3_FT0C || + doprocessMonteCarloRun3_FT0CVar1 || + doprocessMonteCarloRun3_FT0CVar2 || + doprocessMonteCarloRun3_MFT || + doprocessMonteCarloRun3_NGlobal || + doprocessMonteCarloRun3_NTPV) { + isMC = true; + } else { + isMC = false; + } + + if (isRun2) { + histos.add("hCentRun2V0M", "V0M centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentRun2V0A", "V0A centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentRun2SPDTks", "SPD tracklet centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentRun2SPDCls", "SPD cluster centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentRun2CL0", "CL0 centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentRun2CL1", "CL1 centrality (%)", kTH1D, {{nBins, 0, 105.}}); + } else { + histos.add("hCentFV0A", "FV0A centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFT0M", "FT0M centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFT0A", "FT0A centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFT0C", "FT0C centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFT0CVar1", "FT0CVar1 centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFT0CVar2", "FT0CVar2 centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentFDDM", "FDDM centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentNTPV", "NTPV centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentNGlobal", "NGlobal centrality (%)", kTH1D, {{nBins, 0, 105.}}); + histos.add("hCentMFT", "MFT centrality (%)", kTH1D, {{nBins, 0, 105.}}); + + // profiles of midrapidity multiplicity density + histos.add("hCentProfileFV0A", "FV0A centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFT0M", "FT0M centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFT0A", "FT0A centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFT0C", "FT0C centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFT0CVar1", "FT0CVar1 centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFT0CVar2", "FT0CVar2 centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileFDDM", "FDDM centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileNTPV", "NTPV centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileNGlobal", "NGlobal centrality (%)", kTProfile, {{nBins, 0, 105.}}); + histos.add("hCentProfileMFT", "MFT centrality (%)", kTProfile, {{nBins, 0, 105.}}); + + histos.add("hMultEta05VsCentFV0A", "FV0A centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFT0M", "FT0M centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFT0A", "FT0A centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFT0C", "FT0C centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFT0CVar1", "FT0CVar1 centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFT0CVar2", "FT0CVar2 centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentFDDM", "FDDM centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentNTPV", "NTPV centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentNGlobal", "NGlobal centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + histos.add("hMultEta05VsCentMFT", "MFT centrality (%); Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {{nBins, 0, 105.}, axisMultiplicityPV}); + + if (isMC) { + histos.add("hMultEta05VsGenMultFV0A", "Multiplicity FV0A; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFT0M", "Multiplicity FT0M; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFT0A", "Multiplicity FT0A; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFT0C", "Multiplicity FT0C; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFT0CVar1", "Multiplicity FT0CVar1; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFT0CVar2", "Multiplicity FT0CVar2; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultFDDM", "Multiplicity FDDM; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultNTPV", "Multiplicity NTPV; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultNGlobal", "Multiplicity NGlobal; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + histos.add("hMultEta05VsGenMultMFT", "Multiplicity MFT; Multiplicity PV contributors (|#it{#eta}| < 0.5)", kTH2D, {axisMultiplicity, axisMultiplicityPV}); + } + } + + histos.print(); + } + + template + bool isEventAccepted(TCollision const& collision) + // check whether the collision passes our collision selections + { + if constexpr ( + requires { collision.centFV0A(); } || + requires { collision.centFT0M(); } || + requires { collision.centFT0A(); } || + requires { collision.centFT0C(); } || + requires { collision.centFT0CVariant1(); } || + requires { collision.centFT0CVariant2(); } || + requires { collision.centFDDM(); } || + requires { collision.centNTPV(); } || + requires { collision.centNGlobal(); } || + requires { collision.centMFT(); }) { // check if we are in Run 3 + if (eventSelections.requireSel8 && !collision.sel8()) { + return false; + } + + if (eventSelections.requireTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (eventSelections.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (eventSelections.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (std::abs(collision.posZ()) > eventSelections.maxZVtxPosition) { + return false; + } + + if (eventSelections.requireIsBBT0A && !collision.selection_bit(aod::evsel::kIsBBT0A)) { + return false; + } + + if (eventSelections.requireIsBBT0C && !collision.selection_bit(aod::evsel::kIsBBT0C)) { + return false; + } + + if (eventSelections.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventSelections.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (eventSelections.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + + if (eventSelections.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return false; + } + + if (eventSelections.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (eventSelections.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + if (eventSelections.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + + if (eventSelections.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + return false; + } + + if (eventSelections.requireNoCollInROFStd && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + + if (eventSelections.requireNoCollInROFStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + + if (eventSelections.requireINEL0 && collision.multNTracksPVeta1() < 1) { + return false; + } + + if (eventSelections.requireINEL1 && collision.multNTracksPVeta1() < 2) { + return false; + } + + float collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (eventSelections.minOccupancy >= 0 && collisionOccupancy < eventSelections.minOccupancy) { + return false; + } + + if (eventSelections.maxOccupancy >= 0 && collisionOccupancy > eventSelections.maxOccupancy) { + return false; + } + + if constexpr (requires { collision.has_mcCollision(); }) { // check if we are in MC + if (!collision.has_mcCollision()) { + return false; + } + + const auto& mcCollision = collision.template mcCollision_as>(); + const auto& recoBC = collision.template bc_as>(); + const auto& foundBC = collision.template foundBC_as>(); + const auto& mcBC = mcCollision.template bc_as>(); + + // Check that the BC in data and MC is the same + if (eventSelections.rejectMismatchedBCs && recoBC.globalBC() != mcBC.globalBC()) { + return false; + } + if (eventSelections.rejectMismatchedFoundBCs && foundBC.globalBC() != mcBC.globalBC()) { + return false; + } + } + } else { // we are in Run 2 + if (eventSelections.requireSel8 && !collision.sel8()) { + return false; + } + + if (eventSelections.requireSel7 && !collision.sel7()) { + return false; + } + + if (eventSelections.requireINT7 && !collision.alias_bit(kINT7)) { + return false; + } + + if (eventSelections.requireTriggerTVX && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (eventSelections.rejectIncompleteDAQ && !collision.selection_bit(o2::aod::evsel::kNoIncompleteDAQ)) { + return false; + } + + if (std::abs(collision.posZ()) > eventSelections.maxZVtxPosition) { + return false; + } + + if (eventSelections.requireConsistentSPDAndTrackVtx && !collision.selection_bit(o2::aod::evsel::kNoInconsistentVtx)) { + return false; + } + + if (eventSelections.rejectPileupFromSPD && !collision.selection_bit(o2::aod::evsel::kNoPileupFromSPD)) { + return false; + } + + if (eventSelections.rejectV0PFPileup && !collision.selection_bit(o2::aod::evsel::kNoV0PFPileup)) { + return false; + } + + if (eventSelections.rejectPileupInMultBins && !collision.selection_bit(o2::aod::evsel::kNoPileupInMultBins)) { + return false; + } + + if (eventSelections.rejectPileupMV && !collision.selection_bit(o2::aod::evsel::kNoPileupMV)) { + return false; + } + + if (eventSelections.rejectTPCPileup && !collision.selection_bit(o2::aod::evsel::kNoPileupTPC)) { + return false; + } + + if (eventSelections.requireNoV0MOnVsOffPileup && !collision.selection_bit(o2::aod::evsel::kNoV0MOnVsOfPileup)) { + return false; + } + + if (eventSelections.requireNoSPDOnVsOffPileup && !collision.selection_bit(o2::aod::evsel::kNoSPDOnVsOfPileup)) { + return false; + } + + if (eventSelections.requireNoSPDClsVsTklBG && !collision.selection_bit(o2::aod::evsel::kNoSPDClsVsTklBG)) { + return false; + } + + if (eventSelections.requireINEL0 && collision.multNTracksPVeta1() < 1) { + return false; + } + + if (eventSelections.requireINEL1 && collision.multNTracksPVeta1() < 2) { + return false; + } } - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + + return true; + } + + void processRun2PP(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } LOGF(debug, "centV0M=%.0f", col.centRun2V0M()); LOGF(debug, "centSPDTracklets=%.0f", col.centRun2SPDTracklets()); LOGF(debug, "centSPDClusters=%.0f", col.centRun2SPDClusters()); // fill centrality histos - hCentRun2V0M->Fill(col.centRun2V0M()); - hCentRun2SPDTks->Fill(col.centRun2SPDTracklets()); - hCentRun2SPDCls->Fill(col.centRun2SPDClusters()); + histos.fill(HIST("hCentRun2V0M"), col.centRun2V0M()); + histos.fill(HIST("hCentRun2SPDTks"), col.centRun2SPDTracklets()); + histos.fill(HIST("hCentRun2SPDCls"), col.centRun2SPDClusters()); } PROCESS_SWITCH(CentralityQa, processRun2PP, "Process with Run2 SPD clusters centrality/multiplicity estimation", false); void processRun2PbPb(soa::Join::iterator const& col) { - if (!col.alias_bit(kINT7)) { - return; - } - if (!col.sel7()) { - return; - } - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } LOGF(debug, "centV0M=%.0f", col.centRun2V0M()); @@ -89,127 +384,297 @@ struct CentralityQa { LOGF(debug, "centCL0=%.0f", col.centRun2CL0()); LOGF(debug, "centCL1=%.0f", col.centRun2CL1()); // fill centrality histos - hCentRun2V0M->Fill(col.centRun2V0M()); - hCentRun2SPDTks->Fill(col.centRun2SPDTracklets()); - hCentRun2CL0->Fill(col.centRun2CL0()); - hCentRun2CL1->Fill(col.centRun2CL1()); + histos.fill(HIST("hCentRun2V0M"), col.centRun2V0M()); + histos.fill(HIST("hCentRun2SPDTks"), col.centRun2SPDTracklets()); + histos.fill(HIST("hCentRun2CL0"), col.centRun2CL0()); + histos.fill(HIST("hCentRun2CL1"), col.centRun2CL1()); } PROCESS_SWITCH(CentralityQa, processRun2PbPb, "Process with Run2 CL0 and CL1 multiplicities centrality/multiplicity estimation", false); void processRun2PPb(soa::Join::iterator const& col) { - if (!col.alias_bit(kINT7)) { - return; - } - if (!col.sel7()) { - return; - } - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } LOGF(debug, "centV0A=%.0f", col.centRun2V0A()); // fill centrality histos - hCentRun2V0A->Fill(col.centRun2V0A()); + histos.fill(HIST("hCentRun2V0A"), col.centRun2V0A()); } PROCESS_SWITCH(CentralityQa, processRun2PPb, "Process with Run2 V0A multiplicitY centrality/multiplicity estimation", false); void processRun3_FV0A(soa::Join::iterator const& col) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { + return; + } + LOGF(debug, "centFV0A=%.0f", col.centFV0A()); + histos.fill(HIST("hCentFV0A"), col.centFV0A()); + histos.fill(HIST("hCentProfileFV0A"), col.centFV0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFV0A"), col.centFV0A(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_FV0A, "Process with Run 3 FV0A estimator", false); + + void processRun3_FT0M(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + LOGF(debug, "centFT0M=%.0f", col.centFT0M()); + histos.fill(HIST("hCentFT0M"), col.centFT0M()); + histos.fill(HIST("hCentProfileFT0M"), col.centFT0M(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0M"), col.centFT0M(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_FT0M, "Process with Run 3 FT0M estimator", false); + + void processRun3_FT0A(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + histos.fill(HIST("hCentFT0A"), col.centFT0A()); + histos.fill(HIST("hCentProfileFT0A"), col.centFT0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0A"), col.centFT0A(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_FT0A, "Process with Run 3 FT0A estimator", false); + + void processRun3_FT0C(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - LOGF(debug, "centFV0A=%.0f", col.centFV0A()); - hCentFV0A->Fill(col.centFV0A()); - hCentProfileFV0A->Fill(col.centFV0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hCentFT0C"), col.centFT0C()); + histos.fill(HIST("hCentProfileFT0C"), col.centFT0C(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0C"), col.centFT0C(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_FV0A, "Process with Run 3 FV0A estimator", false); + PROCESS_SWITCH(CentralityQa, processRun3_FT0C, "Process with Run 3 FT0C estimator", false); - void processRun3_FT0M(soa::Join::iterator const& col) + void processRun3_FT0CVar1(soa::Join::iterator const& col) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + histos.fill(HIST("hCentFT0CVar1"), col.centFT0CVariant1()); + histos.fill(HIST("hCentProfileFT0CVar1"), col.centFT0CVariant1(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0CVar1"), col.centFT0CVariant1(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_FT0CVar1, "Process with Run 3 FT0CVar1 estimator", false); + + void processRun3_FT0CVar2(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + histos.fill(HIST("hCentFT0CVar2"), col.centFT0CVariant2()); + histos.fill(HIST("hCentProfileFT0CVar2"), col.centFT0CVariant2(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0CVar2"), col.centFT0CVariant2(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_FT0CVar2, "Process with Run 3 FT0CVar2 estimator", false); + + void processRun3_FDDM(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - LOGF(debug, "centFT0M=%.0f", col.centFT0M()); - hCentFT0M->Fill(col.centFT0M()); - hCentProfileFT0M->Fill(col.centFT0M(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hCentFDDM"), col.centFDDM()); + histos.fill(HIST("hCentProfileFDDM"), col.centFDDM(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFDDM"), col.centFDDM(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_FT0M, "Process with Run 3 FT0M estimator", false); + PROCESS_SWITCH(CentralityQa, processRun3_FDDM, "Process with Run 3 FDDM estimator", false); - void processRun3_FT0A(soa::Join::iterator const& col) + void processRun3_NTPV(soa::Join::iterator const& col) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + histos.fill(HIST("hCentNTPV"), col.centNTPV()); + histos.fill(HIST("hCentProfileNTPV"), col.centNTPV(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentNTPV"), col.centNTPV(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_NTPV, "Process with Run 3 NTPV estimator", false); + + void processRun3_NGlobal(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + histos.fill(HIST("hCentNGlobal"), col.centNGlobal()); + histos.fill(HIST("hCentProfileNGlobal"), col.centNGlobal(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentNGlobal"), col.centNGlobal(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processRun3_NGlobal, "Process with Run 3 NGlobal estimator", false); + + void processRun3_MFT(soa::Join::iterator const& col) + { + if (!isEventAccepted(col)) { return; } - hCentFT0A->Fill(col.centFT0A()); - hCentProfileFT0A->Fill(col.centFT0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hCentMFT"), col.centMFT()); + histos.fill(HIST("hCentProfileMFT"), col.centMFT(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentMFT"), col.centMFT(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_FT0A, "Process with Run 3 FT0A estimator", false); + PROCESS_SWITCH(CentralityQa, processRun3_MFT, "Process with Run 3 MFT estimator", false); - void processRun3_FT0C(soa::Join::iterator const& col) + void processMonteCarloRun3_FV0A(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + const auto& mcCol = col.mcCollision_as>(); + + LOGF(debug, "centFV0A=%.0f", col.centFV0A()); + histos.fill(HIST("hCentFV0A"), col.centFV0A()); + histos.fill(HIST("hCentProfileFV0A"), col.centFV0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFV0A"), col.centFV0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFV0A"), mcCol.multMCFV0A(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FV0A, "Process with Run 3 FV0A estimator", false); + + void processMonteCarloRun3_FT0M(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + const auto& mcCol = col.mcCollision_as>(); + + LOGF(debug, "centFT0M=%.0f", col.centFT0M()); + histos.fill(HIST("hCentFT0M"), col.centFT0M()); + histos.fill(HIST("hCentProfileFT0M"), col.centFT0M(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0M"), col.centFT0M(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFT0M"), mcCol.multMCFT0A() + mcCol.multMCFT0C(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FT0M, "Process with Run 3 FT0M estimator", false); + + void processMonteCarloRun3_FT0A(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - hCentFT0C->Fill(col.centFT0C()); - hCentProfileFT0C->Fill(col.centFT0C(), col.multNTracksPVetaHalf()); + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFT0A"), col.centFT0A()); + histos.fill(HIST("hCentProfileFT0A"), col.centFT0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0A"), col.centFT0A(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFT0A"), mcCol.multMCFT0A(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_FT0C, "Process with Run 3 FT0A estimator", false); + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FT0A, "Process with Run 3 FT0A estimator", false); - void processRun3_FDDM(soa::Join::iterator const& col) + void processMonteCarloRun3_FT0C(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFT0C"), col.centFT0C()); + histos.fill(HIST("hCentProfileFT0C"), col.centFT0C(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0C"), col.centFT0C(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFT0C"), mcCol.multMCFT0C(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FT0C, "Process with Run 3 FT0C estimator", false); + + void processMonteCarloRun3_FT0CVar1(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFT0CVar1"), col.centFT0CVariant1()); + histos.fill(HIST("hCentProfileFT0CVar1"), col.centFT0CVariant1(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0CVar1"), col.centFT0CVariant1(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFT0CVar1"), mcCol.multMCFT0C(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FT0CVar1, "Process with Run 3 FT0CVar1 estimator", false); + + void processMonteCarloRun3_FT0CVar2(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - hCentFDDM->Fill(col.centFDDM()); - hCentProfileFDDM->Fill(col.centFDDM(), col.multNTracksPVetaHalf()); + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFT0CVar2"), col.centFT0CVariant2()); + histos.fill(HIST("hCentProfileFT0CVar2"), col.centFT0CVariant2(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFT0CVar2"), col.centFT0CVariant2(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFT0CVar2"), mcCol.multMCFT0C(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_FDDM, "Process with Run 3 FDDM estimator", false); + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FT0CVar2, "Process with Run 3 FT0CVar2 estimator", false); - void processRun3_NTPV(soa::Join::iterator const& col) + void processMonteCarloRun3_FDDM(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) { - if (INELgtZERO && col.multNTracksPVeta1() < 1) { + if (!isEventAccepted(col)) { return; } - if (!col.sel8()) { + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFDDM"), col.centFDDM()); + histos.fill(HIST("hCentProfileFDDM"), col.centFDDM(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentFDDM"), col.centFDDM(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultFDDM"), mcCol.multMCFDDA() + mcCol.multMCFDDC(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_FDDM, "Process with Run 3 FDDM estimator", false); + + void processMonteCarloRun3_NTPV(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - if (std::abs(col.posZ()) > vertexZcut) { + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentFDDM"), col.centNTPV()); + histos.fill(HIST("hCentProfileNTPV"), col.centNTPV(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentNTPV"), col.centNTPV(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultNTPV"), mcCol.multMCNParticlesEta08(), col.multNTracksPVetaHalf()); + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_NTPV, "Process with Run 3 NTPV estimator", false); + + void processMonteCarloRun3_NGlobal(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { return; } - hCentNTPV->Fill(col.centNTPV()); - hCentProfileNTPV->Fill(col.centNTPV(), col.multNTracksPVetaHalf()); + const auto& mcCol = col.mcCollision_as>(); + + histos.fill(HIST("hCentNGlobal"), col.centNGlobal()); + histos.fill(HIST("hCentProfileNGlobal"), col.centNGlobal(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentNGlobal"), col.centNGlobal(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsGenMultNGlobal"), mcCol.multMCNParticlesEta08(), col.multNTracksPVetaHalf()); } - PROCESS_SWITCH(CentralityQa, processRun3_NTPV, "Process with Run 3 NTPV estimator", false); + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_NGlobal, "Process with Run 3 NGlobal estimator", false); + + void processMonteCarloRun3_MFT(soa::Join::iterator const& col, + soa::Join const& /*mcCollisions*/, + soa::Join const& /*bcs*/) + { + if (!isEventAccepted(col)) { + return; + } + // const auto& mcCol = col.mcCollision_as>(); // FIXME: uncomment when MC MFT mult is added in aod::MultMCExtras + + histos.fill(HIST("hCentMFT"), col.centMFT()); + histos.fill(HIST("hCentProfileMFT"), col.centMFT(), col.multNTracksPVetaHalf()); + histos.fill(HIST("hMultEta05VsCentMFT"), col.centMFT(), col.multNTracksPVetaHalf()); + // histos.fill(HIST("hMultEta05VsGenMultMFT"), mcCol.multMCMFT(), col.multNTracksPVetaHalf()); // FIXME: uncomment when MC MFT mult is added in aod::MultMCExtras + } + PROCESS_SWITCH(CentralityQa, processMonteCarloRun3_MFT, "Process with Run 3 MFT estimator", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 7c1254c63da6f019f587e74e31fd2e7d1cc54d3f Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Tue, 2 Jun 2026 19:25:23 +0800 Subject: [PATCH 389/449] [PWGCF] Added new plot with different weight (#16502) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 83 ++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index 75b748d1523..d779826c5fd 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -551,6 +551,12 @@ struct PidFlowPtCorr { oba4Ch->Add(new TNamed("ptSquareAve", "ptSquareAve")); oba4Ch->Add(new TNamed("ptAve", "ptAve")); oba4Ch->Add(new TNamed("hMeanPt", "hMeanPt")); + + oba4Ch->Add(new TNamed("covV2PtWeightOne", "covV2PtWeightOne")); + oba4Ch->Add(new TNamed("c22TrackWeightOne", "c22TrackWeightOne")); + oba4Ch->Add(new TNamed("hMeanPtWeightOne", "hMeanPtWeightOne")); + oba4Ch->Add(new TNamed("ptAveWeightOne", "ptAveWeightOne")); + oba4Ch->Add(new TNamed("ptSquareAveWeightOne", "ptSquareAveWeightOne")); // end fill TObjArray for charged // init fFCCh @@ -591,7 +597,7 @@ struct PidFlowPtCorr { registry.add("meanptCentNbs/hChargedPionWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedPionFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hPion", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); - registry.add("meanptCentNbs/hPionMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); if (switchsOpts.cfgClosureTest.value != 0) { registry.add("meanptCentNbs/hPionMeanptWeightC22pure", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); @@ -602,12 +608,12 @@ struct PidFlowPtCorr { registry.add("meanptCentNbs/hChargedKaonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedKaonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hKaon", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); - registry.add("meanptCentNbs/hKaonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hKaonMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedProtonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedProtonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hProton", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); - registry.add("meanptCentNbs/hProtonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hProtonMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); // end pid // end init tprofile3d for <2'> - meanpt @@ -689,9 +695,9 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {2} poiPiP08 {-2}", "PiPi08gap22", false)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {2} poiKaP08 {-2}", "KaKa08gap22", false)); // 30 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN08 {2} poiPrP08 {-2}", "PrPr08gap22", false)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {3} poiPiP08 {-3}", "PiPi08gap22", false)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} poiKaP08 {-3}", "KaKa08gap22", false)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN08 {3} poiPrP08 {-3}", "PrPr08gap22", false)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {3} poiPiP08 {-3}", "PiPi08gap33", false)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} poiKaP08 {-3}", "KaKa08gap33", false)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN08 {3} poiPrP08 {-3}", "PrPr08gap33", false)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN {2} refP {-2}", "Pion0gap22a", false)); // 35 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiP {2} refN {-2}", "Pion0gap22b", false)); @@ -1075,7 +1081,7 @@ struct PidFlowPtCorr { return; registry.fill(HIST("meanptCentNbs/hCharged"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, val, nch * dnx); - registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, nch * dnx * val); + registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, 1.); } /** @@ -1116,7 +1122,7 @@ struct PidFlowPtCorr { registry.fill(HIST("meanptCentNbs/hPion"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); registry.fill(HIST("meanptCentNbs/hChargedPionFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedPionWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); - registry.fill(HIST("meanptCentNbs/hPionMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + registry.fill(HIST("meanptCentNbs/hPionMeanpt"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, 1.); if (switchsOpts.cfgClosureTest.value != 0) { double npair4c22pure = fGFW->Calculate(corrconfigs.at(29), 0, true).real(); @@ -1151,7 +1157,7 @@ struct PidFlowPtCorr { registry.fill(HIST("meanptCentNbs/hKaon"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); registry.fill(HIST("meanptCentNbs/hChargedKaonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedKaonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); - registry.fill(HIST("meanptCentNbs/hKaonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + registry.fill(HIST("meanptCentNbs/hKaonMeanpt"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, 1.); break; // end kaon @@ -1168,7 +1174,7 @@ struct PidFlowPtCorr { registry.fill(HIST("meanptCentNbs/hProton"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); registry.fill(HIST("meanptCentNbs/hChargedProtonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedProtonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); - registry.fill(HIST("meanptCentNbs/hProtonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + registry.fill(HIST("meanptCentNbs/hProtonMeanpt"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, 1.); break; // end proton @@ -1247,7 +1253,14 @@ struct PidFlowPtCorr { return; } - void fillFCvnpt(MyParticleType type, const GFW::CorrConfig& corrconf, const double& cent, const double& rndm, const double& ptSum, const double& nch, const char* tarName) + void fillFCvnpt(MyParticleType type, + const GFW::CorrConfig& corrconf, + const double& cent, + const double& rndm, + const double& ptSum, + const double& nch, + const char* tarName, + bool useWeightOne = false) { double dnx, val; dnx = fGFW->Calculate(corrconf, 0, true).real(); @@ -1257,17 +1270,17 @@ struct PidFlowPtCorr { if (std::fabs(val) < 1) { switch (type) { case MyParticleType::kCharged: - fFCCh->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCCh->FillProfile(tarName, cent, val * (ptSum / nch), useWeightOne ? 1.0 : dnx * nch, rndm); break; case MyParticleType::kPion: - fFCPi->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCPi->FillProfile(tarName, cent, val * (ptSum / nch), useWeightOne ? 1.0 : dnx * nch, rndm); break; case MyParticleType::kKaon: - fFCKa->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCKa->FillProfile(tarName, cent, val * (ptSum / nch), useWeightOne ? 1.0 : dnx * nch, rndm); break; case MyParticleType::kProton: - fFCPr->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCPr->FillProfile(tarName, cent, val * (ptSum / nch), useWeightOne ? 1.0 : dnx * nch, rndm); break; default: @@ -2123,6 +2136,8 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kProton, corrconfigs.at(10), cent, rndm, "c22"); } fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, nch, nch, "c22TrackWeight"); + fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, nch, nch, "c22TrackWeightOne", true); + fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(1), cent, rndm, nch, nch, "c24TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(2), cent, rndm, nch, nch, "c22FullTrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(3), cent, rndm, nch, nch, "c32TrackWeight"); @@ -2137,6 +2152,8 @@ struct PidFlowPtCorr { fillFCvnpt(MyParticleType::kProton, corrconfigs.at(34), cent, rndm, nch, nch, "c32TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, ptSum, nch, "covV2Pt"); + fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, ptSum, nch, "covV2PtWeightOne", true); + fillFCvnpt(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, ptSum, nch, "covV2Pt"); fillFCvnpt(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, ptSum, nch, "covV2Pt"); fillFCvnpt(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, ptSum, nch, "covV2Pt"); @@ -2190,21 +2207,25 @@ struct PidFlowPtCorr { } fFCCh->FillProfile("hMeanPt", cent, (ptSum / nch), nch, rndm); + fFCCh->FillProfile("hMeanPtWeightOne", cent, (ptSum / nch), 1., rndm); if (nPionWeighted > 0) { fFCPi->FillProfile("hMeanPt", cent, (pionPtSum / nPionWeighted), nPionWeighted, rndm); + fFCPi->FillProfile("hMeanPtWeightOne", cent, (pionPtSum / nPionWeighted), 1., rndm); fillFCvnpt(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, pionPtSum, nPionWeighted, "covV2PtPID"); fillFCvnpt(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, nPionWeighted, nPionWeighted, "c22TrackWeightPID"); } if (nKaonWeighted > 0) { fFCKa->FillProfile("hMeanPt", cent, (kaonPtSum / nKaonWeighted), nKaonWeighted, rndm); + fFCKa->FillProfile("hMeanPtWeightOne", cent, (kaonPtSum / nKaonWeighted), 1., rndm); fillFCvnpt(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, kaonPtSum, nKaonWeighted, "covV2PtPID"); fillFCvnpt(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, nKaonWeighted, nKaonWeighted, "c22TrackWeightPID"); } if (nProtonWeighted > 0) { fFCPr->FillProfile("hMeanPt", cent, (protonPtSum / nProtonWeighted), nProtonWeighted, rndm); + fFCPr->FillProfile("hMeanPtWeightOne", cent, (protonPtSum / nProtonWeighted), 1., rndm); fillFCvnpt(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, protonPtSum, nProtonWeighted, "covV2PtPID"); fillFCvnpt(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, nProtonWeighted, nProtonWeighted, "c22TrackWeightPID"); } @@ -2215,9 +2236,17 @@ struct PidFlowPtCorr { (ptSum * ptSum - ptSquareSum) / nchDiff, nchDiff, rndm); + fFCCh->FillProfile("ptSquareAveWeightOne", cent, + (ptSum * ptSum - ptSquareSum) / nchDiff, + 1., rndm); + fFCCh->FillProfile("ptAve", cent, (nch * ptSum - ptSumw2) / nchDiff, nchDiff, rndm); + + fFCCh->FillProfile("ptAveWeightOne", cent, + (nch * ptSum - ptSumw2) / nchDiff, + 1., rndm); } double pionDiff = nPionWeighted * nPionWeighted - nPionSquare; @@ -2226,9 +2255,17 @@ struct PidFlowPtCorr { (pionPtSum * pionPtSum - pionPtSquareSum) / pionDiff, pionDiff, rndm); + fFCPi->FillProfile("ptSquareAveWeightOne", cent, + (pionPtSum * pionPtSum - pionPtSquareSum) / pionDiff, + 1., rndm); + fFCPi->FillProfile("ptAve", cent, (nPionWeighted * pionPtSum - pionPtSumw2) / pionDiff, pionDiff, rndm); + + fFCPi->FillProfile("ptAveWeightOne", cent, + (nPionWeighted * pionPtSum - pionPtSumw2) / pionDiff, + 1., rndm); } double kaonDiff = nKaonWeighted * nKaonWeighted - nKaonSquare; @@ -2237,9 +2274,17 @@ struct PidFlowPtCorr { (kaonPtSum * kaonPtSum - kaonPtSquareSum) / kaonDiff, kaonDiff, rndm); + fFCKa->FillProfile("ptSquareAveWeightOne", cent, + (kaonPtSum * kaonPtSum - kaonPtSquareSum) / kaonDiff, + 1., rndm); + fFCKa->FillProfile("ptAve", cent, (nKaonWeighted * kaonPtSum - kaonPtSumw2) / kaonDiff, kaonDiff, rndm); + + fFCKa->FillProfile("ptAveWeightOne", cent, + (nKaonWeighted * kaonPtSum - kaonPtSumw2) / kaonDiff, + 1., rndm); } double protonDiff = nProtonWeighted * nProtonWeighted - nProtonSquare; @@ -2248,9 +2293,17 @@ struct PidFlowPtCorr { (protonPtSum * protonPtSum - protonPtSquareSum) / protonDiff, protonDiff, rndm); + fFCPr->FillProfile("ptSquareAveWeightOne", cent, + (protonPtSum * protonPtSum - protonPtSquareSum) / protonDiff, + 1., rndm); + fFCPr->FillProfile("ptAve", cent, (nProtonWeighted * protonPtSum - protonPtSumw2) / protonDiff, protonDiff, rndm); + + fFCPr->FillProfile("ptAveWeightOne", cent, + (nProtonWeighted * protonPtSum - protonPtSumw2) / protonDiff, + 1., rndm); } } // end fill hist using fillProfile From f138bc1eb56c457b9f574c797075dbe8ae7ae80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:29:11 +0200 Subject: [PATCH 390/449] [PWGEM] Fix includes (#16412) --- PWGEM/Dilepton/DataModel/dileptonTables.h | 1 + PWGEM/Dilepton/DataModel/lmeeMLTables.h | 1 - .../skimmerPrimaryElectronSCT.cxx | 20 ------------------- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 5 +++++ 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 0b57232eea5..425b4e0cb97 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index fed4529ed29..6c973115b9b 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -13,7 +13,6 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" #include diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx index 53467cfbca6..2fa33093663 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronSCT.cxx @@ -14,54 +14,34 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/ElectronModule.h" -#include "PWGEM/Dilepton/Utils/MlResponseO2Track.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/TableHelper.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Tools/ML/MlResponse.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 // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) -#include -#include -#include #include #include -#include #include -#include -#include #include #include diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 86dd85cd25c..4292d12cc83 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -30,6 +30,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include +#include #include #include #include @@ -48,8 +49,12 @@ #include #include #include +#include #include +#include + +#include #include #include From b53ce9e7108fbfb1933421e807cd5de878a5eecd Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 2 Jun 2026 14:24:49 +0200 Subject: [PATCH 391/449] [PWGEM/Dilepton] reduce data size in treeCreatorElectronMLDDA.cxx (#16503) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 43 ++++++++-------- .../treeCreatorElectronMLDDA.cxx | 50 +++++++------------ PWGEM/Dilepton/Tasks/taggingHFE.cxx | 2 +- 3 files changed, 39 insertions(+), 56 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 6c973115b9b..c6ffc2bb93c 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -41,10 +41,21 @@ enum class Track_Type : uint8_t { } // namespace pwgem::dilepton::ml +namespace emmlevent +{ +DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of mc collision +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, float); //! +} // namespace emmlevent + +DECLARE_SOA_TABLE(EMMLEvents, "AOD", "EMMLEVENT", //! + o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmlevent::HadronicRate); +// iterators +using EMMLEvent = EMMLEvents::iterator; + namespace emmltrack { +DECLARE_SOA_INDEX_COLUMN(EMMLEvent, emmlevent); //! index to event table DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, float); //! DECLARE_SOA_COLUMN(PIDLabel, pidlabel, uint8_t); //! DECLARE_SOA_COLUMN(TrackType, tracktype, uint8_t); //! DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); //! @@ -92,22 +103,21 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 // reconstructed track information DECLARE_SOA_TABLE(EMTracksForMLPID, "AOD", "EMTRACKMLPID", //! - o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmltrack::HadronicRate, - emmltrack::P, track::Tgl, emmltrack::Sign, + o2::soa::Index<>, track::Signed1Pt, track::Tgl, track::TPCNClsFindable, emmltrack::TPCNClsFound, emmltrack::TPCNClsCrossedRows, emmltrack::TPCNClsPID, track::TPCChi2NCl, track::TPCInnerParam, - track::TPCSignal, - pidtofbeta::Beta, - track::ITSClusterSizes, track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, emmltrack::PIDLabel, + track::ITSClusterSizes, emmltrack::PIDLabel, // dynamic column emmltrack::MeanClusterSizeITS, emmltrack::MeanClusterSizeITSob); -DECLARE_SOA_TABLE(EMPIDsEl, "AOD", "EMPIDEL", pidtpc::TPCNSigmaEl, pidtof::TOFNSigmaEl); // Joinable with EMTracksForMLPID -DECLARE_SOA_TABLE(EMPIDsPi, "AOD", "EMPIDPI", pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi); // Joinable with EMTracksForMLPID -DECLARE_SOA_TABLE(EMPIDsKa, "AOD", "EMPIDKA", pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa); // Joinable with EMTracksForMLPID -DECLARE_SOA_TABLE(EMPIDsPr, "AOD", "EMPIDPR", pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDs, "AOD", "EMPID", track::TPCSignal, pidtofbeta::Beta); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDsEl, "AOD", "EMPIDEL", pidtpc::TPCNSigmaEl, pidtof::TOFNSigmaEl); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDsPi, "AOD", "EMPIDPI", pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDsKa, "AOD", "EMPIDKA", pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDsPr, "AOD", "EMPIDPR", pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr); // Joinable with EMTracksForMLPID +DECLARE_SOA_TABLE(EMPIDsSub, "AOD", "EMPIDSUB", track::ITSChi2NCl, track::TOFChi2, track::DetectorMap); // Joinable with EMTracksForMLPID, separated from track table because they are not useful for ML PID. // iterators using EMTrackForMLPID = EMTracksForMLPID::iterator; @@ -168,7 +178,7 @@ DECLARE_SOA_COLUMN(MultMFT, multMFT, uint16_t); //! number of MFTsa tracks per c } // namespace emmlfwdtrack DECLARE_SOA_TABLE(EMFwdTracksForML, "AOD", "EMFWDTRKML", //! - o2::soa::Index<>, collision::PosZ, /*collision::NumContrib,*/ mult::MultFT0C, /*evsel::NumTracksInTimeRange,*/ evsel::SumAmpFT0CInTimeRange, emmltrack::HadronicRate, emmlfwdtrack::MultMFT, + o2::soa::Index<>, collision::PosZ, /*collision::NumContrib,*/ mult::MultFT0C, /*evsel::NumTracksInTimeRange,*/ evsel::SumAmpFT0CInTimeRange, emmlevent::HadronicRate, emmlfwdtrack::MultMFT, emmlfwdtrack::Signed1PtMFTatMP, emmlfwdtrack::TglMFTatMP, emmlfwdtrack::PhiMFTatMP, emmlfwdtrack::XMFTatMP, emmlfwdtrack::YMFTatMP, @@ -194,19 +204,8 @@ DECLARE_SOA_TABLE(EMFwdTrackErrsForML, "AOD", "EMFWDTRKERRML", //! Joinable with using EMFwdTrackErrForML = EMFwdTrackErrsForML::iterator; // for SemiCharmTag at midrapidity, only electrons -namespace emmlevent -{ -DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); //! sub generator Id of mc collision -} // namespace emmlevent - -DECLARE_SOA_TABLE(EMMLEvents, "AOD", "EMMLEVENT", //! - o2::soa::Index<>, collision::Chi2, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange); -// iterators -using EMMLEvent = EMMLEvents::iterator; - namespace emmltrack { -DECLARE_SOA_INDEX_COLUMN(EMMLEvent, emmlevent); //! index to event table DECLARE_SOA_COLUMN(IsMotherFromBeauty, isMotherFromBeauty, bool); //! is b quark included in decay history DECLARE_SOA_COLUMN(Signed1PtL, signedPtL, float); //! sign/pT of lepton DECLARE_SOA_COLUMN(EtaL, etaL, float); //! eta of lepton diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index 7e04ba0aa5e..9f1019c3583 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -83,7 +83,10 @@ struct TreeCreatorElectronMLDDA { using MyTrack = MyTracks::iterator; SliceCache cache; - Produces emprimarytracks; // flat table containing collision + track information + Produces eventTable; + Produces trackTable; + Produces empid; + Produces subTable; Produces empidel; Produces empidpi; Produces empidka; @@ -167,8 +170,8 @@ struct TreeCreatorElectronMLDDA { Configurable max_p_for_downscaling_pion{"max_p_for_downscaling_pion", 2.0, "max p to apply down scaling factor to store pion"}; Configurable max_p_for_downscaling_kaon{"max_p_for_downscaling_kaon", 0.0, "max p to apply down scaling factor to store kaon"}; Configurable max_p_for_downscaling_proton{"max_p_for_downscaling_proton", 2.0, "max p to apply down scaling factor to store proton"}; - Configurable store_ele_band_only{"store_ele_band_only", false, "flag to store tracks around electron band only to reduce output size"}; - Configurable reject_v0leg_with_itsib{"reject_v0leg_with_itsib", false, "flag to reject v0 leg with ITSib hits"}; + Configurable store_ele_band_only{"store_ele_band_only", true, "flag to store tracks around electron band only to reduce output size"}; + Configurable reject_v0leg_with_itsib{"reject_v0leg_with_itsib", true, "flag to reject v0 leg with ITSib hits"}; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; @@ -228,7 +231,7 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 5.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_min_chi2its{"cfg_min_chi2its", 0.0, "min chi2/NclsITS"}; // remove ITS afterburner + Configurable cfg_min_chi2its{"cfg_min_chi2its", -1e+10, "min chi2/NclsITS"}; Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY to PV for v0 legs in cm"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -5, "min n sigma e in TPC"}; @@ -634,15 +637,6 @@ struct TreeCreatorElectronMLDDA { return is_Pr_TPC && is_Pr_TOF; } - // template - // bool isPionTightTOFreq(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) - // { - // float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Pion)]; - // bool is_Pi_TPC = tightv0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < tightv0cuts.cfg_max_TPCNsigmaPi; - // bool is_Pi_TOF = tightv0cuts.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < tightv0cuts.cfg_max_TOFNsigmaPi && std::fabs(track.tofChi2()) < tightv0cuts.cfg_max_chi2tof; // TOFreq - // return is_Pi_TPC && is_Pi_TOF; - // } - template void fillTrackTable(TCollision const& collision, TTrack const& track, const uint8_t pidlabel, const std::array tofNSigmas, const float beta, const float hadronicRate) { @@ -713,14 +707,14 @@ struct TreeCreatorElectronMLDDA { } if (std::find(stored_trackIds.begin(), stored_trackIds.end(), track.globalIndex()) == stored_trackIds.end()) { - emprimarytracks(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), hadronicRate, - trackParCov.getP(), trackParCov.getTgl(), track.sign(), - track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcNClsPID(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), - beta, - track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), pidlabel); - + eventTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), hadronicRate); + trackTable(trackParCov.getQ2Pt(), trackParCov.getTgl(), + track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcNClsPID(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.itsClusterSizes(), pidlabel); + + subTable(track.itsChi2NCl(), track.tofChi2(), track.detectorMap()); + empid(track.tpcSignal(), beta); empidel(track.tpcNSigmaEl(), tofNSigmas[0]); empidpi(track.tpcNSigmaPi(), tofNSigmas[1]); empidka(track.tpcNSigmaKa(), tofNSigmas[2]); @@ -1209,7 +1203,6 @@ struct TreeCreatorElectronMLDDA { if (v0cuts.cfg_min_qt_strangeness < v0.qtarm()) { if (v0cuts.cfg_min_qt_k0s < v0.qtarm()) { if (!(v0cuts.cfg_min_mass_lambda_veto < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda_veto) && !(v0cuts.cfg_min_mass_lambda_veto < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda_veto)) { - // if ((isPionTightTOFreq(collision, pos, o2::track::PID::K0) && isSelectedV0LegTight(collision, pos)) && (isPion(collision, neg, o2::track::PID::K0) && isSelectedV0Leg(collision, neg))) { if ((isPionTight(collision, pos, o2::track::PID::K0) && isSelectedV0LegTight(collision, pos)) && (isPion(collision, neg, o2::track::PID::K0) && isSelectedV0Leg(collision, neg))) { registry.fill(HIST("V0/hMassK0Short"), v0.mK0Short()); if (v0cuts.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s) { @@ -1224,7 +1217,6 @@ struct TreeCreatorElectronMLDDA { } } - // if (isPion(collision, pos, o2::track::PID::K0) && isSelectedV0Leg(collision, pos) && isPionTightTOFreq(collision, neg, o2::track::PID::K0) && isSelectedV0LegTight(collision, neg)) { if (isPion(collision, pos, o2::track::PID::K0) && isSelectedV0Leg(collision, pos) && isPionTight(collision, neg, o2::track::PID::K0) && isSelectedV0LegTight(collision, neg)) { registry.fill(HIST("V0/hMassK0Short"), v0.mK0Short()); if (v0cuts.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s) { @@ -1370,19 +1362,12 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("Cascade/hPCA"), cascade.dcacascdaughters()); // distance between bachelor and V0. registry.fill(HIST("Cascade/hCosPA"), cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - // float length = std::sqrt(std::pow(cascade.x() - collision.posX(), 2) + std::pow(cascade.y() - collision.posY(), 2) + std::pow(cascade.z() - collision.posZ(), 2)); - // float mom = cascade.p(); - // float ctauXi = length / mom * o2::constants::physics::MassXiMinus; // 4.91 cm in PDG - // float ctauOmega = length / mom * o2::constants::physics::MassOmegaMinus; // 2.46 cm in PDG - bool isLaProtonPiMinusFromXiMinus = isPionTight(neg.tpcNSigmaPi(), tofNSigmaPiNegFromLambdaFromXi, neg.hasTOF()) && isProtonTight(pos.tpcNSigmaPr(), tofNSigmaPrPosFromLambdaFromXi, pos.hasTOF()); bool isALaAPrPiPlusFromXiPlus = isPionTight(pos.tpcNSigmaPi(), tofNSigmaPiPosFromLambdaFromXi, pos.hasTOF()) && isProtonTight(neg.tpcNSigmaPr(), tofNSigmaPrNegFromLambdaFromXi, neg.hasTOF()); if (isPion(collision, bachelor, o2::track::PID::XiMinus) && (cascade.sign() < 0 ? isLaProtonPiMinusFromXiMinus : isALaAPrPiPlusFromXiPlus)) { registry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); registry.fill(HIST("Cascade/hMassPt_Xi"), cascade.mXi(), cascade.pt()); - // registry.fill(HIST("Cascade/hRxy_Xi"), cascade.mXi(), cascade.cascradius()); - // registry.fill(HIST("Cascade/hCTau_Xi"), cascade.mXi(), ctauXi); } bool isLaProtonPiMinusFromOmegaMinus = isPionTight(neg.tpcNSigmaPi(), tofNSigmaPiNegFromLambdaFromOmega, neg.hasTOF()) && isProtonTight(pos.tpcNSigmaPr(), tofNSigmaPrPosFromLambdaFromOmega, pos.hasTOF()); @@ -1392,8 +1377,6 @@ struct TreeCreatorElectronMLDDA { if (isKaon(collision, bachelor, o2::track::PID::OmegaMinus) && (cascade.sign() < 0 ? isLaProtonPiMinusFromOmegaMinus : isALaAPrPiPlusFromOmegaPlus)) { registry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); registry.fill(HIST("Cascade/hMassPt_Omega"), cascade.mOmega(), cascade.pt()); - // registry.fill(HIST("Cascade/hRxy_Omega"), cascade.mOmega(), cascade.cascradius()); - // registry.fill(HIST("Cascade/hCTau_Omega"), cascade.mOmega(), ctauOmega); if (cascadecuts.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < cascadecuts.cfg_max_mass_Omega) { // select Omega candidates registry.fill(HIST("V0/hTPCdEdx_P_Ka"), bachelor.tpcInnerParam(), bachelor.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)]); @@ -1408,6 +1391,7 @@ struct TreeCreatorElectronMLDDA { } } // end of cascade loop } // end of collision loop + stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -1458,7 +1442,7 @@ struct MLTrackQC { }, }; - using MyPIDTracks = soa::Join; + using MyPIDTracks = soa::Join; void processQC(MyPIDTracks const& tracks) { diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 4292d12cc83..9ed7bd73aae 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -2557,7 +2557,7 @@ struct taggingHFE { } // end of main electron sample if (npos + nele > 0) { // fill eventTable only if at least 1 electron or positron exists. - eventTable(collision.chi2(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + eventTable(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), 0); } electronIds.clear(); From d26dfb6d86b1f977c785d3364fa29444795a6179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 2 Jun 2026 14:57:11 +0200 Subject: [PATCH 392/449] [PWGJE] Fix includes (#16414) --- PWGJE/Tasks/bjetTaggingGnn.cxx | 2 -- PWGJE/Tasks/gammaJetTreeProducer.cxx | 1 + PWGJE/Tasks/jetSpectraEseTask.cxx | 1 + PWGJE/Tasks/jetSubstructureHF.h | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 314e99a77fa..fd47112f547 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -25,8 +25,6 @@ #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" #include #include diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index c117287038c..65b97d96fa9 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -51,6 +51,7 @@ #include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index de4299d79d2..a662c254867 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetSubstructureHF.h b/PWGJE/Tasks/jetSubstructureHF.h index 0dbe9aa6e3f..b0921af1f4e 100644 --- a/PWGJE/Tasks/jetSubstructureHF.h +++ b/PWGJE/Tasks/jetSubstructureHF.h @@ -19,6 +19,7 @@ #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/Core/JetHFUtilities.h" From f5f12aa22154a3d927bc583f524049b326a08c45 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:40:16 +0530 Subject: [PATCH 393/449] [PWGCF] Fixed a Bug with efficiency correction (taking reciprocal of efficiency twice) (#16505) --- PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index a83f25f8e3b..921c33cfed4 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -935,7 +935,7 @@ struct V0ptHadPiKaProt { } template - float getEffAllCharged(const T& candidate) + float getEffWeightAllCharged(const T& candidate) { if (!cfgLoadPtEffWeights || !hEffAllCharged) { return 1.0; @@ -950,7 +950,7 @@ struct V0ptHadPiKaProt { } template - float getEffPion(const T& candidate) + float getEffWeightPion(const T& candidate) { if (!cfgLoadPtEffWeights || !hEffPion) { return 1.0; @@ -965,7 +965,7 @@ struct V0ptHadPiKaProt { } template - float getEffKaon(const T& candidate) + float getEffWeightKaon(const T& candidate) { if (!cfgLoadPtEffWeights || !hEffKaon) { return 1.0; @@ -980,7 +980,7 @@ struct V0ptHadPiKaProt { } template - float getEffProton(const T& candidate) + float getEffWeightProton(const T& candidate) { if (!cfgLoadPtEffWeights || !hEffProton) { return 1.0; @@ -1405,7 +1405,7 @@ struct V0ptHadPiKaProt { double effweight = 1.0; if (cfgLoadPtEffWeights) { - effweight = 1.0 / getEffAllCharged(track); // NUE weight + effweight = getEffWeightAllCharged(track); // NUE weight } // inclusive charged particles @@ -1523,9 +1523,9 @@ struct V0ptHadPiKaProt { double effweightKaon = 1.0; double effweightProton = 1.0; if (cfgLoadPtEffWeights) { - effweightPion = 1.0 / getEffPion(track); // NUE weight for pion - effweightKaon = 1.0 / getEffKaon(track); // NUE weight for kaon - effweightProton = 1.0 / getEffProton(track); // NUE weight for proton + effweightPion = getEffWeightPion(track); // NUE weight for pion + effweightKaon = getEffWeightKaon(track); // NUE weight for kaon + effweightProton = getEffWeightProton(track); // NUE weight for proton } if (track.sign() != 0) { From 3a2ebfb256ad09a8aa1223a1e0cea2c443716e9a Mon Sep 17 00:00:00 2001 From: Thorkj <154221526+Thorkj@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:46:23 +0300 Subject: [PATCH 394/449] [PWGCF] Updated Nch calculation used in tracks counter (#16475) --- .../TwoParticleCorrelations/Tasks/corrFit.cxx | 159 ++++++++++++++---- 1 file changed, 126 insertions(+), 33 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx index b873791944b..dc343428a4c 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrFit.cxx @@ -71,6 +71,12 @@ struct CorrFit { O2_DEFINE_CONFIGURABLE(cfgUseTransverseMomentum, bool, false, "Use transverse momentum for correlation container") O2_DEFINE_CONFIGURABLE(cfgQaCheck, bool, true, "Enable QA histograms for event selection") O2_DEFINE_CONFIGURABLE(cfgStrictTrackCounter, bool, false, "Strict track counter for multiplicity correlation cut, counts only tracks that pass all cuts and are used in the correlation") + O2_DEFINE_CONFIGURABLE(cfgRefpTt, bool, false, "Apply upper pT cut on reference tracks") + O2_DEFINE_CONFIGURABLE(cfgRefpTMax, float, 3.0f, "maximum pT for reference tracks if cfgRefpTt is true") + O2_DEFINE_CONFIGURABLE(cfgMinMultForCorrelations, int, 0, "minimum multiplicity for correlations") + O2_DEFINE_CONFIGURABLE(cfgMaxMultForCorrelations, int, 20, "maximum multiplicity for correlations") + O2_DEFINE_CONFIGURABLE(cfgRefMultiplicity, bool, false, "Use multiplicity of reference tracks for multiplicity correlation cut instead of Nch") + struct : ConfigurableGroup{ O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") @@ -116,8 +122,10 @@ struct CorrFit { O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyNch, std::string, "", "CCDB path to multiplicity dependent efficiency object") O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiencyNch, bool, false, "Use local multiplicity dependent efficiency object"); O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") struct : ConfigurableGroup { @@ -167,7 +175,7 @@ struct CorrFit { ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; ConfigurableAxis axisDeltaEtaFt0aFt0c{"axisDeltaEtaFt0aFt0c", {32, -1.5, 3.0}, "delta eta axis"}; - ConfigurableAxis axisDeltaEtaTpcTpc{"axisDeltaEtaTpcTpc", {32, -0.8, 0.8}, "delta eta axis for TPC-TPC"}; + ConfigurableAxis axisDeltaEtaTpcTpc{"axisDeltaEtaTpcTpc", {32, -1.6, 1.6}, "delta eta axis for TPC-TPC"}; ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; @@ -200,6 +208,7 @@ struct CorrFit { // Corrections TH3D* mEfficiency = nullptr; + TH1D* mEfficiencyNch = nullptr; TH1D* mCentralityWeight = nullptr; bool correctionsLoaded = false; @@ -288,6 +297,9 @@ struct CorrFit { registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); } + if (cfgQaCheck) { + registry.add("Nch_corrected", "N_{ch} corrected", {HistType::kTH1D, {axisMult}}); + } } if (doprocessSameTpcFt0a) { @@ -353,7 +365,7 @@ struct CorrFit { {axisPtTrigger, "p_{T} (GeV/c)"}, {axisMult, "N_{ch}"}, {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; // use the same delta eta axis for TPC-TPC correlation + {axisDeltaEtaTpcTpc, "#Delta#eta"}}; // use the same delta eta axis for TPC-TPC correlation if (doprocessSameTpcFt0a) { sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); @@ -673,9 +685,10 @@ struct CorrFit { return; } if (cfgEfficiency.value.empty() == false) { - if (cfgLocalEfficiency > 0) { + if (cfgLocalEfficiency) { TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); } @@ -684,6 +697,19 @@ struct CorrFit { } LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); } + if (cfgEfficiencyNch.value.empty() == false) { + if (cfgLocalEfficiencyNch) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiencyNch.value.c_str(), "READ"); + mEfficiencyNch = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + + } else { + mEfficiencyNch = ccdb->getForTimeStamp(cfgEfficiencyNch, timestamp); + } + if (!mEfficiencyNch) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiencyNch.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiencyNch.value.c_str(), (void*)mEfficiencyNch); + } if (cfgCentralityWeight.value.empty() == false) { mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); if (mCentralityWeight == nullptr) { @@ -694,20 +720,39 @@ struct CorrFit { correctionsLoaded = true; } - bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) + bool getEfficiencyCorrection_Nch(float& weight_Nch, float pt) + { + float eff_Nch = 1.; + if (mEfficiencyNch) { + + int ptBin = mEfficiencyNch->FindBin(pt); + eff_Nch = mEfficiencyNch->GetBinContent(ptBin); + + } else { + eff_Nch = 1.0; + } + if (eff_Nch == 0) + return false; + weight_Nch = 1. / eff_Nch; + return true; + } + + bool getEfficiencyCorrection(float& weight, float pt, float eta, float vertex) { float eff = 1.; if (mEfficiency) { - int etaBin = mEfficiency->GetXaxis()->FindBin(eta); + + int etaBin = mEfficiency->GetXaxis()->FindBin(eta); // use the eta bin corresponding to eta=0 for the trigger particle efficiency int ptBin = mEfficiency->GetYaxis()->FindBin(pt); - int zBin = mEfficiency->GetZaxis()->FindBin(posZ); - eff = mEfficiency->GetBinContent(etaBin, ptBin, zBin); + int vertexBin = mEfficiency->GetZaxis()->FindBin(vertex); // use the vertex bin corresponding to z=0 for the trigger particle efficiency + eff = mEfficiency->GetBinContent(etaBin, ptBin, vertexBin); + } else { eff = 1.0; } if (eff == 0) return false; - weight_nue = 1. / eff; + weight = 1. / eff; return true; } @@ -727,16 +772,24 @@ struct CorrFit { } template - void trackCounter(TTracks tracks, int& multiplicity) // function to count the number of tracks in the event and fill the histogram + void trackCounter(TTracks tracks, double& multiplicity) // function to count the number of tracks in the event and fill the histogram { - int mult = 0; + double nTracksCorrected = 0; + float weight_Nch = 1.0f; for (auto const& track : tracks) { - if (!trackSelected(track)) + if (cfgRefMultiplicity) { + if (track.pt() > cfgRefpTMax) + continue; + } + + if (!getEfficiencyCorrection_Nch(weight_Nch, track.pt())) { continue; - mult++; + } + + nTracksCorrected += weight_Nch; } - multiplicity = mult; + multiplicity = nTracksCorrected; } template @@ -757,7 +810,7 @@ struct CorrFit { continue; } - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + if (!getEfficiencyCorrection(triggerWeight, track1.pt(), track1.eta(), posZ)) continue; if (system == SameEvent) { @@ -828,13 +881,15 @@ struct CorrFit { float weff1 = 1.0; float zvtx = collision.posZ(); + registry.fill(HIST("zVtx"), zvtx); + registry.fill(HIST("Nch"), tracks.size()); for (auto const& track1 : tracks) { if (!trackSelected(track1)) { continue; } - if (!getEfficiencyCorrection(weff1, track1.eta(), track1.pt(), zvtx)) { + if (!getEfficiencyCorrection_Nch(weff1, track1.pt())) { continue; } @@ -903,18 +958,15 @@ struct CorrFit { float triggerWeight = 1.0f; + float associateWeight = 1.0f; + // loop over all tracks for (auto const& track1 : tracks1) { if (!trackSelected(track1)) continue; - if (cfgSystematics.cfgSystematicsVariation) { - if (!trackSelectedSystematics(track1)) - continue; - } - - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + if (!getEfficiencyCorrection_Nch(triggerWeight, track1.pt())) continue; if (system == SameEvent) { @@ -926,6 +978,14 @@ struct CorrFit { if (!trackSelected(track2)) continue; + if (!getEfficiencyCorrection_Nch(associateWeight, track2.pt())) + continue; + + if (cfgRefpTt) { + if (track2.pt() > cfgRefpTMax) { + continue; + } + } if (track1.pt() <= track2.pt()) continue; // skip if the trigger pt is less than the associate pt @@ -957,16 +1017,16 @@ struct CorrFit { // fill the right sparse and histograms if (system == SameEvent) { - sameTPC->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta); + sameTPC->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta, triggerWeight * associateWeight); if (cfgQaCheck) { - registry.fill(HIST("deltaEta_deltaPhi_same_TPC"), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC"), deltaPhi, deltaEta, triggerWeight * associateWeight); } } else if (system == MixedEvent) { - mixedTPC->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta); + mixedTPC->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), multiplicity, deltaPhi, deltaEta, triggerWeight * associateWeight); if (cfgQaCheck) { - registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC"), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC"), deltaPhi, deltaEta, triggerWeight * associateWeight); } } } @@ -1004,12 +1064,20 @@ struct CorrFit { fillYield(collision, tracks); - int multiplicity = tracks.size(); + double multiplicity = tracks.size(); if (cfgStrictTrackCounter) { trackCounter(tracks, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + + if (multiplicity > cfgMaxMultForCorrelations || multiplicity < cfgMinMultForCorrelations) { + return; + } + const auto& ft0 = collision.foundFT0(); fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, multiplicity, kFT0A, eventWeight); } @@ -1054,12 +1122,16 @@ struct CorrFit { loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - int multiplicity = tracks1.size(); + double multiplicity = tracks1.size(); if (cfgStrictTrackCounter) { trackCounter(tracks1, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + const auto& ft0 = collision2.foundFT0(); fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, multiplicity, kFT0A, eventWeight); } @@ -1095,12 +1167,16 @@ struct CorrFit { const auto& ft0 = collision.foundFT0(); - int multiplicity = tracks.size(); + double multiplicity = tracks.size(); if (cfgStrictTrackCounter) { trackCounter(tracks, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, multiplicity, kFT0C, 1.0f); } PROCESS_SWITCH(CorrFit, processSameTpcFt0c, "Process same event for TPC-FT0C correlation", false); @@ -1144,12 +1220,16 @@ struct CorrFit { float eventWeight = 1.0f; const auto& ft0 = collision2.foundFT0(); - int multiplicity = tracks1.size(); + double multiplicity = tracks1.size(); if (cfgStrictTrackCounter) { trackCounter(tracks, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, multiplicity, kFT0C, eventWeight); } } @@ -1187,12 +1267,16 @@ struct CorrFit { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - int multiplicity = tracks.size(); + double multiplicity = tracks.size(); if (cfgStrictTrackCounter) { trackCounter(tracks, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), SameEvent, multiplicity, eventWeight); } PROCESS_SWITCH(CorrFit, processSameFt0aFt0c, "Process same event for FT0A-FT0C correlation", true); @@ -1238,12 +1322,15 @@ struct CorrFit { const auto& ft0Col1 = collision1.foundFT0(); const auto& ft0Col2 = collision2.foundFT0(); - int multiplicity = tracks1.size(); + double multiplicity = tracks1.size(); if (cfgStrictTrackCounter) { trackCounter(tracks1, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin fillCorrelationsFT0AFT0C(ft0Col1, ft0Col2, collision1.posZ(), MixedEvent, multiplicity, eventWeight); @@ -1269,15 +1356,20 @@ struct CorrFit { return; registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + loadCorrection(bc.timestamp()); fillYield(collision, tracks); - int multiplicity = tracks.size(); + double multiplicity = tracks.size(); if (cfgStrictTrackCounter) { trackCounter(tracks, multiplicity); } + if (cfgQaCheck) { + registry.fill(HIST("Nch_corrected"), multiplicity); + } + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, multiplicity, getMagneticField(bc.timestamp())); } PROCESS_SWITCH(CorrFit, processSameTPC, "Process same event for TPC-TPC correlation", false); @@ -1312,8 +1404,9 @@ struct CorrFit { continue; registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + loadCorrection(collision1.bc_as().timestamp()); - int multiplicity = tracks1.size(); + double multiplicity = tracks1.size(); if (cfgStrictTrackCounter) { trackCounter(tracks1, multiplicity); From cdd13cbafa101e95ff304886cd4e44134e65067c Mon Sep 17 00:00:00 2001 From: Xufei Xue <150438610+dongfangqingxin@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:52:40 +0800 Subject: [PATCH 395/449] [PWGHF] feat(taskLcToK0sP): add THnSparse with ML scores, align with taskLc patterns (#16492) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/Tasks/taskLcToK0sP.cxx | 938 +++++++++++++++++-------------- 1 file changed, 502 insertions(+), 436 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx index 78fd2c5174a..ec90f907724 100644 --- a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx +++ b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx @@ -14,9 +14,11 @@ /// /// \author Chiara Zampolli, , CERN /// Paul Buehler, , Vienna +/// Xufei Xue, , CUG /// /// \note based on taskD0.cxx, taskLc.cxx +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/AliasTables.h" @@ -35,31 +37,85 @@ #include #include +#include + #include +#include +#include #include using namespace o2; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_centrality; /// LcToK0sp analysis task struct HfTaskLcToK0sP { + Configurable fillTHn{"fillTHn", true, "fill THnSparse"}; Configurable selectionFlagLcToK0sP{"selectionFlagLcToK0sP", 1, "Selection Flag for Lc"}; - Configurable selectionFlagLcbarToK0sP{"selectionFlagLcbarToK0sP", 1, "Selection Flag for Lcbar"}; Configurable etaCandMax{"etaCandMax", -1., "max. cand. pseudorapidity"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_k0s_p::vecBinsPt}, "pT bin limits"}; + SliceCache cache; + + using FilteredCandLcToPK0SWSelFlag = soa::Filtered>; + using FilteredCandLcToPK0SWSelFlagAndMl = soa::Filtered>; + using FilteredCandLcToPK0SWSelFlagAndMc = soa::Filtered>; + using FilteredCandLcToPK0SWSelFlagAndMcAndMl = soa::Filtered>; + using TracksWPid = soa::Join; - Filter filterSelectCandidates = (aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcToK0sP || aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcbarToK0sP); + using Collisions = soa::Join; + using CollisionsMc = soa::Join; + using CollisionsWithFT0C = soa::Join; + using CollisionsMcWithFT0C = soa::Join; + using CollisionsWithFT0M = soa::Join; + using CollisionsMcWithFT0M = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcToK0sP; + + Preslice lcToPK0SPerCollision = aod::hf_cand::collisionId; + PresliceUnsorted colPerMcCollision = aod::mcparticle::mcCollisionId; + + // THnSparse configurable axes + ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {300, 2.0, 2.6}, ""}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {360, 0., 36.}, ""}; + ConfigurableAxis thnConfigAxisBdtScoreBkg{"thnConfigAxisBdtScoreBkg", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisBdtScorePrompt{"thnConfigAxisBdtScorePrompt", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisBdtScoreNonPrompt{"thnConfigAxisBdtScoreNonPrompt", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisPtB{"thnConfigAxisPtB", {3000, 0., 300.}, ""}; + ConfigurableAxis thnConfigAxisOrigin{"thnConfigAxisOrigin", {2, -0.5, 1.5}, ""}; + ConfigurableAxis thnConfigAxisCentrality{"thnConfigAxisCentrality", {100, 0., 100.}, ""}; + ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"}; + ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {20, -1., 1.}, "candidate rapidity"}; HistogramRegistry registry{"registry"}; - void init(InitContext& context) + // ML class indices + enum MlClasses : int { + MlClassBackground = 0, + MlClassPrompt, + MlClassNonPrompt, + NumberOfMlClasses + }; + + static constexpr int KDecayChannelLcToK0sP = 1; + + void init(InitContext&) { + // Check that only one process function is enabled + std::array processFlags{ + doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, + doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, + doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, + doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M}; + if ((std::accumulate(processFlags.begin(), processFlags.end(), 0)) != 1) { + LOGP(fatal, "no or more than one process function enabled! Please check your configuration!"); + } + // axes AxisSpec const axisBinsPt = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec const axisPt = {300, 0.0f, 30.0f, "#it{p}_{T} (GeV/#it{c})"}; @@ -80,176 +136,94 @@ struct HfTaskLcToK0sP { AxisSpec const axisProperLifetimeV0 = {1000, 0.f, 80.f, "#it{c#tau} (cm)"}; AxisSpec const axisNSigma = {100, -6.f, 6.f, "n#it{#sigma}_{p}"}; AxisSpec const axisPidP = {100, 0.f, 10.0f, "#it{p} (GeV/#it{c})"}; - // data - registry.add("hPtCand", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("hEtaCand", "cascade candidates;candidate #it{#eta};entries", {HistType::kTH1F, {axisEta}}); - registry.add("hEtaCandVsPtCand", "cascade candidates;candidate #it{#eta};p_{T}", {HistType::kTH2F, {axisEta, axisBinsPt}}); - registry.add("hPhiCand", "cascade candidates;candidate #it{#phi};entries", {HistType::kTH1F, {axisPhi}}); - registry.add("hPhiCandVsPtCand", "cascade candidates;candidate #it{#phi};p_{T}", {HistType::kTH2F, {axisPhi, axisBinsPt}}); - registry.add("hMass", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassCand}}); - registry.add("hMassVsPtCand", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassCand, axisBinsPt}}); - registry.add("hPtBach", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("hPtBachVsPtCand", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("hPtV0", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("hPtV0VsPtCand", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("hd0Bach", "cascade candidates;bachelor DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("hd0BachVsPtCand", "cascade candidates;bachelor DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("hd0V0", "cascade candidates;V0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("hd0V0VsPtCand", "cascade candidates;V0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("hd0V0pos", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("hd0V0posVsPtCand", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("hd0V0neg", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("hd0V0negVsPtCand", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("hPtV0pos", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("hPtV0posVsPtCand", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("hPtV0neg", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("hPtV0negVsPtCand", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("hV0CPA", "cascade candidates;v0 cosine of pointing angle;entries", {HistType::kTH1F, {axisV0CPA}}); - registry.add("hV0CPAVsPtCand", "cascade candidates;v0 cosine of pointing angle;p_{T}", {HistType::kTH2F, {axisV0CPA, axisBinsPt}}); - registry.add("hV0Radius", "cascade candidates;v0 radius (cm);entries", {HistType::kTH1F, {axisV0Radius}}); - registry.add("hV0RadiusVsPtCand", "cascade candidates;v0 radius (cm);p_{T}", {HistType::kTH2F, {axisV0Radius, axisBinsPt}}); - registry.add("hV0DCADaughters", "cascade candidates;v0 dca daughters (cm);entries", {HistType::kTH1F, {axisV0DCADaughters}}); - registry.add("hV0DCADaughtersVsPtCand", "cascade candidates;v0 dca daughters (cm);p_{T}", {HistType::kTH2F, {axisV0DCADaughters, axisBinsPt}}); - registry.add("hV0MK0Short", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassK0Short}}); - registry.add("hV0MK0ShortVsPtCand", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassK0Short, axisBinsPt}}); - registry.add("hV0MLambda", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("hV0MLambdaVsPtCand", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("hV0MAntiLambda", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("hV0MAntiLambdaVsPtCand", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("hV0MGamma", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassGamma}}); - registry.add("hV0MGammaVsPtCand", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassGamma, axisBinsPt}}); - registry.add("hCtV0K0Short", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("hCtV0K0ShortVsPtCand", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("hCtV0Lambda", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("hCtV0LambdaVsPtCand", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("hCPACand", "cascade candidates;cosine pointing angle;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("hCPACandVsPtCand", "cascade candidates;cosine pointing angle;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("hCPAxyCand", "cascade candidates;cosine pointing angle xy;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("hCPAxyCandVsPtCand", "cascade candidates;cosine pointing angle xy;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("hDecLengthCand", "cascade candidates;decay length (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("hDecLengthCandVsPtCand", "cascade candidates;decay length (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("hDecLengthXYCand", "cascade candidates;decay length xy (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("hDecLengthXYCandVsPtCand", "cascade candidates;decay length xy (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("hCtCand", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetime}}); - registry.add("hCtCandVsPtCand", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetime, axisBinsPt}}); - registry.add("hTPCNSigmaPrBach", "cascade candidates;n#it{#sigma}_{p} TPC;entries", {HistType::kTH1F, {axisNSigma}}); - registry.add("hPBachVsTPCNSigmaPrBach", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TPC", {HistType::kTH2F, {axisPidP, axisNSigma}}); - registry.add("hTOFNSigmaPrBach", "cascade candidates;n#it{#sigma}_{p} TOF;entries", {HistType::kTH1F, {axisNSigma}}); - registry.add("hPBachVsTOFNSigmaPrBach", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TOF", {HistType::kTH2F, {axisPidP, axisNSigma}}); + // data - helper lambda: adds 1D histogram and its VsPtCand 2D variant + auto addHistosData = [&](const std::string& name, const std::string& title, const AxisSpec& axis) { + registry.add(("Data/h" + name).c_str(), ("cascade candidates;" + title + ";entries").c_str(), {HistType::kTH1F, {axis}}); + registry.add(("Data/h" + name + "VsPtCand").c_str(), ("cascade candidates;" + title + ";p_{T}").c_str(), {HistType::kTH2F, {axis, axisBinsPt}}); + }; + + addHistosData("PtCand", "candidate #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosData("EtaCand", "candidate #it{#eta}", axisEta); + addHistosData("PhiCand", "candidate #it{#phi}", axisPhi); + addHistosData("Mass", "inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2})", axisMassCand); + addHistosData("PtBach", "bachelor #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosData("PtV0", "v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosData("d0Bach", "bachelor DCAxy to prim. vertex (cm)", axisd0); + addHistosData("d0V0", "V0 DCAxy to prim. vertex (cm)", axisd0); + addHistosData("d0V0pos", "pos daugh v0 DCAxy to prim. vertex (cm)", axisd0V0Daughters); + addHistosData("d0V0neg", "neg daugh v0 DCAxy to prim. vertex (cm)", axisd0V0Daughters); + addHistosData("PtV0pos", "pos daugh v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosData("PtV0neg", "neg daugh v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosData("V0CPA", "v0 cosine of pointing angle", axisV0CPA); + addHistosData("V0Radius", "V0 radius (cm)", axisV0Radius); + addHistosData("V0DCADaughters", "v0 dca daughters (cm)", axisV0DCADaughters); + addHistosData("V0MK0Short", "v0 mass K0s (GeV/#it{c}^{2})", axisMassK0Short); + addHistosData("V0MLambda", "v0 mass #Lambda (GeV/#it{c}^{2})", axisMassLambda); + addHistosData("V0MAntiLambda", "v0 mass Anti#Lambda (GeV/#it{c}^{2})", axisMassLambda); + addHistosData("V0MGamma", "v0 mass #gamma (GeV/#it{c}^{2})", axisMassGamma); + addHistosData("CtV0K0Short", "proper lifetime (V0) * #it{c} (cm)", axisProperLifetimeV0); + addHistosData("CtV0Lambda", "proper lifetime (V0) * #it{c} (cm)", axisProperLifetimeV0); + addHistosData("CPACand", "cosine pointing angle", axisCPACand); + addHistosData("CPAxyCand", "cosine pointing angle xy", axisCPACand); + addHistosData("DecLengthCand", "decay length (cm)", axisDecLength); + addHistosData("DecLengthXYCand", "decay length xy (cm)", axisDecLength); + addHistosData("CtCand", "proper lifetime (#Lambda_{c}) * #it{c} (cm)", axisProperLifetime); + + // PID histograms (non-standard axis pattern) + registry.add("Data/hTPCNSigmaPrBach", "cascade candidates;n#it{#sigma}_{p} TPC;entries", {HistType::kTH1F, {axisNSigma}}); + registry.add("Data/hPBachVsTPCNSigmaPrBach", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TPC", {HistType::kTH2F, {axisPidP, axisNSigma}}); + registry.add("Data/hTOFNSigmaPrBach", "cascade candidates;n#it{#sigma}_{p} TOF;entries", {HistType::kTH1F, {axisNSigma}}); + registry.add("Data/hPBachVsTOFNSigmaPrBach", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TOF", {HistType::kTH2F, {axisPidP, axisNSigma}}); // add MC histograms - if (context.mOptions.get("processMc")) { + bool const isMc = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M || + doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M; + if (isMc) { + // MC helper lambdas + auto addHistosMcRec = [&](const std::string& name, const std::string& title, const AxisSpec& axis) { + registry.add(("MC/Rec/h" + name + "RecSig").c_str(), ("cascade candidates;" + title + ";entries").c_str(), {HistType::kTH1F, {axis}}); + registry.add(("MC/Rec/h" + name + "VsPtCandRecSig").c_str(), ("cascade candidates;" + title + ";p_{T}").c_str(), {HistType::kTH2F, {axis, axisBinsPt}}); + registry.add(("MC/Rec/h" + name + "RecBg").c_str(), ("cascade candidates;" + title + ";entries").c_str(), {HistType::kTH1F, {axis}}); + registry.add(("MC/Rec/h" + name + "VsPtCandRecBg").c_str(), ("cascade candidates;" + title + ";p_{T}").c_str(), {HistType::kTH2F, {axis, axisBinsPt}}); + }; + auto addHistosMcGen = [&](const std::string& name, const std::string& title, const AxisSpec& axis) { + registry.add(("MC/Gen/h" + name + "Gen").c_str(), ("cascade candidates;" + title + ";entries").c_str(), {HistType::kTH1F, {axis}}); + registry.add(("MC/Gen/h" + name + "VsPtCandGen").c_str(), ("cascade candidates;" + title + ";p_{T}").c_str(), {HistType::kTH2F, {axis, axisBinsPt}}); + }; + + // MC Rec: PtCand has extra Prompt/NonPrompt variants registry.add("MC/Rec/hPtCandRecSig", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("MC/Rec/hPtCandRecSigPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("MC/Rec/hPtCandRecSigNonPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("MC/Rec/hPtCandRecBg", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hEtaCandRecSig", "cascade candidates;candidate #it{#eta};entries", {HistType::kTH1F, {axisEta}}); - registry.add("MC/Rec/hEtaCandVsPtCandRecSig", "cascade candidates;candidate #it{#eta};p_{T}", {HistType::kTH2F, {axisEta, axisBinsPt}}); - registry.add("MC/Rec/hEtaCandRecBg", "cascade candidates;candidate #it{#eta};entries", {HistType::kTH1F, {axisEta}}); - registry.add("MC/Rec/hEtaCandVsPtCandRecBg", "cascade candidates;candidate #it{#eta};p_{T}", {HistType::kTH2F, {axisEta, axisBinsPt}}); - registry.add("MC/Rec/hPhiCandRecSig", "cascade candidates;candidate #it{#phi};entries", {HistType::kTH1F, {axisPhi}}); - registry.add("MC/Rec/hPhiCandVsPtCandRecSig", "cascade candidates;candidate #it{#phi};p_{T}", {HistType::kTH2F, {axisPhi, axisBinsPt}}); - registry.add("MC/Rec/hPhiCandRecBg", "cascade candidates;candidate #it{#phi};entries", {HistType::kTH1F, {axisPhi}}); - registry.add("MC/Rec/hPhiCandVsPtCandRecBg", "cascade candidates;candidate #it{#phi};p_{T}", {HistType::kTH2F, {axisPhi, axisBinsPt}}); - registry.add("MC/Gen/hPtCandGen", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Gen/hPtCandGenPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Gen/hPtCandGenNonPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Gen/hEtaCandGen", "cascade candidates;candidate #it{#eta};entries", {HistType::kTH1F, {axisEta}}); - registry.add("MC/Gen/hEtaCandVsPtCandGen", "cascade candidates;candidate #it{#eta};p_{T}", {HistType::kTH2F, {axisEta, axisBinsPt}}); - registry.add("MC/Gen/hPhiCandGen", "cascade candidates;candidate #it{#phi};entries", {HistType::kTH1F, {axisPhi}}); - registry.add("MC/Gen/hPhiCandVsPtCandGen", "cascade candidates;candidate #it{#phi};p_{T}", {HistType::kTH2F, {axisPhi, axisBinsPt}}); - registry.add("MC/Rec/hMassRecSig", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH1F, {axisMassCand}}); - registry.add("MC/Rec/hMassVsPtCandRecSig", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassCand, axisBinsPt}}); - registry.add("MC/Rec/hMassRecBg", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH1F, {axisMassCand}}); - registry.add("MC/Rec/hMassVsPtCandRecBg", "cascade candidates;inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassCand, axisBinsPt}}); - registry.add("MC/Rec/hPtBachRecSig", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtBachVsPtCandRecSig", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtBachRecBg", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtBachVsPtCandRecBg", "cascade candidates;bachelor #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtV0RecSig", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0VsPtCandRecSig", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtV0RecBg", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0VsPtCandRecBg", "cascade candidates;v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hd0BachRecSig", "cascade candidates;bachelor DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("MC/Rec/hd0BachVsPtCandRecSig", "cascade candidates;bachelor DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("MC/Rec/hd0BachRecBg", "cascade candidates;bachelor DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("MC/Rec/hd0BachVsPtCandRecBg", "cascade candidates;bachelor DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("MC/Rec/hd0V0RecSig", "cascade candidates;V0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("MC/Rec/hd0V0VsPtCandRecSig", "cascade candidates;V0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("MC/Rec/hd0V0RecBg", "cascade candidates;V0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0}}); - registry.add("MC/Rec/hd0V0VsPtCandRecBg", "cascade candidates;V0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0, axisBinsPt}}); - registry.add("MC/Rec/hd0V0posRecSig", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("MC/Rec/hd0V0posVsPtCandRecSig", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("MC/Rec/hd0V0posRecBg", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("MC/Rec/hd0V0posVsPtCandRecBg", "cascade candidates;pos daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("MC/Rec/hd0V0negRecSig", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("MC/Rec/hd0V0negVsPtCandRecSig", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("MC/Rec/hd0V0negRecBg", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {axisd0V0Daughters}}); - registry.add("MC/Rec/hd0V0negVsPtCandRecBg", "cascade candidates;neg daugh v0 DCAxy to prim. vertex (cm);p_{T}", {HistType::kTH2F, {axisd0V0Daughters, axisBinsPt}}); - registry.add("MC/Rec/hPtV0posRecSig", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0posVsPtCandRecSig", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtV0posRecBg", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0posVsPtCandRecBg", "cascade candidates;pos daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtV0negRecSig", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0negVsPtCandRecSig", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hPtV0negRecBg", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("MC/Rec/hPtV0negVsPtCandRecBg", "cascade candidates;neg daugh v0 #it{p}_{T} (GeV/#it{c});p_{T}", {HistType::kTH2F, {axisPt, axisBinsPt}}); - registry.add("MC/Rec/hV0CPARecSig", "cascade candidates;v0 cosine of pointing angle;entries", {HistType::kTH1F, {axisV0CPA}}); - registry.add("MC/Rec/hV0CPAVsPtCandRecSig", "cascade candidates;v0 cosine of pointing angle;p_{T}", {HistType::kTH2F, {axisV0CPA, axisBinsPt}}); - registry.add("MC/Rec/hV0CPARecBg", "cascade candidates;v0 cosine of pointing angle;entries", {HistType::kTH1F, {axisV0CPA}}); - registry.add("MC/Rec/hV0CPAVsPtCandRecBg", "cascade candidates;v0 cosine of pointing angle;p_{T}", {HistType::kTH2F, {axisV0CPA, axisBinsPt}}); - registry.add("MC/Rec/hV0RadiusRecSig", "cascade candidates;v0 radius (cm);entries", {HistType::kTH1F, {axisV0Radius}}); - registry.add("MC/Rec/hV0RadiusVsPtCandRecSig", "cascade candidates;v0 radius (cm);p_{T}", {HistType::kTH2F, {axisV0Radius, axisBinsPt}}); - registry.add("MC/Rec/hV0RadiusRecBg", "cascade candidates;v0 radius (cm);entries", {HistType::kTH1F, {axisV0Radius}}); - registry.add("MC/Rec/hV0RadiusVsPtCandRecBg", "cascade candidates;v0 radius (cm);p_{T}", {HistType::kTH2F, {axisV0Radius, axisBinsPt}}); - registry.add("MC/Rec/hV0DCADaughtersRecSig", "cascade candidates;v0 dca daughters (cm);entries", {HistType::kTH1F, {axisV0DCADaughters}}); - registry.add("MC/Rec/hV0DCADaughtersVsPtCandRecSig", "cascade candidates;v0 dca daughters (cm);p_{T}", {HistType::kTH2F, {axisV0DCADaughters, axisBinsPt}}); - registry.add("MC/Rec/hV0DCADaughtersRecBg", "cascade candidates;v0 dca daughters (cm);entries", {HistType::kTH1F, {axisV0DCADaughters}}); - registry.add("MC/Rec/hV0DCADaughtersVsPtCandRecBg", "cascade candidates;v0 dca daughters (cm);p_{T}", {HistType::kTH2F, {axisV0DCADaughters, axisBinsPt}}); - registry.add("MC/Rec/hV0MK0ShortRecSig", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassK0Short}}); - registry.add("MC/Rec/hV0MK0ShortVsPtCandRecSig", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassK0Short, axisBinsPt}}); - registry.add("MC/Rec/hV0MK0ShortRecBg", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassK0Short}}); - registry.add("MC/Rec/hV0MK0ShortVsPtCandRecBg", "cascade candidates;v0 mass K0s (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassK0Short, axisBinsPt}}); - registry.add("MC/Rec/hV0MLambdaRecSig", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("MC/Rec/hV0MLambdaVsPtCandRecSig", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("MC/Rec/hV0MLambdaRecBg", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("MC/Rec/hV0MLambdaVsPtCandRecBg", "cascade candidates;v0 mass Lambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("MC/Rec/hV0MAntiLambdaRecSig", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("MC/Rec/hV0MAntiLambdaVsPtCandRecSig", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("MC/Rec/hV0MAntiLambdaRecBg", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassLambda}}); - registry.add("MC/Rec/hV0MAntiLambdaVsPtCandRecBg", "cascade candidates;v0 mass AntiLambda (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassLambda, axisBinsPt}}); - registry.add("MC/Rec/hV0MGammaRecSig", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassGamma}}); - registry.add("MC/Rec/hV0MGammaVsPtCandRecSig", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassGamma, axisBinsPt}}); - registry.add("MC/Rec/hV0MGammaRecBg", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMassGamma}}); - registry.add("MC/Rec/hV0MGammaVsPtCandRecBg", "cascade candidates;v0 mass Gamma (GeV/#it{c}^{2});p_{T}", {HistType::kTH2F, {axisMassGamma, axisBinsPt}}); - registry.add("MC/Rec/hCtV0K0ShortRecSig", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("MC/Rec/hCtV0K0ShortVsPtCandRecSig", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("MC/Rec/hCtV0K0ShortRecBg", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("MC/Rec/hCtV0K0ShortVsPtCandRecBg", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("MC/Rec/hCtV0LambdaRecSig", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("MC/Rec/hCtV0LambdaVsPtCandRecSig", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("MC/Rec/hCtV0LambdaRecBg", "cascade candidates;proper lifetime (V0) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetimeV0}}); - registry.add("MC/Rec/hCtV0LambdaVsPtCandRecBg", "cascade candidates;proper lifetime (V0) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetimeV0, axisBinsPt}}); - registry.add("MC/Rec/hCPACandRecSig", "cascade candidates;cosine pointing angle;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("MC/Rec/hCPACandVsPtCandRecSig", "cascade candidates;cosine pointing angle;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("MC/Rec/hCPACandRecBg", "cascade candidates;cosine pointing angle;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("MC/Rec/hCPACandVsPtCandRecBg", "cascade candidates;cosine pointing angle;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("MC/Rec/hCPAxyCandRecSig", "cascade candidates;cosine pointing angle xy;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("MC/Rec/hCPAxyCandVsPtCandRecSig", "cascade candidates;cosine pointing angle xy;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("MC/Rec/hCPAxyCandRecBg", "cascade candidates;cosine pointing angle xy;entries", {HistType::kTH1F, {axisCPACand}}); - registry.add("MC/Rec/hCPAxyCandVsPtCandRecBg", "cascade candidates;cosine pointing angle xy;p_{T}", {HistType::kTH2F, {axisCPACand, axisBinsPt}}); - registry.add("MC/Rec/hDecLengthCandRecSig", "cascade candidates;decay length (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("MC/Rec/hDecLengthCandVsPtCandRecSig", "cascade candidates;decay length (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("MC/Rec/hDecLengthCandRecBg", "cascade candidates;decay length (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("MC/Rec/hDecLengthCandVsPtCandRecBg", "cascade candidates;decay length (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("MC/Rec/hDecLengthXYCandRecSig", "cascade candidates;decay length xy (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("MC/Rec/hDecLengthXYCandVsPtCandRecSig", "cascade candidates;decay length xy (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("MC/Rec/hDecLengthXYCandRecBg", "cascade candidates;decay length xy (cm);entries", {HistType::kTH1F, {axisDecLength}}); - registry.add("MC/Rec/hDecLengthXYCandVsPtCandRecBg", "cascade candidates;decay length xy (cm);p_{T}", {HistType::kTH2F, {axisDecLength, axisBinsPt}}); - registry.add("MC/Rec/hCtCandRecSig", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetime}}); - registry.add("MC/Rec/hCtCandVsPtCandRecSig", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetime, axisBinsPt}}); - registry.add("MC/Rec/hCtCandRecBg", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {axisProperLifetime}}); - registry.add("MC/Rec/hCtCandVsPtCandRecBg", "cascade candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);p_{T}", {HistType::kTH2F, {axisProperLifetime, axisBinsPt}}); + + addHistosMcRec("EtaCand", "candidate #it{#eta}", axisEta); + addHistosMcRec("PhiCand", "candidate #it{#phi}", axisPhi); + addHistosMcRec("Mass", "inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2})", axisMassCand); + addHistosMcRec("PtBach", "bachelor #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosMcRec("PtV0", "v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosMcRec("d0Bach", "bachelor DCAxy to prim. vertex (cm)", axisd0); + addHistosMcRec("d0V0", "V0 DCAxy to prim. vertex (cm)", axisd0); + addHistosMcRec("d0V0pos", "pos daugh v0 DCAxy to prim. vertex (cm)", axisd0V0Daughters); + addHistosMcRec("d0V0neg", "neg daugh v0 DCAxy to prim. vertex (cm)", axisd0V0Daughters); + addHistosMcRec("PtV0pos", "pos daugh v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosMcRec("PtV0neg", "neg daugh v0 #it{p}_{T} (GeV/#it{c})", axisPt); + addHistosMcRec("V0CPA", "v0 cosine of pointing angle", axisV0CPA); + addHistosMcRec("V0Radius", "V0 radius (cm)", axisV0Radius); + addHistosMcRec("V0DCADaughters", "v0 dca daughters (cm)", axisV0DCADaughters); + addHistosMcRec("V0MK0Short", "v0 mass K0s (GeV/#it{c}^{2})", axisMassK0Short); + addHistosMcRec("V0MLambda", "v0 mass #Lambda (GeV/#it{c}^{2})", axisMassLambda); + addHistosMcRec("V0MAntiLambda", "v0 mass Anti#Lambda (GeV/#it{c}^{2})", axisMassLambda); + addHistosMcRec("V0MGamma", "v0 mass #gamma (GeV/#it{c}^{2})", axisMassGamma); + addHistosMcRec("CtV0K0Short", "proper lifetime (V0) * #it{c} (cm)", axisProperLifetimeV0); + addHistosMcRec("CtV0Lambda", "proper lifetime (V0) * #it{c} (cm)", axisProperLifetimeV0); + addHistosMcRec("CPACand", "cosine pointing angle", axisCPACand); + addHistosMcRec("CPAxyCand", "cosine pointing angle xy", axisCPACand); + addHistosMcRec("DecLengthCand", "decay length (cm)", axisDecLength); + addHistosMcRec("DecLengthXYCand", "decay length xy (cm)", axisDecLength); + addHistosMcRec("CtCand", "proper lifetime (#Lambda_{c}) * #it{c} (cm)", axisProperLifetime); + + // MC Rec PID registry.add("MC/Rec/hTPCNSigmaPrBachRecSig", "cascade candidates;n#it{#sigma}_{p} TPC;entries", {HistType::kTH1F, {axisNSigma}}); registry.add("MC/Rec/hPBachVsTPCNSigmaPrBachRecSig", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TPC", {HistType::kTH2F, {axisPidP, axisNSigma}}); registry.add("MC/Rec/hTPCNSigmaPrBachRecBg", "cascade candidates;n#it{#sigma}_{p} TPC;entries", {HistType::kTH1F, {axisNSigma}}); @@ -258,319 +232,411 @@ struct HfTaskLcToK0sP { registry.add("MC/Rec/hPBachVsTOFNSigmaPrBachRecSig", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TOF", {HistType::kTH2F, {axisPidP, axisNSigma}}); registry.add("MC/Rec/hTOFNSigmaPrBachRecBg", "cascade candidates;n#it{#sigma}_{p} TOF;entries", {HistType::kTH1F, {axisNSigma}}); registry.add("MC/Rec/hPBachVsTOFNSigmaPrBachRecBg", "cascade candidates;#it{p} bachelor (GeV/#it{c}) ;n#it{#sigma}_{p} TOF", {HistType::kTH2F, {axisPidP, axisNSigma}}); + + // MC Gen + registry.add("MC/Gen/hPtCandGen", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("MC/Gen/hPtCandGenPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + registry.add("MC/Gen/hPtCandGenNonPrompt", "cascade candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); + + addHistosMcGen("EtaCand", "candidate #it{#eta}", axisEta); + addHistosMcGen("PhiCand", "candidate #it{#phi}", axisPhi); + } + + // THnSparse for ML analysis + if (fillTHn) { + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K_{S}^{0}) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisBdtScoreBkg{thnConfigAxisBdtScoreBkg, "BDT bkg score"}; + const AxisSpec thnAxisBdtScorePrompt{thnConfigAxisBdtScorePrompt, "BDT prompt score"}; + const AxisSpec thnAxisBdtScoreNonPrompt{thnConfigAxisBdtScoreNonPrompt, "BDT non-prompt score"}; + const AxisSpec thnAxisCentrality{thnConfigAxisCentrality, "centrality (FT0C)"}; + const AxisSpec thnAxisNumPvContr{thnConfigAxisNumPvContr, "Number of PV contributors"}; + const AxisSpec thnAxisPtB{thnConfigAxisPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; + const AxisSpec thnAxisOrigin{thnConfigAxisOrigin, "origin"}; + const AxisSpec thnAxisY{thnConfigAxisY, "rapidity"}; + + // Data with ML: {mass, pt, centrality, bkg, prompt, non-prompt, numPvContr} + if (doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M) { + registry.add("hnLcK0sPDataWithBdt", "THn for Lc->K0sP data with BDT", HistType::kTHnSparseF, + {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreBkg, thnAxisBdtScorePrompt, thnAxisBdtScoreNonPrompt, thnAxisNumPvContr}); + } + + // MC Rec with ML: {mass, pt, centrality, bkg, prompt, non-prompt, numPvContr, origin} + if (doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M) { + registry.add("hnLcK0sPRecMcWithBdt", "THn for Lc->K0sP MC rec with BDT", HistType::kTHnSparseF, + {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreBkg, thnAxisBdtScorePrompt, thnAxisBdtScoreNonPrompt, thnAxisNumPvContr, thnAxisOrigin}); + } + + // MC Gen: {pt, centrality, rapidity, numPvContr, ptB, origin} + if (doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M) { + registry.add("hnLcK0sPGenMc", "THn for Lc->K0sP MC gen", HistType::kTHnSparseF, + {thnAxisPt, thnAxisCentrality, thnAxisY, thnAxisNumPvContr, thnAxisPtB, thnAxisOrigin}); + } + } + } + + /// Evaluate centrality/multiplicity percentile + /// \param collision is collision + /// \return centrality/multiplicity percentile of the collision + template + float evaluateCentralityColl(const Coll& collision) + { + return o2::hf_centrality::getCentralityColl(collision); + } + + /// Helper function to fill candidate histograms + /// \param candidate is the candidate + template + void fillCandHistograms(CandType const& candidate) + { + auto ptCand = candidate.pt(); + auto eta = candidate.eta(); + auto phi = candidate.phi(); + auto invMassLcToK0sP = HfHelper::invMassLcToK0sP(candidate); + auto ptProng0 = candidate.ptProng0(); + auto ptProng1 = candidate.ptProng1(); + auto impactParameter0 = candidate.impactParameter0(); + auto impactParameter1 = candidate.impactParameter1(); + auto dcaPosToPV = candidate.dcapostopv(); + auto dcaNegToPV = candidate.dcanegtopv(); + auto ptV0Pos = candidate.ptV0Pos(); + auto ptV0Neg = candidate.ptV0Neg(); + auto v0CosPA = candidate.v0cosPA(); + auto v0Radius = candidate.v0radius(); + auto dcaV0Daughters = candidate.dcaV0daughters(); + auto mK0Short = candidate.mK0Short(); + auto mLambda = candidate.mLambda(); + auto mAntiLambda = candidate.mAntiLambda(); + auto mGamma = candidate.mGamma(); + auto ctV0K0Short = HfHelper::ctV0K0s(candidate); + auto ctV0Lambda = HfHelper::ctV0Lambda(candidate); + auto cpa = candidate.cpa(); + auto cpaXY = candidate.cpaXY(); + auto decayLength = candidate.decayLength(); + auto decayLengthXY = candidate.decayLengthXY(); + auto ctLc = HfHelper::ctLc(candidate); + + registry.fill(HIST("Data/hPtCand"), ptCand); + registry.fill(HIST("Data/hEtaCand"), eta); + registry.fill(HIST("Data/hEtaCandVsPtCand"), eta, ptCand); + registry.fill(HIST("Data/hPhiCand"), phi); + registry.fill(HIST("Data/hPhiCandVsPtCand"), phi, ptCand); + registry.fill(HIST("Data/hMass"), invMassLcToK0sP); + registry.fill(HIST("Data/hMassVsPtCand"), invMassLcToK0sP, ptCand); + registry.fill(HIST("Data/hPtBach"), ptProng0); + registry.fill(HIST("Data/hPtBachVsPtCand"), ptProng0, ptCand); + registry.fill(HIST("Data/hPtV0"), ptProng1); + registry.fill(HIST("Data/hPtV0VsPtCand"), ptProng1, ptCand); + registry.fill(HIST("Data/hd0Bach"), impactParameter0); + registry.fill(HIST("Data/hd0BachVsPtCand"), impactParameter0, ptCand); + registry.fill(HIST("Data/hd0V0"), impactParameter1); + registry.fill(HIST("Data/hd0V0VsPtCand"), impactParameter1, ptCand); + registry.fill(HIST("Data/hd0V0pos"), dcaPosToPV); + registry.fill(HIST("Data/hd0V0posVsPtCand"), dcaPosToPV, ptCand); + registry.fill(HIST("Data/hd0V0neg"), dcaNegToPV); + registry.fill(HIST("Data/hd0V0negVsPtCand"), dcaNegToPV, ptCand); + registry.fill(HIST("Data/hPtV0pos"), ptV0Pos); + registry.fill(HIST("Data/hPtV0posVsPtCand"), ptV0Pos, ptCand); + registry.fill(HIST("Data/hPtV0neg"), ptV0Neg); + registry.fill(HIST("Data/hPtV0negVsPtCand"), ptV0Neg, ptCand); + registry.fill(HIST("Data/hV0CPA"), v0CosPA); + registry.fill(HIST("Data/hV0CPAVsPtCand"), v0CosPA, ptCand); + registry.fill(HIST("Data/hV0Radius"), v0Radius); + registry.fill(HIST("Data/hV0RadiusVsPtCand"), v0Radius, ptCand); + registry.fill(HIST("Data/hV0DCADaughters"), dcaV0Daughters); + registry.fill(HIST("Data/hV0DCADaughtersVsPtCand"), dcaV0Daughters, ptCand); + registry.fill(HIST("Data/hV0MK0Short"), mK0Short); + registry.fill(HIST("Data/hV0MK0ShortVsPtCand"), mK0Short, ptCand); + registry.fill(HIST("Data/hV0MLambda"), mLambda); + registry.fill(HIST("Data/hV0MLambdaVsPtCand"), mLambda, ptCand); + registry.fill(HIST("Data/hV0MAntiLambda"), mAntiLambda); + registry.fill(HIST("Data/hV0MAntiLambdaVsPtCand"), mAntiLambda, ptCand); + registry.fill(HIST("Data/hV0MGamma"), mGamma); + registry.fill(HIST("Data/hV0MGammaVsPtCand"), mGamma, ptCand); + registry.fill(HIST("Data/hCtV0K0Short"), ctV0K0Short); + registry.fill(HIST("Data/hCtV0K0ShortVsPtCand"), ctV0K0Short, ptCand); + registry.fill(HIST("Data/hCtV0Lambda"), ctV0Lambda); + registry.fill(HIST("Data/hCtV0LambdaVsPtCand"), ctV0Lambda, ptCand); + registry.fill(HIST("Data/hCPACand"), cpa); + registry.fill(HIST("Data/hCPACandVsPtCand"), cpa, ptCand); + registry.fill(HIST("Data/hCPAxyCand"), cpaXY); + registry.fill(HIST("Data/hCPAxyCandVsPtCand"), cpaXY, ptCand); + registry.fill(HIST("Data/hDecLengthCand"), decayLength); + registry.fill(HIST("Data/hDecLengthCandVsPtCand"), decayLength, ptCand); + registry.fill(HIST("Data/hDecLengthXYCand"), decayLengthXY); + registry.fill(HIST("Data/hDecLengthXYCandVsPtCand"), decayLengthXY, ptCand); + registry.fill(HIST("Data/hCtCand"), ctLc); + registry.fill(HIST("Data/hCtCandVsPtCand"), ctLc, ptCand); + } + + /// Data processing template + /// \tparam FillMl switch to fill ML histograms + template + void runAnalysisPerCollisionData(CollType const& collisions, CandType const& candidates) + { + for (const auto& collision : collisions) { + fillHistosData(collision, candidates); } } - void process(soa::Filtered> const& candidates, - TracksWPid const&) + /// Helper function to fill data histograms + /// \tparam FillMl switch to fill ML histograms + template + void fillHistosData(CollType const& collision, CandType const& candidates) { - for (const auto& candidate : candidates) { + const auto thisCollId = collision.globalIndex(); + const auto& groupedCandidates = candidates.sliceBy(lcToPK0SPerCollision, thisCollId); + + for (const auto& candidate : groupedCandidates) { if (etaCandMax >= 0. && std::abs(candidate.eta()) > etaCandMax) { continue; } if (yCandRecoMax >= 0. && std::abs(HfHelper::yLc(candidate)) > yCandRecoMax) { continue; } + if (candidate.isSelLcToK0sP() < selectionFlagLcToK0sP) { + continue; + } + + fillCandHistograms(candidate); - auto ptCand = candidate.pt(); - auto eta = candidate.eta(); - auto phi = candidate.phi(); - auto invMassLcToK0sP = HfHelper::invMassLcToK0sP(candidate); - auto ptProng0 = candidate.ptProng0(); - auto ptProng1 = candidate.ptProng1(); - auto impactParameter0 = candidate.impactParameter0(); - auto impactParameter1 = candidate.impactParameter1(); - auto dcaPosToPV = candidate.dcapostopv(); - auto dcaNegToPV = candidate.dcanegtopv(); - auto ptV0Pos = candidate.ptV0Pos(); - auto ptV0Neg = candidate.ptV0Neg(); - auto v0CosPA = candidate.v0cosPA(); - auto v0Radius = candidate.v0radius(); - auto dcaV0Daughters = candidate.dcaV0daughters(); - auto mK0Short = candidate.mK0Short(); - auto mLambda = candidate.mLambda(); - auto mAntiLambda = candidate.mAntiLambda(); - auto mGamma = candidate.mGamma(); - auto ctV0K0Short = HfHelper::ctV0K0s(candidate); - auto ctV0Lambda = HfHelper::ctV0Lambda(candidate); - auto cpa = candidate.cpa(); - auto cpaXY = candidate.cpaXY(); - auto decayLength = candidate.decayLength(); - auto decayLengthXY = candidate.decayLengthXY(); - auto ctLc = HfHelper::ctLc(candidate); - - registry.fill(HIST("hPtCand"), ptCand); - registry.fill(HIST("hEtaCand"), eta); - registry.fill(HIST("hEtaCandVsPtCand"), eta, ptCand); - registry.fill(HIST("hPhiCand"), phi); - registry.fill(HIST("hPhiCandVsPtCand"), phi, ptCand); - registry.fill(HIST("hMass"), invMassLcToK0sP); - registry.fill(HIST("hMassVsPtCand"), invMassLcToK0sP, ptCand); - registry.fill(HIST("hPtBach"), ptProng0); - registry.fill(HIST("hPtBachVsPtCand"), ptProng0, ptCand); - registry.fill(HIST("hPtV0"), ptProng1); - registry.fill(HIST("hPtV0VsPtCand"), ptProng1, ptCand); - registry.fill(HIST("hd0Bach"), impactParameter0); - registry.fill(HIST("hd0BachVsPtCand"), impactParameter0, ptCand); - registry.fill(HIST("hd0V0"), impactParameter1); - registry.fill(HIST("hd0V0VsPtCand"), impactParameter1, ptCand); - registry.fill(HIST("hd0V0pos"), dcaPosToPV); - registry.fill(HIST("hd0V0posVsPtCand"), dcaPosToPV, ptCand); - registry.fill(HIST("hd0V0neg"), dcaNegToPV); - registry.fill(HIST("hd0V0negVsPtCand"), dcaNegToPV, ptCand); - registry.fill(HIST("hPtV0pos"), ptV0Pos); - registry.fill(HIST("hPtV0posVsPtCand"), ptV0Pos, ptCand); - registry.fill(HIST("hPtV0neg"), ptV0Neg); - registry.fill(HIST("hPtV0negVsPtCand"), ptV0Neg, ptCand); - registry.fill(HIST("hV0CPA"), v0CosPA); - registry.fill(HIST("hV0CPAVsPtCand"), v0CosPA, ptCand); - registry.fill(HIST("hV0Radius"), v0Radius); - registry.fill(HIST("hV0RadiusVsPtCand"), v0Radius, ptCand); - registry.fill(HIST("hV0DCADaughters"), dcaV0Daughters); - registry.fill(HIST("hV0DCADaughtersVsPtCand"), dcaV0Daughters, ptCand); - registry.fill(HIST("hV0MK0Short"), mK0Short); - registry.fill(HIST("hV0MK0ShortVsPtCand"), mK0Short, ptCand); - registry.fill(HIST("hV0MLambda"), mLambda); - registry.fill(HIST("hV0MLambdaVsPtCand"), mLambda, ptCand); - registry.fill(HIST("hV0MAntiLambda"), mAntiLambda); - registry.fill(HIST("hV0MAntiLambdaVsPtCand"), mAntiLambda, ptCand); - registry.fill(HIST("hV0MGamma"), mGamma); - registry.fill(HIST("hV0MGammaVsPtCand"), mGamma, ptCand); - registry.fill(HIST("hCtV0K0Short"), ctV0K0Short); - registry.fill(HIST("hCtV0K0ShortVsPtCand"), ctV0K0Short, ptCand); - registry.fill(HIST("hCtV0Lambda"), ctV0Lambda); - registry.fill(HIST("hCtV0LambdaVsPtCand"), ctV0Lambda, ptCand); - registry.fill(HIST("hCPACand"), cpa); - registry.fill(HIST("hCPACandVsPtCand"), cpa, ptCand); - registry.fill(HIST("hCPAxyCand"), cpaXY); - registry.fill(HIST("hCPAxyCandVsPtCand"), cpaXY, ptCand); - registry.fill(HIST("hDecLengthCand"), decayLength); - registry.fill(HIST("hDecLengthCandVsPtCand"), decayLength, ptCand); - registry.fill(HIST("hDecLengthXYCand"), decayLengthXY); - registry.fill(HIST("hDecLengthXYCandVsPtCand"), decayLengthXY, ptCand); - registry.fill(HIST("hCtCand"), ctLc); - registry.fill(HIST("hCtCandVsPtCand"), ctLc, ptCand); - - const auto& bach = candidate.prong0_as(); // bachelor track + // PID histograms + const auto& bach = candidate.template prong0_as(); auto tpcNSigmaPr = bach.tpcNSigmaPr(); auto pBach = bach.p(); - registry.fill(HIST("hTPCNSigmaPrBach"), tpcNSigmaPr); - registry.fill(HIST("hPBachVsTPCNSigmaPrBach"), pBach, tpcNSigmaPr); + registry.fill(HIST("Data/hTPCNSigmaPrBach"), tpcNSigmaPr); + registry.fill(HIST("Data/hPBachVsTPCNSigmaPrBach"), pBach, tpcNSigmaPr); if (bach.hasTOF()) { - auto tofNSigmaPr = bach.tofNSigmaPr(); - registry.fill(HIST("hTOFNSigmaPrBach"), tofNSigmaPr); - registry.fill(HIST("hPBachVsTOFNSigmaPrBach"), pBach, tofNSigmaPr); + registry.fill(HIST("Data/hTOFNSigmaPrBach"), bach.tofNSigmaPr()); + registry.fill(HIST("Data/hPBachVsTOFNSigmaPrBach"), pBach, bach.tofNSigmaPr()); } + + if (fillTHn && FillMl) { + if constexpr (CandType::template contains()) { + if (candidate.mlProbLcToK0sP().size() == NumberOfMlClasses) { + float ml0 = candidate.mlProbLcToK0sP()[MlClassBackground]; + float ml1 = candidate.mlProbLcToK0sP()[MlClassPrompt]; + float ml2 = candidate.mlProbLcToK0sP()[MlClassNonPrompt]; + if (ml0 >= 0.f && ml1 >= 0.f && ml2 >= 0.f) { + float cent = evaluateCentralityColl(collision); + int numPvContr = collision.numContrib(); + registry.get(HIST("hnLcK0sPDataWithBdt"))->Fill(HfHelper::invMassLcToK0sP(candidate), candidate.pt(), cent, ml0, ml1, ml2, static_cast(numPvContr)); + } + } + } + } + } + } + + /// MC processing template + /// \tparam FillMl switch to fill ML histograms + template + void runAnalysisPerCollisionMc(CollType const& collisions, + CandType const& candidates, + CandMcGen const& mcParticles) + { + for (const auto& collision : collisions) { + fillHistosMcRec(collision, candidates, mcParticles); } + fillHistosMcGen(mcParticles, collisions); } - void processMc(soa::Filtered> const& candidates, - soa::Join const& mcParticles, - aod::TracksWMc const&, - TracksWPid const&) + /// Helper function to fill MC reconstructed histograms + /// \tparam FillMl switch to fill ML histograms + template + void fillHistosMcRec(CollType const& collision, CandType const& candidates, CandMcGen const&) { - // MC rec. - for (const auto& candidate : candidates) { + const auto thisCollId = collision.globalIndex(); + const auto& groupedCandidates = candidates.sliceBy(lcToPK0SPerCollision, thisCollId); + + for (const auto& candidate : groupedCandidates) { if (etaCandMax >= 0. && std::abs(candidate.eta()) > etaCandMax) { continue; } - if (yCandRecoMax >= 0. && std::abs(HfHelper::yLc(candidate)) > yCandRecoMax) { continue; } - auto ptCand = candidate.pt(); - auto eta = candidate.eta(); - auto phi = candidate.phi(); - auto invMassLcToK0sP = HfHelper::invMassLcToK0sP(candidate); - auto ptProng0 = candidate.ptProng0(); - auto ptProng1 = candidate.ptProng1(); - auto impactParameter0 = candidate.impactParameter0(); - auto impactParameter1 = candidate.impactParameter1(); - auto dcaPosToPV = candidate.dcapostopv(); - auto dcaNegToPV = candidate.dcanegtopv(); - auto ptV0Pos = candidate.ptV0Pos(); - auto ptV0Neg = candidate.ptV0Neg(); - auto v0CosPA = candidate.v0cosPA(); - auto v0Radius = candidate.v0radius(); - auto dcaV0Daughters = candidate.dcaV0daughters(); - auto mK0Short = candidate.mK0Short(); - auto mLambda = candidate.mLambda(); - auto mAntiLambda = candidate.mAntiLambda(); - auto mGamma = candidate.mGamma(); - auto ctV0K0Short = HfHelper::ctV0K0s(candidate); - auto ctV0Lambda = HfHelper::ctV0Lambda(candidate); - auto cpa = candidate.cpa(); - auto cpaXY = candidate.cpaXY(); - auto decayLength = candidate.decayLength(); - auto decayLengthXY = candidate.decayLengthXY(); - auto ctLc = HfHelper::ctLc(candidate); - - const auto& bach = candidate.prong0_as(); // bachelor track - auto tpcNSigmaPr = bach.tpcNSigmaPr(); - auto pBach = bach.p(); + if (std::abs(candidate.flagMcMatchRec()) == KDecayChannelLcToK0sP) { + fillCandHistograms(candidate); - if (std::abs(candidate.flagMcMatchRec()) == 1) { - if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("MC/Rec/hPtCandRecSigPrompt"), ptCand); - } else if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("MC/Rec/hPtCandRecSigNonPrompt"), ptCand); - } - registry.fill(HIST("MC/Rec/hPtCandRecSig"), ptCand); - registry.fill(HIST("MC/Rec/hEtaCandRecSig"), eta); - registry.fill(HIST("MC/Rec/hEtaCandVsPtCandRecSig"), eta, ptCand); - registry.fill(HIST("MC/Rec/hPhiCandRecSig"), phi); - registry.fill(HIST("MC/Rec/hPhiCandVsPtCandRecSig"), phi, ptCand); - registry.fill(HIST("MC/Rec/hMassRecSig"), invMassLcToK0sP); - registry.fill(HIST("MC/Rec/hMassVsPtCandRecSig"), invMassLcToK0sP, ptCand); - registry.fill(HIST("MC/Rec/hPtBachRecSig"), ptProng0); - registry.fill(HIST("MC/Rec/hPtBachVsPtCandRecSig"), ptProng0, ptCand); - registry.fill(HIST("MC/Rec/hPtV0RecSig"), ptProng1); - registry.fill(HIST("MC/Rec/hPtV0VsPtCandRecSig"), ptProng1, ptCand); - registry.fill(HIST("MC/Rec/hd0BachRecSig"), impactParameter0); - registry.fill(HIST("MC/Rec/hd0BachVsPtCandRecSig"), impactParameter0, ptCand); - registry.fill(HIST("MC/Rec/hd0V0RecSig"), impactParameter1); - registry.fill(HIST("MC/Rec/hd0V0VsPtCandRecSig"), impactParameter1, ptCand); - registry.fill(HIST("MC/Rec/hd0V0posRecSig"), dcaPosToPV); - registry.fill(HIST("MC/Rec/hd0V0posVsPtCandRecSig"), dcaPosToPV, ptCand); - registry.fill(HIST("MC/Rec/hd0V0negRecSig"), dcaNegToPV); - registry.fill(HIST("MC/Rec/hd0V0negVsPtCandRecSig"), dcaNegToPV, ptCand); - registry.fill(HIST("MC/Rec/hPtV0posRecSig"), ptV0Pos); - registry.fill(HIST("MC/Rec/hPtV0posVsPtCandRecSig"), ptV0Pos, ptCand); - registry.fill(HIST("MC/Rec/hPtV0negRecSig"), ptV0Neg); - registry.fill(HIST("MC/Rec/hPtV0negVsPtCandRecSig"), ptV0Neg, ptCand); - registry.fill(HIST("MC/Rec/hV0CPARecSig"), v0CosPA); - registry.fill(HIST("MC/Rec/hV0CPAVsPtCandRecSig"), v0CosPA, ptCand); - registry.fill(HIST("MC/Rec/hV0RadiusRecSig"), v0Radius); - registry.fill(HIST("MC/Rec/hV0RadiusVsPtCandRecSig"), v0Radius, ptCand); - registry.fill(HIST("MC/Rec/hV0DCADaughtersRecSig"), dcaV0Daughters); - registry.fill(HIST("MC/Rec/hV0DCADaughtersVsPtCandRecSig"), dcaV0Daughters, ptCand); - registry.fill(HIST("MC/Rec/hV0MK0ShortRecSig"), mK0Short); - registry.fill(HIST("MC/Rec/hV0MK0ShortVsPtCandRecSig"), mK0Short, ptCand); - registry.fill(HIST("MC/Rec/hV0MLambdaRecSig"), mLambda); - registry.fill(HIST("MC/Rec/hV0MLambdaVsPtCandRecSig"), mLambda, ptCand); - registry.fill(HIST("MC/Rec/hV0MAntiLambdaRecSig"), mAntiLambda); - registry.fill(HIST("MC/Rec/hV0MAntiLambdaVsPtCandRecSig"), mAntiLambda, ptCand); - registry.fill(HIST("MC/Rec/hV0MGammaRecSig"), mGamma); - registry.fill(HIST("MC/Rec/hV0MGammaVsPtCandRecSig"), mGamma, ptCand); - registry.fill(HIST("MC/Rec/hCtV0K0ShortRecSig"), ctV0K0Short); - registry.fill(HIST("MC/Rec/hCtV0K0ShortVsPtCandRecSig"), ctV0K0Short, ptCand); - registry.fill(HIST("MC/Rec/hCtV0LambdaRecSig"), ctV0Lambda); - registry.fill(HIST("MC/Rec/hCtV0LambdaVsPtCandRecSig"), ctV0Lambda, ptCand); - registry.fill(HIST("MC/Rec/hCPACandRecSig"), cpa); - registry.fill(HIST("MC/Rec/hCPACandVsPtCandRecSig"), cpa, ptCand); - registry.fill(HIST("MC/Rec/hCPAxyCandRecSig"), cpaXY); - registry.fill(HIST("MC/Rec/hCPAxyCandVsPtCandRecSig"), cpaXY, ptCand); - registry.fill(HIST("MC/Rec/hDecLengthCandRecSig"), decayLength); - registry.fill(HIST("MC/Rec/hDecLengthCandVsPtCandRecSig"), decayLength, ptCand); - registry.fill(HIST("MC/Rec/hDecLengthXYCandRecSig"), decayLengthXY); - registry.fill(HIST("MC/Rec/hDecLengthXYCandVsPtCandRecSig"), decayLengthXY, ptCand); - registry.fill(HIST("MC/Rec/hCtCandRecSig"), ctLc); - registry.fill(HIST("MC/Rec/hCtCandVsPtCandRecSig"), ctLc, ptCand); - registry.fill(HIST("MC/Rec/hTPCNSigmaPrBachRecSig"), tpcNSigmaPr); - registry.fill(HIST("MC/Rec/hPBachVsTPCNSigmaPrBachRecSig"), pBach, tpcNSigmaPr); - if (bach.hasTOF()) { - auto tofNSigmaPr = bach.tofNSigmaPr(); - registry.fill(HIST("MC/Rec/hTOFNSigmaPrBachRecSig"), tofNSigmaPr); - registry.fill(HIST("MC/Rec/hPBachVsTOFNSigmaPrBachRecSig"), pBach, tofNSigmaPr); - } - } else { - registry.fill(HIST("MC/Rec/hPtCandRecBg"), ptCand); - registry.fill(HIST("MC/Rec/hEtaCandRecBg"), eta); - registry.fill(HIST("MC/Rec/hEtaCandVsPtCandRecBg"), eta, ptCand); - registry.fill(HIST("MC/Rec/hPhiCandRecBg"), phi); - registry.fill(HIST("MC/Rec/hPhiCandVsPtCandRecBg"), phi, ptCand); - registry.fill(HIST("MC/Rec/hMassRecBg"), invMassLcToK0sP); - registry.fill(HIST("MC/Rec/hMassVsPtCandRecBg"), invMassLcToK0sP, ptCand); - registry.fill(HIST("MC/Rec/hPtBachRecBg"), ptProng0); - registry.fill(HIST("MC/Rec/hPtBachVsPtCandRecBg"), ptProng0, ptCand); - registry.fill(HIST("MC/Rec/hPtV0RecBg"), ptProng1); - registry.fill(HIST("MC/Rec/hPtV0VsPtCandRecBg"), ptProng1, ptCand); - registry.fill(HIST("MC/Rec/hd0BachRecBg"), impactParameter0); - registry.fill(HIST("MC/Rec/hd0BachVsPtCandRecBg"), impactParameter0, ptCand); - registry.fill(HIST("MC/Rec/hd0V0RecBg"), impactParameter1); - registry.fill(HIST("MC/Rec/hd0V0VsPtCandRecBg"), impactParameter1, ptCand); - registry.fill(HIST("MC/Rec/hd0V0posRecBg"), dcaPosToPV); - registry.fill(HIST("MC/Rec/hd0V0posVsPtCandRecBg"), dcaPosToPV, ptCand); - registry.fill(HIST("MC/Rec/hd0V0negRecBg"), dcaNegToPV); - registry.fill(HIST("MC/Rec/hd0V0negVsPtCandRecBg"), dcaNegToPV, ptCand); - registry.fill(HIST("MC/Rec/hPtV0posRecBg"), ptV0Pos); - registry.fill(HIST("MC/Rec/hPtV0posVsPtCandRecBg"), ptV0Pos, ptCand); - registry.fill(HIST("MC/Rec/hPtV0negRecBg"), ptV0Neg); - registry.fill(HIST("MC/Rec/hPtV0negVsPtCandRecBg"), ptV0Neg, ptCand); - registry.fill(HIST("MC/Rec/hV0CPARecBg"), v0CosPA); - registry.fill(HIST("MC/Rec/hV0CPAVsPtCandRecBg"), v0CosPA, ptCand); - registry.fill(HIST("MC/Rec/hV0RadiusRecBg"), v0Radius); - registry.fill(HIST("MC/Rec/hV0RadiusVsPtCandRecBg"), v0Radius, ptCand); - registry.fill(HIST("MC/Rec/hV0DCADaughtersRecBg"), dcaV0Daughters); - registry.fill(HIST("MC/Rec/hV0DCADaughtersVsPtCandRecBg"), dcaV0Daughters, ptCand); - registry.fill(HIST("MC/Rec/hV0MK0ShortRecBg"), mK0Short); - registry.fill(HIST("MC/Rec/hV0MK0ShortVsPtCandRecBg"), mK0Short, ptCand); - registry.fill(HIST("MC/Rec/hV0MLambdaRecBg"), mLambda); - registry.fill(HIST("MC/Rec/hV0MLambdaVsPtCandRecBg"), mLambda, ptCand); - registry.fill(HIST("MC/Rec/hV0MAntiLambdaRecBg"), mAntiLambda); - registry.fill(HIST("MC/Rec/hV0MAntiLambdaVsPtCandRecBg"), mAntiLambda, ptCand); - registry.fill(HIST("MC/Rec/hV0MGammaRecBg"), mGamma); - registry.fill(HIST("MC/Rec/hV0MGammaVsPtCandRecBg"), mGamma, ptCand); - registry.fill(HIST("MC/Rec/hCtV0K0ShortRecBg"), ctV0K0Short); - registry.fill(HIST("MC/Rec/hCtV0K0ShortVsPtCandRecBg"), ctV0K0Short, ptCand); - registry.fill(HIST("MC/Rec/hCtV0LambdaRecBg"), ctV0Lambda); - registry.fill(HIST("MC/Rec/hCtV0LambdaVsPtCandRecBg"), ctV0Lambda, ptCand); - registry.fill(HIST("MC/Rec/hCPACandRecBg"), cpa); - registry.fill(HIST("MC/Rec/hCPACandVsPtCandRecBg"), cpa, ptCand); - registry.fill(HIST("MC/Rec/hCPAxyCandRecBg"), cpaXY); - registry.fill(HIST("MC/Rec/hCPAxyCandVsPtCandRecBg"), cpaXY, ptCand); - registry.fill(HIST("MC/Rec/hDecLengthCandRecBg"), decayLength); - registry.fill(HIST("MC/Rec/hDecLengthCandVsPtCandRecBg"), decayLength, ptCand); - registry.fill(HIST("MC/Rec/hDecLengthXYCandRecBg"), decayLengthXY); - registry.fill(HIST("MC/Rec/hDecLengthXYCandVsPtCandRecBg"), decayLengthXY, ptCand); - registry.fill(HIST("MC/Rec/hCtCandRecBg"), ctLc); - registry.fill(HIST("MC/Rec/hCtCandVsPtCandRecBg"), ctLc, ptCand); - registry.fill(HIST("MC/Rec/hTPCNSigmaPrBachRecBg"), tpcNSigmaPr); - registry.fill(HIST("MC/Rec/hPBachVsTPCNSigmaPrBachRecBg"), pBach, tpcNSigmaPr); - if (bach.hasTOF()) { - auto tofNSigmaPr = bach.tofNSigmaPr(); - registry.fill(HIST("MC/Rec/hTOFNSigmaPrBachRecBg"), tofNSigmaPr); - registry.fill(HIST("MC/Rec/hPBachVsTOFNSigmaPrBachRecBg"), pBach, tofNSigmaPr); + if (fillTHn && FillMl) { + float mass = HfHelper::invMassLcToK0sP(candidate); + float pt = candidate.pt(); + std::array mlScores{-1.f, -1.f, -1.f}; + if constexpr (CandType::template contains()) { + if (candidate.mlProbLcToK0sP().size() == NumberOfMlClasses) { + mlScores = {candidate.mlProbLcToK0sP()[MlClassBackground], + candidate.mlProbLcToK0sP()[MlClassPrompt], + candidate.mlProbLcToK0sP()[MlClassNonPrompt]}; + } + } + float cent = evaluateCentralityColl(collision); + int numPvContr = collision.numContrib(); + int8_t origin = candidate.originMcRec(); + registry.get(HIST("hnLcK0sPRecMcWithBdt"))->Fill(mass, pt, cent, mlScores[0], mlScores[1], mlScores[2], static_cast(numPvContr), origin); } } } - // MC gen. - for (const auto& particle : mcParticles) { - if (etaCandMax >= 0. && std::abs(particle.eta()) > etaCandMax) { - continue; - } - - if (std::abs(particle.flagMcMatchGen()) == 1) { + } + /// Helper function to fill MC generated histograms + template + void fillHistosMcGen(CandMcGen const& mcParticles, Coll const& recoCollisions) + { + for (const auto& particle : mcParticles) { + // if (etaCandMax >= 0. && std::abs(particle.eta()) > etaCandMax) { + // continue; + // } + if (std::abs(particle.flagMcMatchGen()) == KDecayChannelLcToK0sP) { auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaCPlus); if (yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) { continue; } - auto ptCand = particle.pt(); - auto eta = particle.eta(); - auto phi = particle.phi(); - registry.fill(HIST("MC/Gen/hPtCandGen"), ptCand); - registry.fill(HIST("MC/Gen/hEtaCandGen"), eta); - registry.fill(HIST("MC/Gen/hEtaCandVsPtCandGen"), eta, ptCand); - registry.fill(HIST("MC/Gen/hPhiCandGen"), phi); - registry.fill(HIST("MC/Gen/hPhiCandVsPtCandGen"), phi, ptCand); - + registry.fill(HIST("MC/Gen/hPtCandGen"), particle.pt()); + registry.fill(HIST("MC/Gen/hEtaCandGen"), particle.eta()); + registry.fill(HIST("MC/Gen/hPhiCandGen"), particle.phi()); if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("MC/Gen/hPtCandGenPrompt"), ptCand); + registry.fill(HIST("MC/Gen/hPtCandGenPrompt"), particle.pt()); } else if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("MC/Gen/hPtCandGenNonPrompt"), ptCand); + registry.fill(HIST("MC/Gen/hPtCandGenNonPrompt"), particle.pt()); + } + + if (fillTHn) { + int8_t origin = particle.originMcGen(); + float ptB = (origin == RecoDecay::OriginType::NonPrompt) ? mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt() : -1.; + const auto& recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollision, particle.mcCollision().globalIndex()); + int numPvContr = 0; + for (const auto& recCol : recoCollsPerMcColl) { + numPvContr = recCol.numContrib() > numPvContr ? recCol.numContrib() : numPvContr; + } + float cent = o2::hf_centrality::getCentralityGenColl(recoCollsPerMcColl); + registry.get(HIST("hnLcK0sPGenMc"))->Fill(particle.pt(), cent, yGen, static_cast(numPvContr), ptB, origin); } } } } - PROCESS_SWITCH(HfTaskLcToK0sP, processMc, "Process MC data", false); + void processDataStd(Collisions const& collisions, + FilteredCandLcToPK0SWSelFlag const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataStd, "Process Data", false); + + void processMcStd(CollisionsMc const& collisions, + FilteredCandLcToPK0SWSelFlagAndMc const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcStd, "Process MC data", false); + + // Data with ML + void processDataWithMl(Collisions const& collisions, + FilteredCandLcToPK0SWSelFlagAndMl const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataWithMl, "Process Data with ML", false); + + // MC Rec and Gen with ML + void processMcWithMl(CollisionsMc const& collisions, + FilteredCandLcToPK0SWSelFlagAndMcAndMl const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcWithMl, "Process MC with ML", false); + + // Data with FT0C centrality + void processDataStdWithFT0C(CollisionsWithFT0C const& collisions, + FilteredCandLcToPK0SWSelFlag const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataStdWithFT0C, "Process Data with FT0C centrality", false); + + // Data with FT0M centrality + void processDataStdWithFT0M(CollisionsWithFT0M const& collisions, + FilteredCandLcToPK0SWSelFlag const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataStdWithFT0M, "Process Data with FT0M centrality", false); + + // Data with ML + FT0C centrality + void processDataWithMlWithFT0C(CollisionsWithFT0C const& collisions, + FilteredCandLcToPK0SWSelFlagAndMl const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataWithMlWithFT0C, "Process Data with ML and FT0C centrality", false); + + // Data with ML + FT0M centrality + void processDataWithMlWithFT0M(CollisionsWithFT0M const& collisions, + FilteredCandLcToPK0SWSelFlagAndMl const& candidates, + TracksWPid const&) + { + runAnalysisPerCollisionData(collisions, candidates); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processDataWithMlWithFT0M, "Process Data with ML and FT0M centrality", false); + + // MC Std with FT0C centrality + void processMcStdWithFT0C(CollisionsMcWithFT0C const& collisions, + FilteredCandLcToPK0SWSelFlagAndMc const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcStdWithFT0C, "Process MC with FT0C centrality", false); + + // MC Std with FT0M centrality + void processMcStdWithFT0M(CollisionsMcWithFT0M const& collisions, + FilteredCandLcToPK0SWSelFlagAndMc const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcStdWithFT0M, "Process MC with FT0M centrality", false); + + // MC with ML + FT0C centrality + void processMcWithMlWithFT0C(CollisionsMcWithFT0C const& collisions, + FilteredCandLcToPK0SWSelFlagAndMcAndMl const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcWithMlWithFT0C, "Process MC with ML and FT0C centrality", false); + + // MC with ML + FT0M centrality + void processMcWithMlWithFT0M(CollisionsMcWithFT0M const& collisions, + FilteredCandLcToPK0SWSelFlagAndMcAndMl const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + TracksWPid const&) + { + runAnalysisPerCollisionMc(collisions, candidates, mcParticles); + } + PROCESS_SWITCH(HfTaskLcToK0sP, processMcWithMlWithFT0M, "Process MC with ML and FT0M centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 5935fab0d044bf2272fccda7f621f96f08cd4cbe Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Tue, 2 Jun 2026 17:09:15 +0200 Subject: [PATCH 396/449] [PWGHF] Apply UPC Lc ZDC timing cut online and simplify TTree (#16501) --- PWGHF/D2H/Tasks/taskUpcLc.cxx | 60 ++++++++++++++++------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskUpcLc.cxx b/PWGHF/D2H/Tasks/taskUpcLc.cxx index 74764b924ff..0a445cbe505 100644 --- a/PWGHF/D2H/Tasks/taskUpcLc.cxx +++ b/PWGHF/D2H/Tasks/taskUpcLc.cxx @@ -92,11 +92,7 @@ DECLARE_SOA_TABLE(HfUpcQa, "AOD", "HFUPCQA", DECLARE_SOA_TABLE(HfUpcLcBdtInfos, "AOD", "HFUPCLCBDTINFOS", full::M, full::Pt, - full::BkgScore, - full::AmpFT0A, - full::AmpFT0C, - full::ZdcTimeZNA, - full::ZdcTimeZNC); + full::BkgScore); DECLARE_SOA_TABLE(HfUpcLcInfos, "AOD", "HFUPCLCINFOS", full::M, @@ -106,11 +102,7 @@ DECLARE_SOA_TABLE(HfUpcLcInfos, "AOD", "HFUPCLCINFOS", full::PtProng2, full::Chi2PCA, full::DecayLength, - full::Cpa, - full::AmpFT0A, - full::AmpFT0C, - full::ZdcTimeZNA, - full::ZdcTimeZNC); + full::Cpa); } // namespace o2::aod /// Λc± → p± K∓ π± analysis task @@ -125,6 +117,7 @@ struct HfTaskUpcLc { Configurable fillTreeOnlySingleGap{"fillTreeOnlySingleGap", false, "Only fill the tree for candidates that pass the single-gap UPC events"}; Configurable fillTreeUpcQa{"fillTreeUpcQa", false, "Fill Tree for UPC QA"}; Configurable verticesWithUpc{"verticesWithUpc", false, "Consider vertices with UPC settings"}; + Configurable zdcTimeThreshold{"zdcTimeThreshold", 2., "Threshold for ZNA/ZNC time"}; // CCDB configuration Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; @@ -167,7 +160,7 @@ struct HfTaskUpcLc { registry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); registry.add("Data/hUpcMulti", "Multiplicity of UPC events;Multiplicity;Counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); registry.add("Data/hUpcVtz", "Vertex Z position of UPC events;Vz (cm);Counts", {HistType::kTH1F, {{200, -10., 10.}}}); - + registry.add("Data/eta_vs_Multi", "Eta vs Multiplicity;Eta;Multiplicity", {HistType::kTH2F, {{20, -1., 1.}, {200, -0.5, 199.5}}}); hfEvSel.addHistograms(registry); ccdb->setURL(ccdbUrl); ccdb->setCaching(true); @@ -226,9 +219,13 @@ struct HfTaskUpcLc { float zdcEnergyZNC = -1.f; float zdcTimeZNA = -1.f; float zdcTimeZNC = -1.f; + bool gapA0nXn = false; + bool gapCXn0n = false; + if (verticesWithUpc && !upcFlag) { continue; } + if (hasZdc) { const auto zdc = bcForUPC.zdc(); zdcEnergyZNA = zdc.energyCommonZNA(); @@ -240,12 +237,22 @@ struct HfTaskUpcLc { registry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); registry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast(gap)); } - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - registry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); - registry.fill(HIST("Data/hUpcVtz"), collision.posZ()); - if (fillTreeUpcQa) { - rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); - } + const bool ignoreZdcTime = (zdcTimeThreshold < 0.f); + + if (gap == o2::aod::sgselector::TrueGap::SingleGapA && (ignoreZdcTime || (std::abs(zdcTimeZNA) > zdcTimeThreshold && std::abs(zdcTimeZNC) < zdcTimeThreshold))) { + gapA0nXn = true; + } + if (gap == o2::aod::sgselector::TrueGap::SingleGapC && (ignoreZdcTime || (std::abs(zdcTimeZNA) < zdcTimeThreshold && std::abs(zdcTimeZNC) > zdcTimeThreshold))) { + gapCXn0n = true; + } + if (fillTreeOnlySingleGap & !gapA0nXn & !gapCXn0n) { + continue; + } + registry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); + registry.fill(HIST("Data/hUpcVtz"), collision.posZ()); + + if (fillTreeUpcQa) { + rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } for (const auto& candidate : groupedLcCandidates) { @@ -262,34 +269,23 @@ struct HfTaskUpcLc { const auto decayLength = candidate.decayLength(); const auto chi2PCA = candidate.chi2PCA(); const auto cpa = candidate.cpa(); + const auto eta = candidate.eta(); double outputBkg(-1); auto fillTHnData = [&](bool isPKPi) { const auto massLc = isPKPi ? HfHelper::invMassLcToPKPi(candidate) : HfHelper::invMassLcToPiKP(candidate); - + registry.fill(HIST("Data/eta_vs_Multi"), eta, collision.multNTracksPV()); if constexpr (FillMl) { const auto& mlProb = isPKPi ? candidate.mlProbLcToPKPi() : candidate.mlProbLcToPiKP(); if (mlProb.size() == NumberOfMlClasses) { outputBkg = mlProb[MlClassBackground]; /// bkg score } /// Fill the ML outputScores and variables of candidate - if (fillTreeOnlySingleGap) { - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - rowCandUpcBdt(massLc, pt, outputBkg, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); - } - } else { - rowCandUpcBdt(massLc, pt, outputBkg, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); - } + rowCandUpcBdt(massLc, pt, outputBkg); } else { - if (fillTreeOnlySingleGap) { - if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { - rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); - } - } else { - rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); - } + rowCandUpc(massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa); } }; From c9da89f5e0222f7f675a1f750f5dfcc140f5f211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:10:33 +0200 Subject: [PATCH 397/449] [Infrastructure] Bump oxsecurity/megalinter from 9.4.0 to 9.5.0 (#16506) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/mega-linter.yml | 2 +- .mega-linter.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 7b558e9e825..a52b7b6f404 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -38,7 +38,7 @@ jobs: id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://megalinter.io/flavors/ - uses: oxsecurity/megalinter@v9.4.0 + uses: oxsecurity/megalinter@v9.5.0 env: # All available variables are described in documentation: # https://megalinter.io/configuration/ diff --git a/.mega-linter.yml b/.mega-linter.yml index b9a956bd20a..befd6badf61 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -21,11 +21,13 @@ DISABLE_LINTERS: - REPOSITORY_DEVSKIM - REPOSITORY_GITLEAKS - REPOSITORY_KICS + - REPOSITORY_OSV_SCANNER - REPOSITORY_SECRETLINT - REPOSITORY_TRIVY - YAML_PRETTIER - YAML_V8R DISABLE_ERRORS_LINTERS: # If errors are found by these linters, they will be considered as non blocking. + - ACTION_ZIZMOR - PYTHON_BANDIT # The bandit check is overly broad and complains about subprocess usage. SHOW_ELAPSED_TIME: true FILEIO_REPORTER: false @@ -42,3 +44,4 @@ CPP_CLANG_FORMAT_FILE_EXTENSIONS: [".C", ".c", ".c++", ".cc", ".cl", ".cpp", ".c CPP_CPPCHECK_FILE_EXTENSIONS: [".C", ".c", ".c++", ".cc", ".cl", ".cpp", ".cu", ".cuh", ".cxx", ".cxx.in", ".h", ".h++", ".hh", ".h.in", ".hpp", ".hxx", ".inc", ".inl", ".macro"] CPP_CPPCHECK_ARGUMENTS: --language=c++ --std=c++20 --check-level=exhaustive --suppressions-list=cppcheck_config REPOSITORY_GITLEAKS_PR_COMMITS_SCAN: true +ACTION_ZIZMOR_UNSECURED_ENV_VARIABLES: [GITHUB_TOKEN] From bf2030708e40a136164ff1074464a41ae5912e31 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:37:15 +0200 Subject: [PATCH 398/449] [PWGCF] Add interaction rate and occupancy selection for MC (#16508) --- PWGCF/Flow/Tasks/CMakeLists.txt | 2 +- PWGCF/Flow/Tasks/flowMc.cxx | 46 ++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index 64f235e7337..226449b78fe 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -26,7 +26,7 @@ o2physics_add_dpl_workflow(flow-runby-run o2physics_add_dpl_workflow(flow-mc SOURCES flowMc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(flow-qa diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index ed371aa5a3a..e630075dc45 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -21,6 +21,7 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -59,6 +60,7 @@ #include #include #include +#include #include using namespace o2; @@ -118,6 +120,13 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgRecoEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgRecoEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking', 'CBT_hadronPID' ") + O2_DEFINE_CONFIGURABLE(cfgIRFetch, bool, false, "Get interaction rate from CCDB") + O2_DEFINE_CONFIGURABLE(cfgIRCutEnabled, bool, false, "Use events with low interaction rate") + O2_DEFINE_CONFIGURABLE(cfgIRMax, float, 50.0f, "maximum interaction rate (kHz)") + O2_DEFINE_CONFIGURABLE(cfgIRMin, float, 0.0f, "minimum interaction rate (kHz)") + O2_DEFINE_CONFIGURABLE(cfgOccupancyEnabled, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgOccupancyMax, int, 2000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgOccupancyMin, int, 0, "Low cut on TPC occupancy") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.6003720411, 0.6152630970, 0.6288860646, 0.6360694031, 0.6409494798, 0.6450540203, 0.6482117301, 0.6512592056, 0.6640008690, 0.6862631416, 0.7005738691, 0.7106567432, 0.7170728333}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-1.007592e-05, -8.932635e-06, -9.114538e-06, -1.054818e-05, -1.220212e-05, -1.312304e-05, -1.376433e-05, -1.412813e-05, -1.289562e-05, -1.050065e-05, -8.635725e-06, -7.380821e-06, -6.201250e-06}, "parameter 1 for track density efficiency correction"}; @@ -181,7 +190,12 @@ struct FlowMc { std::vector corrconfigsReco; TRandom3* fRndm = new TRandom3(0); double epsilon = 1e-6; - + int mRunNumber{-1}; + uint64_t mSOR{0}; + double mMinSeconds{-1.}; + std::unordered_map gHadronicRate; + ctpRateFetcher mRateFetcher; + TH2* gCurrentHadronicRate; RCTFlagsChecker rctChecker{"CBT"}; void init(InitContext&) @@ -442,6 +456,23 @@ struct FlowMc { } } + void initHadronicRate(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + if (gHadronicRate.find(mRunNumber) == gHadronicRate.end()) { + auto runDuration = ccdb->getRunDuration(mRunNumber); + mSOR = runDuration.first; + mMinSeconds = std::floor(mSOR * 1.e-3); /// round tsSOR to the highest integer lower than tsSOR + double maxSec = std::ceil(runDuration.second * 1.e-3); /// round tsEOR to the lowest integer higher than tsEOR + const AxisSpec axisSeconds{static_cast((maxSec - mMinSeconds) / 20.f), 0, maxSec - mMinSeconds, "Seconds since SOR"}; + gHadronicRate[mRunNumber] = histos.add(Form("HadronicRate/%i", mRunNumber), ";Time since SOR (s);Hadronic rate (kHz)", kTH2D, {axisSeconds, {510, 0., 51.}}).get(); + } + gCurrentHadronicRate = gHadronicRate[mRunNumber]; + } + template bool eventSelected(TCollision collision) { @@ -451,6 +482,11 @@ struct FlowMc { if (cfgRecoEvSel8 && !collision.sel8()) { return 0; } + if (cfgOccupancyEnabled) { + auto occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < cfgOccupancyMin || occupancy > cfgOccupancyMax) + return 0; + } if (!cfgEvSelRCTflags.value.empty() && !rctChecker(*collision)) return 0; if (cfgRecoEvkNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { @@ -519,6 +555,14 @@ struct FlowMc { float wacc = 1.; auto bc = mcCollision.bc_as(); loadCorrections(bc.timestamp()); + if (cfgIRFetch) { + initHadronicRate(bc); + double hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), mRunNumber, "ZNC hadronic") * 1.e-3; // + double seconds = bc.timestamp() * 1.e-3 - mMinSeconds; + if (cfgIRCutEnabled && (hadronicRate < cfgIRMin || hadronicRate > cfgIRMax)) // cut on hadronic rate + return; + gCurrentHadronicRate->Fill(seconds, hadronicRate); + } if (collisions.size() > -1) { histos.fill(HIST("numberOfRecoCollisions"), collisions.size()); // number of times coll was reco-ed From 17b408046f240ef77d9ea938049b1796f7267ea9 Mon Sep 17 00:00:00 2001 From: swapneshkhade <107178389+swapneshkhade@users.noreply.github.com> Date: Wed, 3 Jun 2026 00:47:51 +0530 Subject: [PATCH 399/449] [PWGHF] Fix trigger daughter rejection logic in MCGen of the D0-hadron correlator (#16509) --- PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index d5e8a924fc8..9c864ab2909 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -966,6 +966,14 @@ struct HfCorrelatorD0Hadrons { if (!particleAssoc.isPhysicalPrimary()) { continue; } + + // Explicitly reject direct daughters of the current trigger D0/D0bar. + auto const motherIdxD0 = RecoDecay::getMother(mcParticles, particleAssoc, Pdg::kD0, true, nullptr, 1); + auto const motherIdxD0bar = RecoDecay::getMother(mcParticles, particleAssoc, -Pdg::kD0, true, nullptr, 1); + if (motherIdxD0 == particleTrigg.globalIndex() || motherIdxD0bar == particleTrigg.globalIndex()) { + continue; + } + // ==============================soft pion removal================================ registry.fill(HIST("hTrackCounter"), 1); // fill before soft pi removal // method used: indexMother = -1 by default if the mother doesn't match with given PID of the mother. We find mother of pion if it is D* and mother of D0 if it is D*. If they are both positive and they both match each other, then it is detected as a soft pion From 3cf3abe29af51f69754e31a63ff93e27948be5d5 Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Tue, 2 Jun 2026 22:19:27 +0200 Subject: [PATCH 400/449] [PWGLF] Add histogram for centrality distribution for correction factors (#16512) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/chk892LI.cxx | 174 ++++++++++++++++++++++------ 1 file changed, 140 insertions(+), 34 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chk892LI.cxx b/PWGLF/Tasks/Resonances/chk892LI.cxx index 6fcf8f03b42..ecdc279d04a 100644 --- a/PWGLF/Tasks/Resonances/chk892LI.cxx +++ b/PWGLF/Tasks/Resonances/chk892LI.cxx @@ -145,6 +145,9 @@ struct Chk892LI { ConfigurableAxis cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex axis"}; Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; Configurable cNbinsDivQA{"cNbinsDivQA", 1, "Integer to divide the number of bins for QA"}; + + Configurable> cfgGenMultCuts{"cfgGenMultCuts", std::vector{500, 300, 200, 120, 80, 50, 30, 10, 0}, "Generated multiplicity lower cuts corresponding to reco centrality bins"}; + Configurable> cfgCentBinCentres{"cfgCentBinCentres", std::vector{2.5, 7.5, 15.0, 25.0, 35.0, 45.0, 55.0, 75.0, 95.0}, "Reco centrality bin centres"}; } AxisConfig; /// Event cuts @@ -253,7 +256,10 @@ struct Chk892LI { Configurable cfgRecoUseInelGt0{"cfgRecoUseInelGt0", false, "Data/Reco require INEL>0"}; Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", false, "Truth denominator: require INEL>0"}; - Configurable cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", true, "Truth denominator: also require |vtxz| cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", false, "Truth denominator: also require |vtxz| cfgGenMultEtaMax{"cfgGenMultEtaMax", 0.5, "Max Eta for generated mid-rapidity multiplicity"}; + Configurable cfgGenMultEtaMin{"cfgGenMultEtaMin", -0.5, "Min Eta for generated mid-rapidity multiplicity"}; float lCentrality; @@ -422,6 +428,8 @@ struct Chk892LI { // MC if (doprocessMC) { + AxisSpec genMultAxis{500, -0.5, 499.5, "N_{ch}^{gen} (|#eta|<0.5)"}; + histos.add("QACent_woCut", "Centrality without cut", HistType::kTH1F, {centAxis}); histos.add("QACent_woCentCut", "Centrality without cent cut", HistType::kTH1F, {centAxis}); histos.add("QACent_wCentCut", "Centrality with cent cut", HistType::kTH1F, {centAxis}); @@ -445,7 +453,18 @@ struct Chk892LI { histos.add("Correction/sigLoss_num_pri_pos", "Gen primary Kstar selected by vertex position (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); histos.add("Correction/EF_den", "Gen events (truth class)", HistType::kTH1F, {centAxis}); histos.add("Correction/EF_num", "Reco events (selected events)", HistType::kTH1F, {centAxis}); + histos.add("Correction/RecoCentVsGenMult", "Reco centrality vs generated mid-rapidity multiplicity", HistType::kTH2F, {centAxis, genMultAxis}); + histos.add("Correction/sigLoss_num_vsGenMult", "Generated Kstar in selected events vs gen mult", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/sigLoss_num_vsGenMult_pri", "Generated Kstar in selected events vs gen mult", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/sigLoss_num_vsGenMult_pri_pos", "Generated Kstar in selected events vs gen mult", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/sigLoss_den_vsGenMult", "Generated Kstar vs generated mid-rapidity multiplicity", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/sigLoss_den_vsGenMult_pri", "Generated primary Kstar vs generated mid-rapidity multiplicity", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/sigLoss_den_vsGenMult_pri_pos", "Generated primary Kstar selected by vertex position vs generated mid-rapidity multiplicity", HistType::kTH2F, {ptAxis, genMultAxis}); + histos.add("Correction/EF_num_vsGenMult", "Selected reco-associated events vs gen mult", HistType::kTH1F, {genMultAxis}); + histos.add("Correction/EF_den_vsGenMult", "Truth selected generated events vs generated multiplicity", HistType::kTH1F, {genMultAxis}); + histos.add("Correction/MCTruthCent_all", "MC truth FT0M centrality (all mcCollisions)", HistType::kTH1F, {centAxis}); + histos.add("Correction/MCTruthCent_allowed", "MC truth FT0M centrality (allowed mcCollisions)", HistType::kTH1F, {centAxis}); histos.add("Correction/MCTruthCent_cut", "MC truth FT0M centrality (truth selection applied)", HistType::kTH1F, {centAxis}); histos.add("Correction/setSizes", "Sizes of sets", HistType::kTH1F, {{4, -0.5, 3.5}}); @@ -496,6 +515,53 @@ struct Chk892LI { } } + template + int getGenMidRapMultiplicity(McPartsT const& partsThisMc) + { + int nCh = 0; + + for (auto const& part : partsThisMc) { + if (!part.isPhysicalPrimary()) { + continue; + } + if (part.eta() > cfgGenMultEtaMax || part.eta() < cfgGenMultEtaMin) { + continue; + } + + auto pdgParticle = pdg->GetParticle(part.pdgCode()); + if (!pdgParticle) { + continue; + } + if (pdgParticle->Charge() == 0) { + continue; + } + + nCh++; + } + + return nCh; + } + + float getCentClassFromGenMult(int nCh) + { + const auto& cuts = AxisConfig.cfgGenMultCuts.value; + const auto& centres = AxisConfig.cfgCentBinCentres.value; + + if (cuts.size() != centres.size()) { + LOGF(fatal, + "cfgGenMultCuts size (%zu) and cfgCentBinCentres size (%zu) must be same", + cuts.size(), centres.size()); + } + + for (size_t i = 0; i < cuts.size(); ++i) { + if (nCh >= cuts[i]) { + return centres[i]; + } + } + + return kInvalidCentrality; + } + // Track selection template bool trackCut(TrackType const& track) @@ -560,8 +626,6 @@ struct Chk892LI { return false; if (PIDCuts.cfgTPConly) return true; - // if (candidate.pt() <= PIDCuts.cfgTOFMinPt) - // return true; if (candidate.hasTOF()) { const bool tofPIDPassed = std::abs(candidate.tofNSigmaPi()) < PIDCuts.cfgMaxTOFnSigmaPion; @@ -720,10 +784,10 @@ struct Chk892LI { std::unordered_map centTruthByAllowed; std::unordered_set refClassIds; std::unordered_map refCentByMcId; + std::unordered_map genMultByMcId; - template - // void buildAllowedMcIds(McCollsT const& mcCollisions, RecoEventsT const& events) - void buildAllowedMcIds(McCollsT const& mcCollisions, MCEventCandidates const& events) + template + void buildAllowedMcIds(McCollsT const& mcCollisions, MCEventCandidates const& events, McPartsT const& mcparts) { allowedMcIds.clear(); centTruthByAllowed.clear(); @@ -770,14 +834,6 @@ struct Chk892LI { histos.fill(HIST("QACent_woCentCut"), lCentrality); } - if (lCentrality < EventCuts.cfgEventCentralityMin || lCentrality > EventCuts.cfgEventCentralityMax) { - continue; - } - - if (doprocessMC) { - histos.fill(HIST("QACent_wCentCut"), lCentrality); - } - atLeastOneMatch = true; // choose best collision by largest number of PV contributors @@ -792,11 +848,29 @@ struct Chk892LI { continue; } + auto partsThisMc = mcparts.sliceBy(perMCCollision, mcid); + const int genMult = getGenMidRapMultiplicity(partsThisMc); + const float genCentClass = getCentClassFromGenMult(genMult); + + if (genCentClass == kInvalidCentrality) + continue; + + if (genCentClass < EventCuts.cfgEventCentralityMin || genCentClass > EventCuts.cfgEventCentralityMax) { + continue; + } + + if (doprocessMC) { + histos.fill(HIST("QACent_wCentCut"), bestCent); + } + allowedMcIds.insert(mcid); - centTruthByAllowed.emplace(mcid, bestCent); + centTruthByAllowed.emplace(mcid, genCentClass); + genMultByMcId[mcid] = genMult; if (doprocessMC) { - histos.fill(HIST("QAMCCent_allowed"), bestCent); + histos.fill(HIST("Correction/EF_num_vsGenMult"), genMult); + histos.fill(HIST("Correction/RecoCentVsGenMult"), bestCent, genMult); + histos.fill(HIST("QAMCCent_allowed"), genCentClass); } } } // buildAllowedMcIds @@ -808,31 +882,33 @@ struct Chk892LI { refCentByMcId.clear(); for (const auto& coll : mccolls) { - bool pass = true; - - if (cfgTruthIncludeZvtx && std::abs(coll.posZ()) >= EventCuts.cfgEvtZvtx) - pass = false; + const auto mcid = coll.globalIndex(); - if (pass && cfgTruthUseInelGt0) { - auto partsThisMc = mcparts.sliceBy(perMCCollision, coll.globalIndex()); - if (!pwglf::isINELgtNmc(partsThisMc, 0, pdg)) - pass = false; + if (cfgTruthIncludeZvtx && std::abs(coll.posZ()) >= EventCuts.cfgEvtZvtx) { + continue; } - if (!pass) + auto partsThisMc = mcparts.sliceBy(perMCCollision, mcid); + + if (cfgTruthUseInelGt0 && !pwglf::isINELgtNmc(partsThisMc, 0, pdg)) { continue; + } - const auto mcid = coll.globalIndex(); + const int genMult = getGenMidRapMultiplicity(partsThisMc); + const float genCentClass = getCentClassFromGenMult(genMult); - auto it = centTruthByAllowed.find(mcid); - if (it == centTruthByAllowed.end()) { + if (genCentClass == kInvalidCentrality) { + continue; + } + if (genCentClass < EventCuts.cfgEventCentralityMin || genCentClass > EventCuts.cfgEventCentralityMax) { continue; } refClassIds.insert(mcid); + refCentByMcId.emplace(mcid, genCentClass); + genMultByMcId[mcid] = genMult; - const float lCentrality = it->second; - refCentByMcId.emplace(mcid, lCentrality); + histos.fill(HIST("Correction/EF_den_vsGenMult"), genMult); } // for } // buildReferenceMcIds @@ -1115,8 +1191,16 @@ struct Chk892LI { const float lCentrality = iter->second; + auto itMult = genMultByMcId.find(mcid); + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_num_vsGenMult"), part.pt(), itMult->second); + } histos.fill(HIST("Correction/sigLoss_num"), part.pt(), lCentrality); + if (part.vt() == 0) { + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_num_vsGenMult_pri"), part.pt(), itMult->second); + } histos.fill(HIST("Correction/sigLoss_num_pri"), part.pt(), lCentrality); } @@ -1129,6 +1213,9 @@ struct Chk892LI { const float distanceFromPV = std::sqrt(dx * dx + dy * dy + dz * dz); if (distanceFromPV < fMaxPosPV) { + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_num_vsGenMult_pri_pos"), part.pt(), itMult->second); + } histos.fill(HIST("Correction/sigLoss_num_pri_pos"), part.pt(), lCentrality); } } @@ -1155,8 +1242,16 @@ struct Chk892LI { const float lCentrality = iter->second; histos.fill(HIST("Correction/sigLoss_den"), part.pt(), lCentrality); + + auto itMult = genMultByMcId.find(mcid); + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_den_vsGenMult"), part.pt(), itMult->second); + } if (part.vt() == 0) { histos.fill(HIST("Correction/sigLoss_den_pri"), part.pt(), lCentrality); + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_den_vsGenMult_pri"), part.pt(), itMult->second); + } } const auto mcc = part.mcCollision_as(); @@ -1169,6 +1264,9 @@ struct Chk892LI { if (distanceFromPV < fMaxPosPV) { histos.fill(HIST("Correction/sigLoss_den_pri_pos"), part.pt(), lCentrality); + if (itMult != genMultByMcId.end()) { + histos.fill(HIST("Correction/sigLoss_den_vsGenMult_pri_pos"), part.pt(), itMult->second); + } } } } // fillSigLossDen @@ -1428,7 +1526,8 @@ struct Chk892LI { MCEventCandidates const& events, MCTrueEventCandidates const& mccolls) { - buildAllowedMcIds(mccolls, events); + genMultByMcId.clear(); + buildAllowedMcIds(mccolls, events, mcpart); buildReferenceMcIds(mccolls, mcpart); effK0sProcessGen(mcpart); effK0sProcessReco(v0s); @@ -1445,6 +1544,7 @@ struct Chk892LI { const float lCentrality = iter->second; histos.fill(HIST("Correction/EF_den"), lCentrality); } + for (const auto& mcid : allowedMcIds) { auto iter = centTruthByAllowed.find(mcid); if (iter == centTruthByAllowed.end()) @@ -1463,8 +1563,14 @@ struct Chk892LI { histos.fill(HIST("Correction/setSizes"), 2.0, nIntersect); histos.fill(HIST("Correction/setSizes"), 3.0, allowedMcIds.size() - nIntersect); - for (auto const& [mcid, lCentrality] : centTruthByAllowed) { - histos.fill(HIST("Correction/MCTruthCent_all"), lCentrality); + for (auto const& mcc : mccolls) { + auto partsThisMc = mcpart.sliceBy(perMCCollision, mcc.globalIndex()); + const int genMult = getGenMidRapMultiplicity(partsThisMc); + const float genCentClass = getCentClassFromGenMult(genMult); + if (genCentClass == kInvalidCentrality) { + continue; + } + histos.fill(HIST("Correction/MCTruthCent_all"), genCentClass); } for (const auto& mcid : refClassIds) { @@ -1488,7 +1594,7 @@ struct Chk892LI { histos.fill(HIST("Correction/hNEventsMCTruth"), 2.0); auto partsThisMc = mcpart.sliceBy(perMCCollision, mcid); - if (pwglf::isINELgtNmc(partsThisMc, 0, pdg)) { + if (!cfgTruthUseInelGt0 || pwglf::isINELgtNmc(partsThisMc, 0, pdg)) { histos.fill(HIST("Correction/hNEventsMCTruth"), 3.0); } } From 933b7c88aed9e553fefa1f2899ee673c26ff68c6 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Wed, 3 Jun 2026 00:32:27 -0600 Subject: [PATCH 401/449] [PWGLF] Added histograms with finer binning (#16513) Co-authored-by: Paola Vargas Torres --- PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx | 26 +++++++++++++- PWGLF/Tasks/Nuspex/multiplicityPt.cxx | 47 +++++++++++++++++++++----- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index ef69d76fce9..f38ea80f6ef 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -69,6 +69,10 @@ static constexpr int NCentHists{10}; std::array, NCentHists> hDedxVsMomentumVsCentPos{}; std::array, NCentHists> hDedxVsMomentumVsCentNeg{}; std::array, NCentHists + 1> hDedxVspTMomentumVsCent{}; +std::array, NCentHists + 1> hMomentumVsEtaPos{}; +std::array, NCentHists + 1> hMomentumVsEtaNeg{}; +std::array, NCentHists + 1> hpTVsEtaPos{}; +std::array, NCentHists + 1> hpTVsEtaNeg{}; struct DedxPidAnalysis { @@ -247,6 +251,11 @@ struct DedxPidAnalysis { static constexpr std::string_view DedxvsMomentumvsCentPos[CentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Pos", "dEdx_vs_Momentum_Cent1_5_Pos", "dEdx_vs_Momentum_Cent5_10_Pos", "dEdx_vs_Momentum_Cent10_15_Pos", "dEdx_vs_Momentum_Cent15_20_Pos", "dEdx_vs_Momentum_Cent20_30_Pos", "dEdx_vs_Momentum_Cent30_40_Pos", "dEdx_vs_Momentum_Cent40_50_Pos", "dEdx_vs_Momentum_Cent50_70_Pos", "dEdx_vs_Momentum_Cent70_100_Pos"}; static constexpr std::string_view DedxvsMomentumvsCentNeg[CentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Neg", "dEdx_vs_Momentum_Cent1_5_Neg", "dEdx_vs_Momentum_Cent5_10_Neg", "dEdx_vs_Momentum_Cent10_15_Neg", "dEdx_vs_Momentum_Cent15_20_Neg", "dEdx_vs_Momentum_Cent20_30_Neg", "dEdx_vs_Momentum_Cent30_40_Neg", "dEdx_vs_Momentum_Cent40_50_Neg", "dEdx_vs_Momentum_Cent50_70_Neg", "dEdx_vs_Momentum_Cent70_100_Neg"}; static constexpr std::string_view DedxvspTMomentumvsCent[CentralityClasses + 1] = {"dEdx_vs_pTMomentum_Cent0_1", "dEdx_vs_pTMomentum_Cent1_5", "dEdx_vs_pTMomentum_Cent5_10", "dEdx_vs_pTMomentum_Cent10_15", "dEdx_vs_pTMomentum_Cent15_20", "dEdx_vs_pTMomentum_Cent20_30", "dEdx_vs_pTMomentum_Cent30_40", "dEdx_vs_pTMomentum_Cent40_50", "dEdx_vs_pTMomentum_Cent50_70", "dEdx_vs_pTMomentum_Cent70_100", "dEdx_vs_pTMomentum_all_Pos"}; + // Fine binnind + static constexpr std::string_view CentpPos[CentralityClasses + 1] = {"p_vs_eta_Cent0_1_Pos", "p_vs_eta_Cent1_5_Pos", "p_vs_eta_Cent5_10_Pos", "p_vs_eta_Cent10_15_Pos", "p_vs_eta_Cent15_20_Pos", "p_vs_eta_Cent20_30_Pos", "p_vs_eta_Cent30_40_Pos", "p_vs_eta_Cent40_50_Pos", "p_vs_eta_Cent50_70_Pos", "p_vs_eta_Cent70_100_Pos", "p_vs_eta_MB_Pos"}; + static constexpr std::string_view CentpNeg[CentralityClasses + 1] = {"p_vs_eta_Cent0_1_Neg", "p_vs_eta_Cent1_5_Neg", "p_vs_eta_Cent5_10_Neg", "p_vs_eta_Cent10_15_Neg", "p_vs_eta_Cent15_20_Neg", "p_vs_eta_Cent20_30_Neg", "p_vs_eta_Cent30_40_Neg", "p_vs_eta_Cent40_50_Neg", "p_vs_eta_Cent50_70_Neg", "p_vs_eta_Cent70_100_Neg", "p_vs_eta_MB_Neg"}; + static constexpr std::string_view CentpTPos[CentralityClasses + 1] = {"pT_vs_eta_Cent0_1_Pos", "pT_vs_eta_Cent1_5_Pos", "pT_vs_eta_Cent5_10_Pos", "pT_vs_eta_Cent10_15_Pos", "pT_vs_eta_Cent15_20_Pos", "pT_vs_eta_Cent20_30_Pos", "pT_vs_eta_Cent30_40_Pos", "pT_vs_eta_Cent40_50_Pos", "pT_vs_eta_Cent50_70_Pos", "pT_vs_eta_Cent70_100_Pos", "pT_vs_eta_MB_Pos"}; + static constexpr std::string_view CentpTNeg[CentralityClasses + 1] = {"pT_vs_eta_Cent0_1_Neg", "pT_vs_eta_Cent1_5_Neg", "pT_vs_eta_Cent5_10_Neg", "pT_vs_eta_Cent10_15_Neg", "pT_vs_eta_Cent15_20_Neg", "pT_vs_eta_Cent20_30_Neg", "pT_vs_eta_Cent30_40_Neg", "pT_vs_eta_Cent40_50_Neg", "pT_vs_eta_Cent50_70_Neg", "pT_vs_eta_Cent70_100_Neg", "pT_vs_eta_MB_Neg"}; // Ncl TPC static constexpr std::string_view NclTPCDedxMomentumNegBefore[EtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_8_Before"}; static constexpr std::string_view NclTPCDedxMomentumPosBefore[EtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_8_Before"}; @@ -263,6 +272,7 @@ struct DedxPidAnalysis { Configurable> calibrationFactorPos{"calibrationFactorPos", {50.5157, 50.6359, 50.3198, 49.3345, 48.9197, 49.4931, 50.0188, 50.1406}, "positive calibration factors"}; ConfigurableAxis binP{"binP", {VARIABLE_WIDTH, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, ""}; ConfigurableAxis centBins{"centBins", {100, 0, 100}, "Binning for centralidad"}; + ConfigurableAxis pFineBins{"pFineBins", {1995, 0.1, 40}, "Binning for momentum"}; // phi cut fits TF1* fphiCutHigh = nullptr; @@ -351,11 +361,13 @@ struct DedxPidAnalysis { LOGF(info, "Centrality clases between %.1f - %.1f", CentClasses[0], CentClasses[10]); AxisSpec dedxAxis{100, 0.0, 100.0, "dE/dx (a. u.)"}; - AxisSpec ptAxis = {binP, "pT (GeV/c)"}; + AxisSpec ptAxis = {binP, "#it{p}_{T} (GeV/c)"}; AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; AxisSpec pAxis = {binP, "#it{p}/Z (GeV/c)"}; AxisSpec pAxisTrack = {binP, "#it{p} (GeV/c)"}; AxisSpec centAxis{centBins, "Undefined multiplicity estimator"}; + AxisSpec pFineAxis{pFineBins, "#it{p} (GeV/c)"}; + AxisSpec pTFineAxis{pFineBins, "#it{p}_{T} (GeV/c)"}; switch (multiplicityEstimator) { case MultSelectionMode::NoMultiplicity: // No multiplicity LOGF(info, "No multiplicity estimator applied"); @@ -488,6 +500,10 @@ struct DedxPidAnalysis { for (int i = 0; i < CentralityClasses + 1; ++i) { hDedxVspTMomentumVsCent[i] = registryDeDx.add(DedxvspTMomentumvsCent[i].data(), "dE/dx", HistType::kTH3F, {{ptAxis}, {dedxAxis}, {etaAxis}}); + hMomentumVsEtaPos[i] = registryDeDx.add(CentpPos[i].data(), "p vs eta", HistType::kTH2F, {{etaAxis}, {pFineAxis}}); + hMomentumVsEtaNeg[i] = registryDeDx.add(CentpNeg[i].data(), "p vs eta", HistType::kTH2F, {{etaAxis}, {pFineAxis}}); + hpTVsEtaPos[i] = registryDeDx.add(CentpTPos[i].data(), "pT vs eta", HistType::kTH2F, {{etaAxis}, {pTFineAxis}}); + hpTVsEtaNeg[i] = registryDeDx.add(CentpTNeg[i].data(), "pT vs eta", HistType::kTH2F, {{etaAxis}, {pTFineAxis}}); } // Invariant Mass @@ -1704,12 +1720,20 @@ struct DedxPidAnalysis { hDedxVsMomentumVsCentPos[centIndex]->Fill(signedP, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); hDedxVspTMomentumVsCent[centIndex]->Fill(signedpT, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); hDedxVspTMomentumVsCent[10]->Fill(signedpT, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); + hMomentumVsEtaPos[centIndex]->Fill(trk.eta(), signedP); + hMomentumVsEtaPos[10]->Fill(trk.eta(), signedP); + hpTVsEtaPos[centIndex]->Fill(trk.eta(), signedpT); + hpTVsEtaPos[10]->Fill(trk.eta(), signedpT); } else { registryDeDx.fill(HIST(DedxvsMomentumNeg[0]), std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); registryDeDx.fill(HIST("heta_vs_pt_vs_p_all_Neg"), trk.eta(), trk.pt(), trk.p()); hDedxVsMomentumVsCentNeg[centIndex]->Fill(std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); hDedxVspTMomentumVsCent[centIndex]->Fill(std::abs(signedpT), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); hDedxVspTMomentumVsCent[10]->Fill(std::abs(signedpT), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); + hMomentumVsEtaNeg[centIndex]->Fill(trk.eta(), std::abs(signedP)); + hMomentumVsEtaNeg[10]->Fill(trk.eta(), std::abs(signedP)); + hpTVsEtaNeg[centIndex]->Fill(trk.eta(), std::abs(signedpT)); + hpTVsEtaNeg[10]->Fill(trk.eta(), std::abs(signedpT)); } } } diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx index 70c1a2fd46b..b43f8b1895f 100644 --- a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -69,6 +69,7 @@ struct MultiplicityPt { static constexpr int MultBinMax = 200; static constexpr int RecMultBinMax = 100; static constexpr int ParticlesType = 4; + static constexpr int ResponseMatrixTypes = 7; enum INELCutSelection : int { INEL = 0, @@ -116,6 +117,9 @@ struct MultiplicityPt { // Histogram names for V0s dE/dx analysis static constexpr std::string_view DedxvsMomentumPos[ParticlesType] = {"dEdx_vs_Momentum_all_Pos", "dEdx_vs_Momentum_Pi_v0_Pos", "dEdx_vs_Momentum_Pr_v0_Pos", "dEdx_vs_Momentum_El_v0_Pos"}; static constexpr std::string_view DedxvsMomentumNeg[ParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; + + static constexpr std::string_view EtavspvspTPosPart[ResponseMatrixTypes] = {"heta_vs_pt_vs_p_all_Pos", "heta_vs_pt_vs_p_all_Pos_Pri", "heta_vs_pt_vs_p_all_Pos_Pri_MC", "heta_vs_pt_vs_p_all_Pos_Pri_MC_Part", "heta_vs_pt_vs_p_Pi_Pos", "heta_vs_pt_vs_p_K_Pos", "heta_vs_pt_vs_p_Pr_Pos"}; + static constexpr std::string_view EtavspvspTNegPart[ResponseMatrixTypes] = {"heta_vs_pt_vs_p_all_Neg", "heta_vs_pt_vs_p_all_Neg_Pri", "heta_vs_pt_vs_p_all_Neg_Pri_MC", "heta_vs_pt_vs_p_all_Neg_Pri_MC_Part", "heta_vs_pt_vs_p_Pi_Neg", "heta_vs_pt_vs_p_K_Neg", "heta_vs_pt_vs_p_Pr_Neg"}; // Particle fractions histograms static constexpr std::string_view ParticleFractionsVsMomentumPos[ParticlesType + 1] = {"hFractionVsMomentum_Pion_Pos", "hFractionVsMomentum_Kaon_Pos", "hFractionVsMomentum_Proton_Pos", "hFractionVsMomentum_Electron_Pos", "hFractionVsMomentum_Muon_Pos"}; @@ -482,6 +486,15 @@ void MultiplicityPt::init(InitContext const&) "dE/dx vs Momentum Negative", HistType::kTH3F, {{pAxis}, {dedxAxis}, {etaAxis}}); } + // pt vs p + for (int i = 0; i < ResponseMatrixTypes; ++i) { + ue.add(("ResponseMatrix/" + std::string(EtavspvspTPosPart[i])).c_str(), + "eta vs pT vs p Positive", HistType::kTH3F, + {{etaAxis}, {ptAxis}, {pAxis}}); + ue.add(("ResponseMatrix/" + std::string(EtavspvspTNegPart[i])).c_str(), + "eta vs pT vs p Negative", HistType::kTH3F, + {{etaAxis}, {ptAxis}, {pAxis}}); + } // ===== Particle Fractions as function of p and pT ===== ue.add("ParticleFractions/hTotalCountsVsMomentumPos", "Total counts vs momentum;#it{p} (GeV/#it{c});Counts", HistType::kTH2D, {{etaAxis}, {pAxis}}); @@ -499,13 +512,6 @@ void MultiplicityPt::init(InitContext const&) ue.add(("ParticleFractions/" + std::string(ParticleFractionsVsPtNeg[i])).c_str(), "Particle fraction vs pT", HistType::kTH2D, {{etaAxis}, {ptAxis}}); } - // pt vs p - ue.add( - "heta_vs_pt_vs_p_all_Neg", "eta_vs_pT_vs_p", HistType::kTH3F, - {{etaAxis}, {ptAxis}, {pAxis}}); - ue.add( - "heta_vs_pt_vs_p_all_Pos", "eta_vs_pT_vs_p", HistType::kTH3F, - {{etaAxis}, {ptAxis}, {pAxis}}); LOG(info) << "=== Initialization complete ==="; } @@ -754,24 +760,41 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, // dedx for all particles if (charge > 0) { ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_all_Pos"), momentum, tpcSignal, eta); - ue.fill(HIST("heta_vs_pt_vs_p_all_Pos"), eta, track.pt(), momentum); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Pos"), eta, track.pt(), momentum); } else { ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_all_Neg"), momentum, tpcSignal, eta); - ue.fill(HIST("heta_vs_pt_vs_p_all_Neg"), eta, track.pt(), momentum); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Neg"), eta, track.pt(), momentum); + } + + if (track.mcParticle().isPhysicalPrimary()) { + if (charge > 0) { + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Pos_Pri"), eta, track.pt(), momentum); + } else { + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Neg_Pri"), eta, track.pt(), momentum); + } } if (track.has_mcParticle()) { const auto& particle = track.mcParticle(); int pdgCode = std::abs(particle.pdgCode()); + if (particle.isPhysicalPrimary()) { + if (charge > 0) { + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Pos_Pri_MC"), eta, track.pt(), momentum); + } else { + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Neg_Pri_MC"), eta, track.pt(), momentum); + } + } if (pdgCode == PDG_t::kPiPlus || pdgCode == PDG_t::kKPlus || pdgCode == PDG_t::kProton || pdgCode == PDG_t::kElectron || pdgCode == PDG_t::kMuonPlus) { if (particle.isPhysicalPrimary()) { // Fill total counts for fractions if (charge > 0) { ue.fill(HIST("ParticleFractions/hTotalCountsVsMomentumPos"), eta, momentum); ue.fill(HIST("ParticleFractions/hTotalCountsVsPtPos"), eta, track.pt()); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Pos_Pri_MC_Part"), eta, track.pt(), momentum); } else { ue.fill(HIST("ParticleFractions/hTotalCountsVsMomentumNeg"), eta, momentum); ue.fill(HIST("ParticleFractions/hTotalCountsVsPtNeg"), eta, track.pt()); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_all_Neg_Pri_MC_Part"), eta, track.pt(), momentum); } } } @@ -785,10 +808,12 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Pion_Pos"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Pion_Pos"), eta, track.pt()); ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pi_v0_Pos"), momentum, tpcSignal, eta); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_Pi_Pos"), eta, track.pt(), momentum); } else { ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Pion_Neg"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Pion_Neg"), eta, track.pt()); ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pi_v0_Neg"), momentum, tpcSignal, eta); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_Pi_Neg"), eta, track.pt(), momentum); } } else { @@ -802,9 +827,11 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, if (charge > 0) { ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Kaon_Pos"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Kaon_Pos"), eta, track.pt()); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_K_Pos"), eta, track.pt(), momentum); } else { ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Kaon_Neg"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Kaon_Neg"), eta, track.pt()); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_K_Neg"), eta, track.pt(), momentum); } } else { ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); @@ -818,10 +845,12 @@ void MultiplicityPt::processMC(TrackTableMC const& tracks, ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Proton_Pos"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Proton_Pos"), eta, track.pt()); ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pr_v0_Pos"), momentum, tpcSignal, eta); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_Pr_Pos"), eta, track.pt(), momentum); } else { ue.fill(HIST("ParticleFractions/hFractionVsMomentum_Proton_Neg"), eta, momentum); ue.fill(HIST("ParticleFractions/hFractionVsPt_Proton_Neg"), eta, track.pt()); ue.fill(HIST("DedxVsMomentum/dEdx_vs_Momentum_Pr_v0_Neg"), momentum, tpcSignal, eta); + ue.fill(HIST("ResponseMatrix/heta_vs_pt_vs_p_Pr_Neg"), eta, track.pt(), momentum); } } else { ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); From f0899070b31f059b0e04f3060411b8caceff4349 Mon Sep 17 00:00:00 2001 From: Giovanni Malfattore <89481844+giovannimalfattore@users.noreply.github.com> Date: Wed, 3 Jun 2026 08:33:35 +0200 Subject: [PATCH 402/449] [PWGLF] NucleiTask - Add INELgt0 and INELgt1 checks on data model (#16435) --- PWGLF/DataModel/LFNucleiTables.h | 184 +++++++++--------- PWGLF/TableProducer/Nuspex/CMakeLists.txt | 2 +- ...atorNuclei.cxx => lfTreeCreatorNuclei.cxx} | 52 ++--- PWGLF/Tasks/Nuspex/CMakeLists.txt | 2 +- ...{LFNucleiBATask.cxx => lfNucleiBATask.cxx} | 130 ++++++++----- 5 files changed, 197 insertions(+), 173 deletions(-) rename PWGLF/TableProducer/Nuspex/{LFTreeCreatorNuclei.cxx => lfTreeCreatorNuclei.cxx} (89%) rename PWGLF/Tasks/Nuspex/{LFNucleiBATask.cxx => lfNucleiBATask.cxx} (99%) diff --git a/PWGLF/DataModel/LFNucleiTables.h b/PWGLF/DataModel/LFNucleiTables.h index f74d3b8ed9d..03366fbd0e6 100644 --- a/PWGLF/DataModel/LFNucleiTables.h +++ b/PWGLF/DataModel/LFNucleiTables.h @@ -33,7 +33,12 @@ DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(CentFV0M, centFV0M, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); -DECLARE_SOA_DYNAMIC_COLUMN(Selection_Bit, selection_bit, //! Dummy +DECLARE_SOA_COLUMN(MultNTracksPVeta1, multNTracksPVeta1, int); +DECLARE_SOA_DYNAMIC_COLUMN(IsInelGt0, isInelGt0, // is INEL > 0 + [](int multPveta1) -> bool { return multPveta1 > 0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsInelGt1, isInelGt1, // is INEL > 1 + [](int multPveta1) -> bool { return multPveta1 > 1; }); +DECLARE_SOA_DYNAMIC_COLUMN(Selection_bit, selection_bit, // o2-linter: disable=name/o2-column (temporary fix) [](o2::aod::evsel::EventSelectionFlags /*v*/) -> bool { return true; }); } // namespace fullEvent DECLARE_SOA_TABLE(LfNuclEvents, "AOD", "LFNUCLEvent", @@ -44,66 +49,69 @@ DECLARE_SOA_TABLE(LfNuclEvents, "AOD", "LFNUCLEvent", collision::PosZ, fullEvent::CentFV0M, fullEvent::CentFT0M, + fullEvent::MultNTracksPVeta1, + fullEvent::IsInelGt0, + fullEvent::IsInelGt1, fullEvent::IsEventReject, fullEvent::RunNumber, - fullEvent::Selection_Bit<>); + fullEvent::Selection_bit<>); using LfNuclEvent = LfNuclEvents::iterator; namespace full { DECLARE_SOA_INDEX_COLUMN(LfNuclEvent, lfNuclEvent); DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * cosh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Sign, sign, int16_t); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, [](float pt, float eta, float mass) -> float { - const auto p = pt * cosh(eta); - const auto pz = pt * sinh(eta); - const auto energy = sqrt(p * p + mass * mass); - return 0.5f * log((energy + pz) / (energy - pz)); + const auto p = pt * std::cosh(eta); + const auto pz = pt * std::sinh(eta); + const auto energy = std::sqrt(p * p + mass * mass); + return 0.5f * std::log((energy + pz) / (energy - pz)); }); // ITS -DECLARE_SOA_COLUMN(ITSClusterSizes, itsClusterSizes, uint32_t); //! ITS cluster sizes per layer +DECLARE_SOA_COLUMN(ItsClusterSizes, itsClusterSizes, uint32_t); //! ITS cluster sizes per layer // TPC -DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); -DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNSigmaKa, float); -DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); -DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); -DECLARE_SOA_COLUMN(TPCNSigmaTr, tpcNSigmaTr, float); -DECLARE_SOA_COLUMN(TPCNSigmaHe, tpcNSigmaHe, float); -DECLARE_SOA_COLUMN(TPCNSigmaAl, tpcNSigmaAl, float); +DECLARE_SOA_COLUMN(TpcNSigmaPi, tpcNSigmaPi, float); +DECLARE_SOA_COLUMN(TpcNSigmaKa, tpcNSigmaKa, float); +DECLARE_SOA_COLUMN(TpcNSigmaPr, tpcNSigmaPr, float); +DECLARE_SOA_COLUMN(TpcNSigmaDe, tpcNSigmaDe, float); +DECLARE_SOA_COLUMN(TpcNSigmaTr, tpcNSigmaTr, float); +DECLARE_SOA_COLUMN(TpcNSigmaHe, tpcNSigmaHe, float); +DECLARE_SOA_COLUMN(TpcNSigmaAl, tpcNSigmaAl, float); // TOF -DECLARE_SOA_COLUMN(TOFNSigmaPi, tofNSigmaPi, float); -DECLARE_SOA_COLUMN(TOFNSigmaKa, tofNSigmaKa, float); -DECLARE_SOA_COLUMN(TOFNSigmaPr, tofNSigmaPr, float); -DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); -DECLARE_SOA_COLUMN(TOFNSigmaTr, tofNSigmaTr, float); -DECLARE_SOA_COLUMN(TOFNSigmaHe, tofNSigmaHe, float); -DECLARE_SOA_COLUMN(TOFNSigmaAl, tofNSigmaAl, float); -DECLARE_SOA_COLUMN(TPCExpSignalDiffPr, tpcExpSignalDiffPr, float); -DECLARE_SOA_COLUMN(TPCExpSignalDiffDe, tpcExpSignalDiffDe, float); -DECLARE_SOA_COLUMN(TPCExpSignalDiffHe, tpcExpSignalDiffHe, float); -DECLARE_SOA_COLUMN(TOFExpSignalDiffPr, tofExpSignalDiffPr, float); -DECLARE_SOA_COLUMN(TOFExpSignalDiffDe, tofExpSignalDiffDe, float); -DECLARE_SOA_COLUMN(TOFExpSignalDiffHe, tofExpSignalDiffHe, float); +DECLARE_SOA_COLUMN(TofNSigmaPi, tofNSigmaPi, float); +DECLARE_SOA_COLUMN(TofNSigmaKa, tofNSigmaKa, float); +DECLARE_SOA_COLUMN(TofNSigmaPr, tofNSigmaPr, float); +DECLARE_SOA_COLUMN(TofNSigmaDe, tofNSigmaDe, float); +DECLARE_SOA_COLUMN(TofNSigmaTr, tofNSigmaTr, float); +DECLARE_SOA_COLUMN(TofNSigmaHe, tofNSigmaHe, float); +DECLARE_SOA_COLUMN(TofNSigmaAl, tofNSigmaAl, float); +DECLARE_SOA_COLUMN(TpcExpSignalDiffPr, tpcExpSignalDiffPr, float); +DECLARE_SOA_COLUMN(TpcExpSignalDiffDe, tpcExpSignalDiffDe, float); +DECLARE_SOA_COLUMN(TpcExpSignalDiffHe, tpcExpSignalDiffHe, float); +DECLARE_SOA_COLUMN(TofExpSignalDiffPr, tofExpSignalDiffPr, float); +DECLARE_SOA_COLUMN(TofExpSignalDiffDe, tofExpSignalDiffDe, float); +DECLARE_SOA_COLUMN(TofExpSignalDiffHe, tofExpSignalDiffHe, float); DECLARE_SOA_COLUMN(IsEvTimeTOF, isEvTimeTOF, bool); DECLARE_SOA_COLUMN(IsEvTimeT0AC, isEvTimeT0AC, bool); DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); DECLARE_SOA_COLUMN(HasTRD, hasTRD, bool); DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); -DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); -DECLARE_SOA_COLUMN(TOFExpMom, tofExpMom, float); -DECLARE_SOA_COLUMN(TPCSignal, tpcSignal, float); +DECLARE_SOA_COLUMN(TpcInnerParam, tpcInnerParam, float); +DECLARE_SOA_COLUMN(TofExpMom, tofExpMom, float); +DECLARE_SOA_COLUMN(TpcSignal, tpcSignal, float); DECLARE_SOA_COLUMN(Beta, beta, float); // TPC and ITS QA -DECLARE_SOA_COLUMN(PIDForTracking, pidForTracking, uint8_t); -DECLARE_SOA_COLUMN(ITSNCls, itsNCls, int16_t); -DECLARE_SOA_COLUMN(TPCChi2Ncl, tpcChi2NCl, float); -DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, float); +DECLARE_SOA_COLUMN(PidForTracking, pidForTracking, uint8_t); +DECLARE_SOA_COLUMN(ItsNCls, itsNCls, int16_t); +DECLARE_SOA_COLUMN(TpcChi2NCl, tpcChi2NCl, float); +DECLARE_SOA_COLUMN(ItsChi2NCl, itsChi2NCl, float); DECLARE_SOA_COLUMN(TpcPassed, tpcPassed, bool); DECLARE_SOA_COLUMN(ItsPassed, itsPassed, bool); DECLARE_SOA_COLUMN(FakeHitsFlag, fakeHitsFlag, bool); @@ -116,79 +124,71 @@ DECLARE_SOA_COLUMN(GetProcess, getProcess, int); } // namespace full namespace dummy { -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi, tpcNSigmaPi, +DECLARE_SOA_DYNAMIC_COLUMN(TpcNSigmaPi, tpcNSigmaPi, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa, tpcNSigmaKa, +DECLARE_SOA_DYNAMIC_COLUMN(TpcNSigmaKa, tpcNSigmaKa, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr, tpcNSigmaPr, +DECLARE_SOA_DYNAMIC_COLUMN(TpcNSigmaPr, tpcNSigmaPr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaTr, tpcNSigmaTr, +DECLARE_SOA_DYNAMIC_COLUMN(TpcNSigmaTr, tpcNSigmaTr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaAl, tpcNSigmaAl, +DECLARE_SOA_DYNAMIC_COLUMN(TpcNSigmaAl, tpcNSigmaAl, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi, tofNSigmaPi, +DECLARE_SOA_DYNAMIC_COLUMN(TofNSigmaPi, tofNSigmaPi, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa, tofNSigmaKa, +DECLARE_SOA_DYNAMIC_COLUMN(TofNSigmaKa, tofNSigmaKa, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr, tofNSigmaPr, +DECLARE_SOA_DYNAMIC_COLUMN(TofNSigmaPr, tofNSigmaPr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaTr, tofNSigmaTr, +DECLARE_SOA_DYNAMIC_COLUMN(TofNSigmaTr, tofNSigmaTr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaAl, tofNSigmaAl, +DECLARE_SOA_DYNAMIC_COLUMN(TofNSigmaAl, tofNSigmaAl, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffPr, tpcExpSignalDiffPr, +DECLARE_SOA_DYNAMIC_COLUMN(TpcExpSignalDiffPr, tpcExpSignalDiffPr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffDe, tpcExpSignalDiffDe, +DECLARE_SOA_DYNAMIC_COLUMN(TpcExpSignalDiffDe, tpcExpSignalDiffDe, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffHe, tpcExpSignalDiffHe, +DECLARE_SOA_DYNAMIC_COLUMN(TpcExpSignalDiffHe, tpcExpSignalDiffHe, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffPr, tofExpSignalDiffPr, +DECLARE_SOA_DYNAMIC_COLUMN(TofExpSignalDiffPr, tofExpSignalDiffPr, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffDe, tofExpSignalDiffDe, +DECLARE_SOA_DYNAMIC_COLUMN(TofExpSignalDiffDe, tofExpSignalDiffDe, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffHe, tofExpSignalDiffHe, +DECLARE_SOA_DYNAMIC_COLUMN(TofExpSignalDiffHe, tofExpSignalDiffHe, [](bool /*b*/) -> float { return 0.f; }); -DECLARE_SOA_DYNAMIC_COLUMN(TOFExpMom, tofExpMom, +DECLARE_SOA_DYNAMIC_COLUMN(TofExpMom, tofExpMom, [](bool /*b*/) -> float { return 0.f; }); } // namespace dummy -/* -namespace fullMC -{ -DECLARE_SOA_INDEX_COLUMN(LfNuclEvent, lfCandNucleusFullEvent); -DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); -} -*/ - DECLARE_SOA_TABLE(LfCandNucleus, "AOD", "LFNUCL", o2::soa::Index<>, full::LfNuclEventId, full::DcaXY, full::DcaZ, - full::TPCNSigmaDe, full::TPCNSigmaHe, - full::TOFNSigmaDe, full::TOFNSigmaHe, + full::TpcNSigmaDe, full::TpcNSigmaHe, + full::TofNSigmaDe, full::TofNSigmaHe, full::IsEvTimeTOF, full::IsEvTimeT0AC, full::HasTOF, full::HasTRD, - full::TPCInnerParam, + full::TpcInnerParam, full::Beta, - full::PIDForTracking, - full::TPCSignal, + full::PidForTracking, + full::TpcSignal, full::Pt, full::Eta, full::Phi, full::Sign, - full::ITSNCls, + full::ItsNCls, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, - full::TPCChi2Ncl, - full::ITSChi2NCl, + full::TpcChi2NCl, + full::ItsChi2NCl, track::ITSClusterMap, full::IsPVContributor, full::P, full::Rapidity, - full::ITSClusterSizes, + full::ItsClusterSizes, track::TPCNClsFound, track::TPCNClsCrossedRows, track::TPCCrossedRowsOverFindableCls, @@ -197,37 +197,37 @@ DECLARE_SOA_TABLE_VERSIONED(LfCandNucleusDummy, "AOD", "LFNUCL", 1, o2::soa::Index<>, full::LfNuclEventId, full::DcaXY, full::DcaZ, - full::TPCNSigmaDe, full::TPCNSigmaHe, - full::TOFNSigmaDe, full::TOFNSigmaHe, + full::TpcNSigmaDe, full::TpcNSigmaHe, + full::TofNSigmaDe, full::TofNSigmaHe, full::IsEvTimeTOF, full::IsEvTimeT0AC, full::HasTOF, full::HasTRD, - full::TPCInnerParam, + full::TpcInnerParam, full::Beta, - full::PIDForTracking, - full::TPCSignal, + full::PidForTracking, + full::TpcSignal, full::Pt, full::Eta, full::Phi, full::Sign, - full::ITSNCls, + full::ItsNCls, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, - full::TPCChi2Ncl, - full::ITSChi2NCl, + full::TpcChi2NCl, + full::ItsChi2NCl, track::ITSClusterMap, full::IsPVContributor, full::P, - full::ITSClusterSizes, - dummy::TPCNSigmaPi, dummy::TPCNSigmaKa, dummy::TPCNSigmaPr, - dummy::TPCNSigmaTr, dummy::TPCNSigmaAl, - dummy::TOFNSigmaPi, dummy::TOFNSigmaKa, dummy::TOFNSigmaPr, - dummy::TOFNSigmaTr, dummy::TOFNSigmaAl, - dummy::TPCExpSignalDiffPr, dummy::TPCExpSignalDiffDe, dummy::TPCExpSignalDiffHe, - dummy::TOFExpSignalDiffPr, dummy::TOFExpSignalDiffDe, dummy::TOFExpSignalDiffHe, - dummy::TOFExpMom, + full::ItsClusterSizes, + dummy::TpcNSigmaPi, dummy::TpcNSigmaKa, dummy::TpcNSigmaPr, + dummy::TpcNSigmaTr, dummy::TpcNSigmaAl, + dummy::TofNSigmaPi, dummy::TofNSigmaKa, dummy::TofNSigmaPr, + dummy::TofNSigmaTr, dummy::TofNSigmaAl, + dummy::TpcExpSignalDiffPr, dummy::TpcExpSignalDiffDe, dummy::TpcExpSignalDiffHe, + dummy::TofExpSignalDiffPr, dummy::TofExpSignalDiffDe, dummy::TofExpSignalDiffHe, + dummy::TofExpMom, full::Rapidity, track::TPCNClsFound, track::TPCNClsCrossedRows, @@ -235,13 +235,13 @@ DECLARE_SOA_TABLE_VERSIONED(LfCandNucleusDummy, "AOD", "LFNUCL", 1, track::TPCFoundOverFindableCls); DECLARE_SOA_TABLE(LfCandNucleusExtra, "AOD", "LFNUCLEXTRA", - full::TPCNSigmaPi, full::TPCNSigmaKa, full::TPCNSigmaPr, - full::TPCNSigmaTr, full::TPCNSigmaAl, - full::TOFNSigmaPi, full::TOFNSigmaKa, full::TOFNSigmaPr, - full::TOFNSigmaTr, full::TOFNSigmaAl, - full::TPCExpSignalDiffPr, full::TPCExpSignalDiffDe, full::TPCExpSignalDiffHe, - full::TOFExpSignalDiffPr, full::TOFExpSignalDiffDe, full::TOFExpSignalDiffHe, - full::TOFExpMom); + full::TpcNSigmaPi, full::TpcNSigmaKa, full::TpcNSigmaPr, + full::TpcNSigmaTr, full::TpcNSigmaAl, + full::TofNSigmaPi, full::TofNSigmaKa, full::TofNSigmaPr, + full::TofNSigmaTr, full::TofNSigmaAl, + full::TpcExpSignalDiffPr, full::TpcExpSignalDiffDe, full::TpcExpSignalDiffHe, + full::TofExpSignalDiffPr, full::TofExpSignalDiffDe, full::TofExpSignalDiffHe, + full::TofExpMom); DECLARE_SOA_TABLE(LfCandNucleusMC, "AOD", "LFNUCLMC", mcparticle::PdgCode, diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index 40ac3c39879..1851643ae9a 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -30,7 +30,7 @@ o2physics_add_dpl_workflow(lnn-reco-task COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(nucleustreecreator - SOURCES LFTreeCreatorNuclei.cxx + SOURCES lfTreeCreatorNuclei.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx b/PWGLF/TableProducer/Nuspex/lfTreeCreatorNuclei.cxx similarity index 89% rename from PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx rename to PWGLF/TableProducer/Nuspex/lfTreeCreatorNuclei.cxx index 4a255202ea5..238ab1a0afb 100644 --- a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx +++ b/PWGLF/TableProducer/Nuspex/lfTreeCreatorNuclei.cxx @@ -10,22 +10,23 @@ // or submit itself to any jurisdiction. /// -/// \file LFTreeCreatorNuclei.cxx +/// \file lfTreeCreatorNuclei.cxx /// \brief Writer of the nuclei candidates in the form of flat tables to be stored in TTrees. /// Intended for debug or for the local optimization of analysis on small samples. /// In this file are defined and filled the output tables /// /// \author Nicolò Jacazio and Francesca Bellini -/// #include "PWGLF/DataModel/LFNucleiTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -92,7 +93,7 @@ struct LfTreeCreatorNuclei { Configurable cfgHighCutVertex{"cfgHighCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgLowCutVertex{"cfgLowCutVertex", -10.0f, "Accepted z-vertex range"}; Configurable useSel8{"useSel8", true, "Use Sel8 for run3 Event Selection"}; - Configurable TVXtrigger{"TVXtrigger", false, "Use TVX for Event Selection (default w/ Sel8)"}; + Configurable useTVXtrigger{"useTVXtrigger", false, "Use TVX for Event Selection (default w/ Sel8)"}; Configurable removeTFBorder{"removeTFBorder", false, "Remove TimeFrame border (default w/ Sel8)"}; Configurable removeITSROFBorder{"removeITSROFBorder", false, "Remove ITS Read-Out Frame border (default w/ Sel8)"}; @@ -113,12 +114,12 @@ struct LfTreeCreatorNuclei { Filter collisionFilter = (aod::collision::posZ < cfgHighCutVertex && aod::collision::posZ > cfgLowCutVertex); Filter etaFilter = (nabs(aod::track::eta) < cfgCutEta); - Filter trackFilter = (trackSelType.value == 0 && requireGlobalTrackWoDCAInFilter()) || - (trackSelType.value == 1 && requireGlobalTrackInFilter()) || - (trackSelType.value == 2) || - (trackSelType.value == 3); - Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); - using EventCandidates = soa::Join; + Filter trackFilter = (trackSelType.value == 0 && requireGlobalTrackWoDCAInFilter()) || // o2-linter: disable=magic-number (filters) + (trackSelType.value == 1 && requireGlobalTrackInFilter()) || // o2-linter: disable=magic-number (filters) + (trackSelType.value == 2) || // o2-linter: disable=magic-number (filters) + (trackSelType.value == 3); // o2-linter: disable=magic-number (filters) + Filter dcaFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + using EventCandidates = soa::Join; using TrackCandidates = soa::Join ptcutHigh.value)) { continue; } - if ((TMath::Abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (TMath::Abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { + if ((std::abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (std::abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { continue; } out = kTRUE; @@ -202,6 +203,7 @@ struct LfTreeCreatorNuclei { collision.posZ(), collision.centFV0A(), collision.centFT0M(), + collision.multNTracksPVeta1(), collision.sel8(), collision.bc().runNumber()); @@ -211,26 +213,26 @@ struct LfTreeCreatorNuclei { if constexpr (isMC) { tableCandidateMC.reserve(tracks.size()); } - for (auto& track : tracks) { + for (const auto& track : tracks) { if (track.itsNClsInnerBarrel() < nITSInnerBarrelHits) { continue; } - if (trackSelType.value == 2) { // custom track selection mode + if (trackSelType.value == 2) { // custom track selection mode // o2-linter: disable=magic-number (filters) if (!customTrackSelection.IsSelected(track)) { continue; } } - if (trackSelType.value == 3) { // Filtering mode + if (trackSelType.value == 3) { // Filtering mode // o2-linter: disable=magic-number (filters) if (!track.hasTPC()) { continue; } - if (track.tpcNClsCrossedRows() < 90) { + if (track.tpcNClsCrossedRows() < 90) { // o2-linter: disable=magic-number (filters) continue; } if ((track.pt() < ptcutLow.value) || (track.pt() > ptcutHigh.value)) { continue; } - if ((TMath::Abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (TMath::Abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { + if ((std::abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (std::abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { continue; } } @@ -250,7 +252,6 @@ struct LfTreeCreatorNuclei { track.tpcSignal(), track.pt(), track.eta(), track.phi(), track.sign(), - track.itsClusterSizes(), track.itsNCls(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), @@ -258,7 +259,8 @@ struct LfTreeCreatorNuclei { track.tpcChi2NCl(), track.itsChi2NCl(), track.itsClusterMap(), - track.isPVContributor()); + track.isPVContributor(), + track.itsClusterSizes()); tableCandidateExtra( track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), @@ -274,7 +276,7 @@ struct LfTreeCreatorNuclei { bool itsPassed = isITStrack(track); bool tpcPassed = isTPCtrack(track); bool hasFakeHit = false; - for (int i = 0; i < 10; i++) { // From ITS to TPC + for (int i = 0; i < 10; i++) { // From ITS to TPC // o2-linter: disable=magic-number (fake hit loop) if (track.mcMask() & 1 << i) { hasFakeHit = true; break; @@ -310,7 +312,7 @@ struct LfTreeCreatorNuclei { hEvents.fill(HIST("eventSelection"), 0); if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) { - if (TVXtrigger) + if (useTVXtrigger) continue; } else { hEvents.fill(HIST("eventSelection"), 1); @@ -346,11 +348,11 @@ struct LfTreeCreatorNuclei { hEvents.fill(HIST("eventSelection"), 6); // Fill the norm. column with good events with |z| < 10 cm before skimming - if (collision.posZ() < 10 && collision.posZ() > -10) { + if (collision.posZ() < cfgHighCutVertex && collision.posZ() > cfgLowCutVertex) { hEvents.fill(HIST("eventSelection"), 7); } - if (doSkim && (trackSelType.value == 3) && !checkQuality(collision, tracksInCollision)) + if (doSkim && (trackSelType.value == 3) && !checkQuality(collision, tracksInCollision)) // o2-linter: disable=magic-number (filters) continue; fillForOneEvent(collision, tracksInCollision); hEvents.fill(HIST("eventSelection"), 8); @@ -368,7 +370,7 @@ struct LfTreeCreatorNuclei { hEvents.fill(HIST("eventSelection"), 0); if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) { - if (TVXtrigger) + if (useTVXtrigger) continue; } else { hEvents.fill(HIST("eventSelection"), 1); @@ -399,7 +401,7 @@ struct LfTreeCreatorNuclei { hEvents.fill(HIST("eventSelection"), 5); // Fill the norm. column with good events with |z| < 10 cm before skimming - if (collision.posZ() < 10 && collision.posZ() > -10) { + if (collision.posZ() < cfgHighCutVertex && collision.posZ() > cfgLowCutVertex) { hEvents.fill(HIST("eventSelection"), 7); } diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index 71a38eb1c9f..91617ea0567 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -10,7 +10,7 @@ # or submit itself to any jurisdiction. o2physics_add_dpl_workflow(nuclei-batask - SOURCES LFNucleiBATask.cxx + SOURCES lfNucleiBATask.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/lfNucleiBATask.cxx similarity index 99% rename from PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx rename to PWGLF/Tasks/Nuspex/lfNucleiBATask.cxx index 17173fe5276..8e01eb0ca50 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/lfNucleiBATask.cxx @@ -10,12 +10,11 @@ // or submit itself to any jurisdiction. /// -/// \file LFNucleiBATask.cxx +/// \file lfNucleiBATask.cxx /// /// \brief Analysis task for the measurement of the coalescence parameter B2/B3 in pp collisions for (anti)deuteron/(anti)helium-3 /// /// \author Giovanni Malfattore and Rutuparna Rath -/// #include "PWGLF/DataModel/LFNucleiTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" @@ -66,7 +65,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct LFNucleiBATask { +struct lfNucleiBATask { Service ccdb; Service pdgDB; @@ -92,8 +91,8 @@ struct LFNucleiBATask { Configurable enableHe{"enableHe", true, "Flag to enable helium-3 analysis."}; Configurable enableAl{"enableAl", true, "Flag to enable alpha analysis."}; - Configurable enableTrackingEff{"enableTrackingEff", 0, "Flag to enable tracking efficiency histos."}; - Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable enableTrackingEff{"enableTrackingEff", false, "Flag to enable tracking efficiency histos."}; + Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; // o2-linter: disable=name/configurable (fast fix) // Set the triggered events skimming scheme struct : ConfigurableGroup { @@ -238,14 +237,15 @@ struct LFNucleiBATask { Configurable enablePtShiftPID{"enablePtShiftPID", true, "Flag to enable wrong PID in tracking pT correction shift"}; Configurable> parShiftPtPID{"parShiftPtPID", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for helium3-Pt wrong pid shift (if enabled)."}; + Configurable cfgPtShiftPID{"cfgPtShiftPID", 1.25f, "Default upper limit for PID pt-shift correction"}; Configurable enableCentrality{"enableCentrality", true, "Flag to enable centrality 3D histos)"}; // ITS to TPC - Fake hit loop - static constexpr int kFakeLoop = 10; // Fixed O2Linter error + static constexpr int IntFakeLoop = 10; // Fixed O2Linter error // TPC low/high momentum range - static constexpr float kCfgTpcClasses[] = {0.5f, 0.1f}; - static constexpr float kCfgKaonCut = 5.f; + static constexpr float CfgTpcClasses[] = {0.5f, 0.1f}; + static constexpr float CfgKaonCut = 5.f; // PDG codes and masses used in this analysis static constexpr int PDGPion = PDG_t::kPiPlus; @@ -263,7 +263,7 @@ struct LFNucleiBATask { static constexpr float MassAlphaVal = o2::constants::physics::MassAlpha; // PDG of Mothers - static constexpr int kPdgMotherList[] = { + static constexpr int PdgMotherList[] = { PDG_t::kPiPlus, PDG_t::kKPlus, PDG_t::kK0Short, @@ -276,9 +276,9 @@ struct LFNucleiBATask { o2::constants::physics::Pdg::kHyperTriton, o2::constants::physics::Pdg::kAlpha}; - static constexpr int kNumMotherList = sizeof(kPdgMotherList) / sizeof(kPdgMotherList[0]); + static constexpr int NumMotherList = sizeof(PdgMotherList) / sizeof(PdgMotherList[0]); - static constexpr const char* kMotherNames[kNumMotherList] = { + static constexpr const char* kMotherNames[NumMotherList] = { "#pi^{+}", "K^{+}", "K^{0}_{S}", @@ -497,7 +497,7 @@ struct LFNucleiBATask { hSkim->GetXaxis()->SetBinLabel(2, "Skimmed events"); if (enableCentrality) { - histos.add("event/eventSelection", "eventSelection", HistType::kTH2D, {{8, -0.5, 7.5}, {binsPercentile, "Centrality FT0M"}}); + histos.add("event/eventSelection", "eventSelection", HistType::kTH2D, {{11, -0.5, 10.5}, {binsPercentile, "Centrality FT0M"}}); auto h2d = histos.get(HIST("event/eventSelection")); if (skimmingOptions.applySkimming) h2d->GetXaxis()->SetBinLabel(1, "Skimmed events"); @@ -511,8 +511,11 @@ struct LFNucleiBATask { h2d->GetXaxis()->SetBinLabel(6, "Sel8 cut"); h2d->GetXaxis()->SetBinLabel(7, "Z-vert Cut"); h2d->GetXaxis()->SetBinLabel(8, "Multiplicity cut"); + h2d->GetXaxis()->SetBinLabel(9, "INEL"); + h2d->GetXaxis()->SetBinLabel(10, "INEL > 0"); + h2d->GetXaxis()->SetBinLabel(11, "INEL > 1"); } else { - histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{8, -0.5, 7.5}}); + histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{11, -0.5, 10.5}}); auto h1d = histos.get(HIST("event/eventSelection")); if (skimmingOptions.applySkimming) h1d->GetXaxis()->SetBinLabel(1, "Skimmed events"); @@ -526,6 +529,9 @@ struct LFNucleiBATask { h1d->GetXaxis()->SetBinLabel(6, "Sel8 cut"); h1d->GetXaxis()->SetBinLabel(7, "Z-vert Cut"); h1d->GetXaxis()->SetBinLabel(8, "Multiplicity cut"); + h1d->GetXaxis()->SetBinLabel(9, "INEL"); + h1d->GetXaxis()->SetBinLabel(10, "INEL > 0"); + h1d->GetXaxis()->SetBinLabel(11, "INEL > 1"); } if (enableCentrality) @@ -1078,7 +1084,7 @@ struct LFNucleiBATask { histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTrueMaterial", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hNumMothers", "N mothers per particle; N mothers;counts", HistType::kTH1I, {{7, 1.0, 8.0}}); - histos.add("tracks/proton/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {kNumMotherList + 2, -1.5, static_cast(kNumMotherList) + 0.5}, {150, 0.0, 15.0}}); + histos.add("tracks/proton/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {NumMotherList + 2, -1.5, static_cast(NumMotherList) + 0.5}, {150, 0.0, 15.0}}); std::shared_ptr hTempPr = histos.get(HIST("tracks/proton/dca/before/hMomTrueMaterial")); TH3* hPdgPr = hTempPr.get(); @@ -1090,7 +1096,7 @@ struct LFNucleiBATask { TAxis* ayPdgPr = hPdgPr->GetYaxis(); ayPdgPr->SetBinLabel(1, "undef."); ayPdgPr->SetBinLabel(2, "other"); - for (int i = 0; i < kNumMotherList; i++) { + for (int i = 0; i < NumMotherList; i++) { ayPdgPr->SetBinLabel(i + 3, kMotherNames[i]); } @@ -1150,7 +1156,7 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueMaterial", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/hNumMothers", "N mothers per particle; N mothers;counts", HistType::kTH1I, {{7, 1.0, 8.0}}); - histos.add("tracks/deuteron/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {kNumMotherList + 2, -1.5, static_cast(kNumMotherList) + 0.5}, {150, 0.0, 15.0}}); + histos.add("tracks/deuteron/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {NumMotherList + 2, -1.5, static_cast(NumMotherList) + 0.5}, {150, 0.0, 15.0}}); std::shared_ptr hTempDe = histos.get(HIST("tracks/deuteron/dca/before/hMomTrueMaterial")); TH3* hPdgDe = hTempDe.get(); @@ -1162,7 +1168,7 @@ struct LFNucleiBATask { TAxis* ayPdgDe = hPdgDe->GetYaxis(); ayPdgDe->SetBinLabel(1, "undef."); ayPdgDe->SetBinLabel(2, "other"); - for (int i = 0; i < kNumMotherList; i++) { + for (int i = 0; i < NumMotherList; i++) { ayPdgDe->SetBinLabel(i + 3, kMotherNames[i]); } @@ -1324,7 +1330,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueMaterial", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/hNumMothers", "N mothers per particle; N mothers;counts", HistType::kTH1I, {{7, 1.0, 8.0}}); - histos.add("tracks/helium/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {kNumMotherList + 2, -1.5, static_cast(kNumMotherList) + 0.5}, {150, 0.0, 15.0}}); + histos.add("tracks/helium/dca/before/hMomTrueMaterial", "MC mothers;mother index;mother type; mother #it{p}_{T}", HistType::kTH3F, {{2, -2.0, 2.0}, {NumMotherList + 2, -1.5, static_cast(NumMotherList) + 0.5}, {150, 0.0, 15.0}}); // Fix for getting TH3 pointer std::shared_ptr hTempHe = histos.get(HIST("tracks/helium/dca/before/hMomTrueMaterial")); @@ -1337,7 +1343,7 @@ struct LFNucleiBATask { TAxis* ayPdgHe = hPdgHe->GetYaxis(); ayPdgHe->SetBinLabel(1, "undef."); ayPdgHe->SetBinLabel(2, "other"); - for (int i = 0; i < kNumMotherList; i++) { + for (int i = 0; i < NumMotherList; i++) { ayPdgHe->SetBinLabel(i + 3, kMotherNames[i]); } @@ -2161,7 +2167,7 @@ struct LFNucleiBATask { } // To be optimised if (!doprocessMCGen && !doprocessMCReco && !doprocessMCRecoLfPid && !doprocessMCRecoFiltered && !doprocessMCRecoFilteredLight) { - LOG(info) << "Histograms of LFNucleiBATask:"; + LOG(info) << "Histograms of lfNucleiBATask:"; histos.print(); return; } @@ -2300,7 +2306,7 @@ struct LFNucleiBATask { spectraGen.add("alpha/histGenPtantiAlSec", "generated particles", HistType::kTH1F, {ptAxis}); spectraGen.add("alpha/histSecTransportPtantiAl", "generated particles", HistType::kTH1F, {ptAxis}); } - LOG(info) << "Histograms of LFNucleiBATask:"; + LOG(info) << "Histograms of lfNucleiBATask:"; histos.print(); if (doprocessMCGen) spectraGen.print(); @@ -2405,10 +2411,26 @@ struct LFNucleiBATask { if (enableCentrality && (centFT0M <= cfgMultCutLow || centFT0M > cfgMultCutHigh)) { return; } - if (enableCentrality) + if (enableCentrality) { histos.fill(HIST("event/eventSelection"), 7, centFT0M); - else + histos.fill(HIST("event/eventSelection"), 8, centFT0M); + } else { histos.fill(HIST("event/eventSelection"), 7); + histos.fill(HIST("event/eventSelection"), 8); + } + + if (event.isInelGt0()) { + if (enableCentrality) + histos.fill(HIST("event/eventSelection"), 9, centFT0M); + else + histos.fill(HIST("event/eventSelection"), 9); + } + if (event.isInelGt1()) { + if (enableCentrality) + histos.fill(HIST("event/eventSelection"), 10, centFT0M); + else + histos.fill(HIST("event/eventSelection"), 10); + } float gamma = 0., massTOF = 0., massTOFhe = 0., massTOFantihe = 0., heTPCmomentum = 0.f, antiheTPCmomentum = 0.f, heP = 0.f, antiheP = 0.f, hePt = 0.f, antihePt = 0.f, antiDPt = 0.f, DPt = 0.f; bool isTritonTPCpid = false; @@ -2555,7 +2577,7 @@ struct LFNucleiBATask { } if (enablePtShiftPID && fShiftPtPID) { shiftPtPID = fShiftPtPID->Eval(2 * track.pt()); - if (tritonPID && (track.pt() <= 1.25f)) { + if (tritonPID && (track.pt() <= cfgPtShiftPID)) { hePt = track.pt() - shiftPtPID / 2.f; antihePt = track.pt() - shiftPtPID / 2.f; } @@ -3409,7 +3431,7 @@ struct LFNucleiBATask { } genPt = track.mcParticle().pt(); - for (int i = 0; i < kFakeLoop; i++) { // From ITS to TPC + for (int i = 0; i < IntFakeLoop; i++) { // From ITS to TPC if (track.mcMask() & 1 << i) { hasFakeHit = true; break; @@ -3447,8 +3469,8 @@ struct LFNucleiBATask { int motherSpeciesBin = -1; if (pdgMom != -1) { motherSpeciesBin = 0; - for (int j = 0; j < kNumMotherList; j++) { - if (std::abs(kPdgMotherList[j]) == std::abs(pdgMom)) { + for (int j = 0; j < NumMotherList; j++) { + if (std::abs(PdgMotherList[j]) == std::abs(pdgMom)) { motherSpeciesBin = j + 1; break; } @@ -3544,8 +3566,8 @@ struct LFNucleiBATask { int motherSpeciesBin = -1; if (pdgMom != -1) { motherSpeciesBin = 0; - for (int j = 0; j < kNumMotherList; j++) { - if (std::abs(kPdgMotherList[j]) == std::abs(pdgMom)) { + for (int j = 0; j < NumMotherList; j++) { + if (std::abs(PdgMotherList[j]) == std::abs(pdgMom)) { motherSpeciesBin = j + 1; break; } @@ -3703,8 +3725,8 @@ struct LFNucleiBATask { int motherSpeciesBin = -1; if (pdgMom != -1) { motherSpeciesBin = 0; - for (int j = 0; j < kNumMotherList; j++) { - if (std::abs(kPdgMotherList[j]) == std::abs(pdgMom)) { + for (int j = 0; j < NumMotherList; j++) { + if (std::abs(PdgMotherList[j]) == std::abs(pdgMom)) { motherSpeciesBin = j + 1; break; } @@ -4154,26 +4176,26 @@ struct LFNucleiBATask { debugHistos.fill(HIST("debug/qa/h2TPCncrVsPtPos"), track.tpcInnerParam(), track.tpcNClsCrossedRows()); debugHistos.fill(HIST("debug/qa/h2TPCncrVsTPCsignalPos"), track.tpcSignal(), track.tpcNClsCrossedRows()); - if (track.tpcInnerParam() < kCfgTpcClasses[0]) { + if (track.tpcInnerParam() < CfgTpcClasses[0]) { debugHistos.fill(HIST("debug/qa/h1TPCncrLowPPos"), track.tpcNClsCrossedRows()); } - if ((track.tpcInnerParam() >= kCfgTpcClasses[0]) && (track.tpcInnerParam() < kCfgTpcClasses[1])) { + if ((track.tpcInnerParam() >= CfgTpcClasses[0]) && (track.tpcInnerParam() < CfgTpcClasses[1])) { debugHistos.fill(HIST("debug/qa/h1TPCncrMidPPos"), track.tpcNClsCrossedRows()); } - if (track.tpcInnerParam() >= kCfgTpcClasses[1]) { + if (track.tpcInnerParam() >= CfgTpcClasses[1]) { debugHistos.fill(HIST("debug/qa/h1TPCncrHighPPos"), track.tpcNClsCrossedRows()); } } else { debugHistos.fill(HIST("debug/qa/h2TPCncrVsPtNeg"), track.tpcInnerParam(), track.tpcNClsCrossedRows()); debugHistos.fill(HIST("debug/qa/h2TPCncrVsTPCsignalNeg"), track.tpcSignal(), track.tpcNClsCrossedRows()); - if (track.tpcInnerParam() < kCfgTpcClasses[0]) { + if (track.tpcInnerParam() < CfgTpcClasses[0]) { debugHistos.fill(HIST("debug/qa/h1TPCncrLowPNeg"), track.tpcNClsCrossedRows()); } - if ((track.tpcInnerParam() >= kCfgTpcClasses[0]) && (track.tpcInnerParam() < kCfgTpcClasses[1])) { + if ((track.tpcInnerParam() >= CfgTpcClasses[0]) && (track.tpcInnerParam() < CfgTpcClasses[1])) { debugHistos.fill(HIST("debug/qa/h1TPCncrMidPNeg"), track.tpcNClsCrossedRows()); } - if (track.tpcInnerParam() >= kCfgTpcClasses[1]) { + if (track.tpcInnerParam() >= CfgTpcClasses[1]) { debugHistos.fill(HIST("debug/qa/h1TPCncrHighPNeg"), track.tpcNClsCrossedRows()); } } @@ -4186,7 +4208,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/eff/h2pVsTPCmomentum"), track.tpcInnerParam(), track.p()); if (filterOptions.enableFiltering) { - if (track.tpcNSigmaKa() < kCfgKaonCut) + if (track.tpcNSigmaKa() < CfgKaonCut) continue; } @@ -5178,7 +5200,7 @@ struct LFNucleiBATask { track.passedTPCRefit() && track.hasTPC(); - for (int i = 0; i < kFakeLoop; i++) { // From ITS to TPC + for (int i = 0; i < IntFakeLoop; i++) { // From ITS to TPC if (track.mcMask() & 1 << i) { hasFakeHit = true; break; @@ -6090,7 +6112,7 @@ struct LFNucleiBATask { } } - using EventCandidates = soa::Join; + using EventCandidates = soa::Join; using EventCandidatesMC = soa::Join; using TrackCandidates0 = soa::Join(event, tracks, true /*dummy*/, event.centFT0M()); } - PROCESS_SWITCH(LFNucleiBATask, processData, "process data", true); + PROCESS_SWITCH(lfNucleiBATask, processData, "process data", true); // Process function that runs on the original AO2D void processDataLfPid(EventCandidates::iterator const& event, @@ -6136,7 +6158,7 @@ struct LFNucleiBATask { { fillHistograms(event, tracks, true /*dummy*/, event.centFT0M()); } - PROCESS_SWITCH(LFNucleiBATask, processDataLfPid, "process data with LF PID", false); + PROCESS_SWITCH(lfNucleiBATask, processDataLfPid, "process data with LF PID", false); // Process function that runs on the filtered data void processDataFiltered(o2::aod::LfNuclEvents::iterator const& event, @@ -6147,7 +6169,7 @@ struct LFNucleiBATask { // Takes as input full AO2Ds fillHistograms(event, tracks, true /*dummy*/, event.centFT0M()); } - PROCESS_SWITCH(LFNucleiBATask, processDataFiltered, "process data on the filtered data", false); + PROCESS_SWITCH(lfNucleiBATask, processDataFiltered, "process data on the filtered data", false); void processDataLight(o2::aod::LfNuclEvents::iterator const& event, o2::aod::LfCandNucleusDummy const& tracks, @@ -6157,7 +6179,7 @@ struct LFNucleiBATask { // Takes as input derived trees fillHistograms(event, tracks, true /*dummy*/, event.centFT0M()); } - PROCESS_SWITCH(LFNucleiBATask, processDataLight, "process data on the derived trees", false); + PROCESS_SWITCH(lfNucleiBATask, processDataLight, "process data on the derived trees", false); ///////////// // MC Reco // @@ -6205,7 +6227,7 @@ struct LFNucleiBATask { fillHistograms(event, tracks, mcParticles, mcCentFT0M); } // CLOSING PROCESS MC RECO - PROCESS_SWITCH(LFNucleiBATask, processMCReco, "process mc reco", false); + PROCESS_SWITCH(lfNucleiBATask, processMCReco, "process mc reco", false); // Process function that runs on the original AO2D (for the MC) with the LfPIDcalibration void processMCRecoLfPid(EventCandidatesMC::iterator const& event, @@ -6246,7 +6268,7 @@ struct LFNucleiBATask { fillHistograms(event, tracks, mcParticles, mcCentFT0M); } // CLOSING PROCESS MC RECO - PROCESS_SWITCH(LFNucleiBATask, processMCRecoLfPid, "process mc reco with LfPid", false); + PROCESS_SWITCH(lfNucleiBATask, processMCRecoLfPid, "process mc reco with LfPid", false); // Process function that runs on the original AO2D (for the MC) with the LfPIDcalibration void processMCRecoLfPidEv(EventCandidatesMC const& collisions, @@ -6358,7 +6380,7 @@ struct LFNucleiBATask { } } // CLOSING PROCESS MC RECO - PROCESS_SWITCH(LFNucleiBATask, processMCRecoLfPidEv, "process mc reco with LfPid w/ Event", false); + PROCESS_SWITCH(lfNucleiBATask, processMCRecoLfPidEv, "process mc reco with LfPid w/ Event", false); // Process function that runs on the filtered AO2D (for the MC) void processMCRecoFiltered(o2::aod::LfNuclEvents::iterator const& event, @@ -6367,7 +6389,7 @@ struct LFNucleiBATask { { fillHistograms(event, tracks, true /*dummy*/, event.centFT0M()); } // CLOSING PROCESS MC RECO ON FILTERED DATA - PROCESS_SWITCH(LFNucleiBATask, processMCRecoFiltered, "process mc reco on the filtered data", false); + PROCESS_SWITCH(lfNucleiBATask, processMCRecoFiltered, "process mc reco on the filtered data", false); void processMCRecoFilteredLight(o2::aod::LfNuclEvents::iterator const& event, soa::Join const& tracks, @@ -6375,7 +6397,7 @@ struct LFNucleiBATask { { fillHistograms(event, tracks, true /*dummy*/, event.centFT0M()); } // CLOSING PROCESS MC RECO ON FILTERED DATA - PROCESS_SWITCH(LFNucleiBATask, processMCRecoFilteredLight, "process mc reco on the derived trees", false); + PROCESS_SWITCH(lfNucleiBATask, processMCRecoFilteredLight, "process mc reco on the derived trees", false); //////////// // MC Gen // @@ -6645,7 +6667,7 @@ struct LFNucleiBATask { } } } // Close processMCGen - PROCESS_SWITCH(LFNucleiBATask, processMCGen, "process MC Generated", true); + PROCESS_SWITCH(lfNucleiBATask, processMCGen, "process MC Generated", true); void processEvSgLossMC(soa::Join::iterator const& mcCollision, aod::McParticles const& mcParticles, @@ -6687,7 +6709,7 @@ struct LFNucleiBATask { for (const auto& mcPart : mcParticles) { if (!mcPart.isPhysicalPrimary()) continue; - if (std::abs(mcPart.y()) >= kCfgTpcClasses[0]) + if (std::abs(mcPart.y()) >= CfgTpcClasses[0]) continue; const float pt = mcPart.pt(); @@ -6731,7 +6753,7 @@ struct LFNucleiBATask { } } } - PROCESS_SWITCH(LFNucleiBATask, processEvSgLossMC, "process MC SignLoss", false); + PROCESS_SWITCH(lfNucleiBATask, processEvSgLossMC, "process MC SignLoss", false); // void processMCGen(soa::Join::iterator const& mcCollision, // aod::McParticles const& mcParticles) @@ -6907,10 +6929,10 @@ struct LFNucleiBATask { } } } - PROCESS_SWITCH(LFNucleiBATask, processMCGenLosses, "process MCGen losses", false); + PROCESS_SWITCH(lfNucleiBATask, processMCGenLosses, "process MCGen losses", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From cb62f234e9047fecb7d4d37422a2ee1a0d97b2f8 Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Wed, 3 Jun 2026 09:46:04 +0300 Subject: [PATCH 403/449] [Common] Uppercase for struct definitions (#16504) --- .../TableProducer/eventSelectionService.cxx | 38 ++++++-------- .../eventSelectionServiceRun2.cxx | 36 ++++++------- Common/Tools/EventSelectionModule.h | 52 +++++++++---------- Common/Tools/timestampModule.h | 27 ++++++---- 4 files changed, 73 insertions(+), 80 deletions(-) diff --git a/Common/TableProducer/eventSelectionService.cxx b/Common/TableProducer/eventSelectionService.cxx index e93f3378730..4be5b73b5a5 100644 --- a/Common/TableProducer/eventSelectionService.cxx +++ b/Common/TableProducer/eventSelectionService.cxx @@ -9,16 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file eventSelectionTester.cxx +/// \file eventSelectionService.cxx /// \brief unified, self-configuring event selection task /// \author ALICE -//=============================================================== -// -// Unified, self-configuring event selection task -// -//=============================================================== - #include "Common/Core/MetadataHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/Tools/EventSelectionModule.h" @@ -50,14 +44,14 @@ using BCsWithRun3Matchings = soa::Join; using FullTracks = soa::Join; using FullTracksIU = soa::Join; -struct eventselectionRun2 { - o2::common::timestamp::timestampConfigurables timestampConfigurables; +struct EventselectionRun2 { // o2-linter: disable=name/workflow-file (exception due to metadata-driven topology) + o2::common::timestamp::TimestampConfigurables timestampConfigurables; o2::common::timestamp::TimestampModule timestampMod; - o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; - o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EvselConfigurables evselOpts; o2::common::eventselection::EventSelectionModule evselmodule; Produces timestampTable; /// Table with SOR timestamps produced by the task @@ -75,7 +69,7 @@ struct eventselectionRun2 { // buffering intermediate results for passing std::vector timestamps; - std::vector bcselsbuffer; + std::vector bcselsbuffer; // auxiliary Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); @@ -109,17 +103,17 @@ struct eventselectionRun2 { } }; -struct eventselectionRun3 { - o2::common::timestamp::timestampConfigurables timestampConfigurables; +struct EventselectionRun3 { // o2-linter: disable=name/workflow-file (exception due to metadata-driven topology) + o2::common::timestamp::TimestampConfigurables timestampConfigurables; o2::common::timestamp::TimestampModule timestampMod; - o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; - o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EvselConfigurables evselOpts; o2::common::eventselection::EventSelectionModule evselmodule; - o2::common::eventselection::lumiConfigurables lumiOpts; + o2::common::eventselection::LumiConfigurables lumiOpts; o2::common::eventselection::LumiModule lumimodule; Produces timestampTable; /// Table with SOR timestamps produced by the task @@ -138,7 +132,7 @@ struct eventselectionRun3 { // the best: have readable cursors // this: a stopgap solution to avoid spawning yet another device std::vector timestamps; - std::vector bcselsbuffer; + std::vector bcselsbuffer; // auxiliary Partition pvTracks = ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)); @@ -173,7 +167,7 @@ struct eventselectionRun3 { } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // o2-linter: disable=o2-workflow-options (metadata-driven topology selection) { // Parse the metadata for later too metadataInfo.initMetadata(cfgc); @@ -191,18 +185,18 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOGF(warn, "Metadata info missing or incomplete. Make sure --aod-file is provided at the end of the last workflow and that the AO2D has metadata stored."); LOGF(warn, "Initializing with Run 3 data as default. Please note you will not be able to change settings manually."); LOGF(warn, "You should instead make sure the metadata is read in correctly."); - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } else { LOGF(info, "Metadata successfully read in. Is this Run 3? %i - will self-configure.", isRun3); if (isRun3) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } else { LOGF(warn, "******************************************************************"); LOGF(warn, " Event selection service self-configuring for Run 2."); LOGF(warn, " WARNING: THIS HAS NOT BEEN VALIDATED YET, USE WITH CAUTION"); LOGF(warn, " If this fails, please use event-selection-service-run2 instead."); LOGF(warn, "******************************************************************"); - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } } throw std::runtime_error("Unsupported run type / problem when configuring event selection!"); diff --git a/Common/TableProducer/eventSelectionServiceRun2.cxx b/Common/TableProducer/eventSelectionServiceRun2.cxx index 2af25cb83a0..b291d41ea8e 100644 --- a/Common/TableProducer/eventSelectionServiceRun2.cxx +++ b/Common/TableProducer/eventSelectionServiceRun2.cxx @@ -9,16 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file eventSelectionTester.cxx -/// \brief unified, self-configuring event selection task +/// \file eventSelectionServiceRun2.cxx +/// \brief event selection task for Run 2 /// \author ALICE -//=============================================================== -// -// Unified, self-configuring event selection task -// -//=============================================================== - #include "Common/Core/MetadataHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/Tools/EventSelectionModule.h" @@ -49,17 +43,17 @@ using BCsWithRun3Matchings = soa::Join; using FullTracks = soa::Join; using FullTracksIU = soa::Join; -struct eventselectionRun2 { - o2::common::timestamp::timestampConfigurables timestampConfigurables; +struct EventselectionRun2 { // o2-linter: disable=name/workflow-file (exception due to metadata-driven topology) + o2::common::timestamp::TimestampConfigurables timestampConfigurables; o2::common::timestamp::TimestampModule timestampMod; - o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; - o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EvselConfigurables evselOpts; o2::common::eventselection::EventSelectionModule evselmodule; - Produces timestampTable; /// Table with SOR timestamps produced by the task + Produces timestampTable; // Table with SOR timestamps produced by the task Produces bcsel; Produces evsel; @@ -74,7 +68,7 @@ struct eventselectionRun2 { // buffering intermediate results for passing std::vector timestamps; - std::vector bcselsbuffer; + std::vector bcselsbuffer; // auxiliary Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); @@ -108,17 +102,17 @@ struct eventselectionRun2 { } }; -struct eventselectionRun3 { - o2::common::timestamp::timestampConfigurables timestampConfigurables; +struct EventselectionRun3 { // o2-linter: disable=name/workflow-file (exception due to metadata-driven topology) + o2::common::timestamp::TimestampConfigurables timestampConfigurables; o2::common::timestamp::TimestampModule timestampMod; - o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; - o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EvselConfigurables evselOpts; o2::common::eventselection::EventSelectionModule evselmodule; - o2::common::eventselection::lumiConfigurables lumiOpts; + o2::common::eventselection::LumiConfigurables lumiOpts; o2::common::eventselection::LumiModule lumimodule; Produces timestampTable; /// Table with SOR timestamps produced by the task @@ -137,7 +131,7 @@ struct eventselectionRun3 { // the best: have readable cursors // this: a stopgap solution to avoid spawning yet another device std::vector timestamps; - std::vector bcselsbuffer; + std::vector bcselsbuffer; // auxiliary Partition pvTracks = ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)); @@ -181,5 +175,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) LOGF(info, "To be improved once metadata enabling in defineDataProcessing is worked out."); // force Run 2 mode - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Common/Tools/EventSelectionModule.h b/Common/Tools/EventSelectionModule.h index 5e44ffe226b..eb4108bf6e6 100644 --- a/Common/Tools/EventSelectionModule.h +++ b/Common/Tools/EventSelectionModule.h @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file EventSelectionModule.h -/// \brief Event selection modeule +/// \brief Event selection module /// \author ALICE #ifndef COMMON_TOOLS_EVENTSELECTIONMODULE_H_ @@ -77,7 +77,7 @@ static const int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; // for providing temporary buffer // FIXME ideally cursors could be readable // to avoid duplicate memory allocation but ok -struct bcselEntry { // o2-linter: disable=name/struct (temporary fix) +struct BcselEntry { uint32_t alias{0}; uint64_t selection{0}; uint32_t rct{0}; @@ -88,20 +88,20 @@ struct bcselEntry { // o2-linter: disable=name/struct (temporary fix) }; // bc selection configurables -struct bcselConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) +struct BcselConfigurables : o2::framework::ConfigurableGroup { std::string prefix = "bcselOpts"; - o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confTimeFrameStartBorderMargin{"TimeFrameStartBorderMargin", -1, "Number of bcs to cut at the start of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confTimeFrameEndBorderMargin{"TimeFrameEndBorderMargin", -1, "Number of bcs to cut at the end of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeFrameStartBorderMargin{"TimeFrameStartBorderMargin", -1, "Number of bcs to cut at the start of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeFrameEndBorderMargin{"TimeFrameEndBorderMargin", -1, "Number of bcs to cut at the end of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable> confMaxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; // o2-linter: disable=name/configurable (temporary fix) - o2::framework::Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) }; // event selection configurables -struct evselConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) +struct EvselConfigurables : o2::framework::ConfigurableGroup { std::string prefix = "evselOpts"; bool isMC_metadata = false; // o2-linter: disable=name/function-variable (temporary fix) o2::framework::Configurable amIneeded{"amIneeded", -1, "run event selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) @@ -129,7 +129,7 @@ struct evselConfigurables : o2::framework::ConfigurableGroup { // o2-linter: dis }; // luminosity configurables -struct lumiConfigurables : o2::framework::ConfigurableGroup { // o2-linter: disable=name/struct (temporary fix) +struct LumiConfigurables : o2::framework::ConfigurableGroup { std::string prefix = "lumiOpts"; o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) }; @@ -143,7 +143,7 @@ class BcSelectionModule } // declaration of structs here // (N.B.: will be invisible to the outside, create your own copies) - o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcselConfigurables bcselOpts; int lastRun = -1; int64_t lastTF = -1; @@ -424,7 +424,7 @@ class BcSelectionModule uint32_t rct = 0; // initialize properties - o2::common::eventselection::bcselEntry entry; + o2::common::eventselection::BcselEntry entry; entry.alias = alias; entry.selection = selection; entry.rct = rct; @@ -597,7 +597,7 @@ class BcSelectionModule } // initialize properties - o2::common::eventselection::bcselEntry entry; + o2::common::eventselection::BcselEntry entry; entry.alias = alias; entry.selection = selection; entry.rct = rct; @@ -706,7 +706,7 @@ class EventSelectionModule // declaration of structs here // (N.B.: will be invisible to the outside, create your own copies) - o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EvselConfigurables evselOpts; template void init(TContext& context, TEvSelOpts const& external_evselopts, THistoRegistry& histos, TMetadataInfo const& metadataInfo) @@ -790,9 +790,9 @@ class EventSelectionModule diffVzParMean = *parMeans; diffVzParSigma = *parSigmas; LOGP(info, ">>> special treatment for diffVz for light ion run {}", runLightIons); - for (int j = 0; j < 5; j++) // o2-linter: disable=magic-number (5 parameters) + for (size_t j = 0; j < diffVzParMean.size(); j++) LOGP(info, " mean par {} = {}", j, diffVzParMean[j]); - for (int j = 0; j < 5; j++) // o2-linter: disable=magic-number (5 parameters) + for (size_t j = 0; j < diffVzParSigma.size(); j++) LOGP(info, " sigma par {} = {}", j, diffVzParSigma[j]); break; } @@ -1553,7 +1553,7 @@ class LumiModule // declaration of structs here // (N.B.: will be invisible to the outside, create your own copies) - o2::common::eventselection::lumiConfigurables lumiOpts; + o2::common::eventselection::LumiConfigurables lumiOpts; template void init(TContext& context, TLumiOpts const& external_lumiopts, THistoRegistry& histos) @@ -1658,12 +1658,12 @@ class LumiModule csZEM = -1; csZNC = -1; // Temporary workaround to get visible cross section. TODO: store run-by-run visible cross sections in CCDB - if (beamZ1 == 8 && beamZ2 == 1) { // o2-linter: disable=magic-number (O beam on p, Z=8 and Z=1) - csTVX = 0.3874e6; // eff(TVX) = 0.807 (based on LHC25e6f); sigma(INEL)=0.48b; arxiv:2507.05853 - } else if (beamZ1 == 8 && beamZ2 == 8) { // o2-linter: disable=magic-number (O-O collisions, Z=8) - csTVX = 1.2050e6; // eff(TVX) = 0.886 (based on LHC25e6b); sigma(INEL)=1.36b; arxiv:2507.05853 + if (beamZ1 == 8 && beamZ2 == 1) { // o2-linter: disable=magic-number (O beam on p, Z=8 and Z=1) + csTVX = 0.3874e6; // eff(TVX) = 0.807 (based on LHC25e6f); sigma(INEL)=0.48b; arxiv:2507.05853 + } else if (beamZ1 == 8 && beamZ2 == 8) { // o2-linter: disable=magic-number (O-O collisions, Z=8) + csTVX = 1.2050e6; // eff(TVX) = 0.886 (based on LHC25e6b); sigma(INEL)=1.36b; arxiv:2507.05853 } else if (beamZ1 == 10 && beamZ2 == 10) { // o2-linter: disable=magic-number (Ne-Ne collisions, Z=10) - csTVX = 1.5411e6; // eff(TVX) = 0.896 (based on LHC25e6g); sigma(INEL)=1.72b; arxiv:2507.05853 + csTVX = 1.5411e6; // eff(TVX) = 0.896 (based on LHC25e6g); sigma(INEL)=1.72b; arxiv:2507.05853 } else if (beamZ1 == 1 && beamZ2 == 1) { if (std::fabs(sqrts - 900.) < 100.) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) csTVX = 0.0357e6; // ub @@ -1757,13 +1757,13 @@ class LumiModule double perBcRateTCE = static_cast(mCounterTCE[i + 1] - mCounterTCE[i]) / nOrbits / nCollidingBCs; double perBcRateZNC = static_cast(mCounterZNC[i + 1] - mCounterZNC[i]) / nOrbits / nCollidingBCs; double perBcRateZEM = static_cast(mCounterZEM[i + 1] - mCounterZEM[i]) / nOrbits / nCollidingBCs; - constexpr float rateMin = 1.e-10; + const float rateMin = 1.e-10; double muTVX = (perBcRateTVX < 1 && perBcRateTVX > rateMin) ? -std::log(1 - perBcRateTVX) : 0; double muTCE = (perBcRateTCE < 1 && perBcRateTCE > rateMin) ? -std::log(1 - perBcRateTCE) : 0; double muZNC = (perBcRateZNC < 1 && perBcRateZNC > rateMin) ? -std::log(1 - perBcRateZNC) : 0; double muZEM = (perBcRateZEM < 1 && perBcRateZEM > rateMin) ? -std::log(1 - perBcRateZEM) : 0; LOGP(debug, "orbit={} muTVX={} muTCE={} muZNC={} muZEM={}", mOrbits[i], muTVX, muTCE, muZNC, muZEM); - constexpr float muMin = 1.e-10; + const float muMin = 1.e-10; mPileupCorrectionTVX.push_back(muTVX > muMin ? muTVX / (1 - std::exp(-muTVX)) : 1); mPileupCorrectionTCE.push_back(muTCE > muMin ? muTCE / (1 - std::exp(-muTCE)) : 1); mPileupCorrectionZNC.push_back(muZNC > muMin ? muZNC / (1 - std::exp(-muZNC)) : 1); diff --git a/Common/Tools/timestampModule.h b/Common/Tools/timestampModule.h index 03981beccaf..2ecc7e8148a 100644 --- a/Common/Tools/timestampModule.h +++ b/Common/Tools/timestampModule.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file timestampModule.h +/// \brief Timestamp module +/// \author ALICE + #ifndef COMMON_TOOLS_TIMESTAMPMODULE_H_ #define COMMON_TOOLS_TIMESTAMPMODULE_H_ @@ -32,12 +36,11 @@ namespace timestamp { // timestamp configurables -struct timestampConfigurables : o2::framework::ConfigurableGroup { +struct TimestampConfigurables : o2::framework::ConfigurableGroup { std::string prefix = "timestamp"; o2::framework::Configurable verbose{"verbose", false, "verbose mode"}; o2::framework::Configurable fatalOnInvalidTimestamp{"fatalOnInvalidTimestamp", false, "Generate fatal error for invalid timestamps"}; - o2::framework::Configurable rct_path{"rct-path", "RCT/Info/RunInformation", "path to the ccdb RCT objects for the SOR timestamps"}; - o2::framework::Configurable orbit_reset_path{"orbit-reset-path", "CTP/Calib/OrbitReset", "path to the ccdb orbit-reset objects"}; + o2::framework::Configurable orbitResetPath{"orbit-reset-path", "CTP/Calib/OrbitReset", "path to the ccdb orbit-reset objects"}; // o2-linter: disable=name/configurable (temporary fix) o2::framework::Configurable isRun2MC{"isRun2MC", -1, "Running mode: enable only for Run 2 MC. Timestamps are set to SOR timestamp. Default: -1 (autoset from metadata) 0 (Standard) 1 (Run 2 MC)"}; // o2-linter: disable=name/configurable (temporary fix) }; @@ -57,7 +60,7 @@ class TimestampModule orbitResetTimestamp = 0; }; - o2::common::timestamp::timestampConfigurables timestampOpts; + o2::common::timestamp::TimestampConfigurables timestampOpts; // objects necessary during processing std::map mapRunToOrbitReset; /// Cache of orbit reset timestamps @@ -104,22 +107,24 @@ class TimestampModule // clear cache to prevent interference with orbit reset queries from other code // FIXME this should not have been a problem, to be investigated - ccdb->clearCache(timestampOpts.orbit_reset_path.value.data()); + ccdb->clearCache(timestampOpts.orbitResetPath.value.data()); - const bool isUnanchoredRun3MC = runNumber >= 300000 && runNumber < 500000; + const int maxRunNumberUnanchored = 499999; + const int minRunNumberUnanchored = 300000; + const bool isUnanchoredRun3MC = runNumber >= minRunNumberUnanchored && runNumber <= maxRunNumberUnanchored; if (timestampOpts.isRun2MC.value == 1 || isUnanchoredRun3MC) { // isRun2MC: bc/orbit distributions are not simulated in Run2 MC. All bcs are set to 0. // isUnanchoredRun3MC: assuming orbit-reset is done in the beginning of each run // Setting orbit-reset timestamp to start-of-run timestamp - orbitResetTimestamp = sorTimestamp * 1000; // from ms to us - } else if (runNumber < 300000) { // Run 2 + orbitResetTimestamp = sorTimestamp * 1000; // from ms to us + } else if (runNumber < minRunNumberUnanchored) { // Run 2 LOGF(debug, "Getting orbit-reset timestamp using start-of-run timestamp from CCDB"); - auto ctp = ccdb->template getSpecific>(timestampOpts.orbit_reset_path.value.data(), sorTimestamp); + auto ctp = ccdb->template getSpecific>(timestampOpts.orbitResetPath.value.data(), sorTimestamp); orbitResetTimestamp = (*ctp)[0]; } else { // sometimes orbit is reset after SOR. Using EOR timestamps for orbitReset query is more reliable LOGF(debug, "Getting orbit-reset timestamp using end-of-run timestamp from CCDB"); - auto ctp = ccdb->template getSpecific>(timestampOpts.orbit_reset_path.value.data(), eorTimestamp / 2 + sorTimestamp / 2); + auto ctp = ccdb->template getSpecific>(timestampOpts.orbitResetPath.value.data(), eorTimestamp / 2 + sorTimestamp / 2); orbitResetTimestamp = (*ctp)[0]; } @@ -136,7 +141,7 @@ class TimestampModule if (timestampOpts.verbose) { LOGF(info, "Orbit-reset timestamp for run number %i found: %llu us", runNumber, orbitResetTimestamp); } - int64_t timestamp{(orbitResetTimestamp + int64_t(bc.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000}; // us -> ms + int64_t timestamp{(orbitResetTimestamp + static_cast(bc.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000}; // us -> ms if (timestamp < runDuration.first || timestamp > runDuration.second) { if (timestampOpts.fatalOnInvalidTimestamp.value) { LOGF(fatal, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); From 67f6faf048fbbbcd957e81fe88a5ce09c95fe9ee Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:55:27 +0530 Subject: [PATCH 404/449] [PWGLF] Added configurable for MID (#16511) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index d3e2f89fc8b..580fd352909 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -137,6 +137,7 @@ struct Kstar892LightIon { // PID selections Configurable onlyTOF{"onlyTOF", false, "only TOF tracks"}; Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; + Configurable onlyTOFVeto{"onlyTOFVeto", false, "only select TOF tracks with TOF and TPC cuts"}; Configurable onlyTPC{"onlyTPC", false, "only TPC tracks"}; Configurable isApplypTdepPID{"isApplypTdepPID", false, "Apply pT dependent PID"}; Configurable isApplypTdepPIDwTOF{"isApplypTdepPIDwTOF", false, "Apply pT dependent PID with compulsory TOF condition in a pT range"}; @@ -158,6 +159,11 @@ struct Kstar892LightIon { Configurable cfgFakeTrackCutKa{"cfgFakeTrackCutKa", 0.3, "Cut based on momentum difference in global and TPC tracks for kaons"}; Configurable cfgFakeTrackCutPi{"cfgFakeTrackCutPi", 0.3, "Cut based on momentum difference in global and TPC tracks for pions"}; + Configurable pionMIDpTLow{"pionMIDpTLow", 1.0, "Low pT cut for pion in MID"}; + Configurable pionMIDpTHigh{"pionMIDpTHigh", 2.5, "High pT cut for pion in MID"}; + Configurable kaonMIDpTLow{"kaonMIDpTLow", 0.7, "Low pT cut for kaon in MID"}; + Configurable kaonMIDpTHigh{"kaonMIDpTHigh", 2.5, "High pT cut for kaon in MID"}; + // Fixed variables float lowPtCutPID = 0.5; @@ -211,7 +217,7 @@ struct Kstar892LightIon { int noOfDaughters = 2; - double pionPIDpTlow = 1.0, pionPIDpThigh = 2.5, kaonPIDpTlow = 0.7, kaonPIDpThigh = 2.5; + double pionPIDpTLow = 1.0, pionPIDpTHigh = 2.5, kaonPIDpTLow = 0.7, kaonPIDpTHigh = 2.5; TRandom* rn = new TRandom(); @@ -646,6 +652,10 @@ struct Kstar892LightIon { if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { return true; } + } else if (selectionConfig.onlyTOFVeto) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } } else if (selectionConfig.onlyTPC) { if (std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { return true; @@ -670,6 +680,10 @@ struct Kstar892LightIon { if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } + } else if (selectionConfig.onlyTOFVeto) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { + return true; + } } else if (selectionConfig.onlyTPC) { if (std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; @@ -717,7 +731,7 @@ struct Kstar892LightIon { bool selectionPIDpTdepTOF(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { - if (candidate.pt() < pionPIDpTlow || candidate.pt() > pionPIDpThigh) { + if (candidate.pt() < pionPIDpTLow || candidate.pt() > pionPIDpTHigh) { if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { return true; } @@ -733,7 +747,7 @@ struct Kstar892LightIon { } } } else if (PID == PIDParticle::kKaon) { - if (candidate.pt() < kaonPIDpTlow || candidate.pt() > kaonPIDpThigh) { + if (candidate.pt() < kaonPIDpTLow || candidate.pt() > kaonPIDpTHigh) { if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } @@ -797,11 +811,11 @@ struct Kstar892LightIon { bool selectionMIDpTdep(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { - if (candidate.pt() >= pionPIDpTlow && candidate.pt() < pionPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + if (candidate.pt() >= selectionConfig.pionMIDpTLow && candidate.pt() < selectionConfig.pionMIDpTHigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { return true; } } else if (PID == PIDParticle::kKaon) { - if (candidate.pt() >= kaonPIDpTlow && candidate.pt() < kaonPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + if (candidate.pt() >= selectionConfig.kaonMIDpTLow && candidate.pt() < selectionConfig.kaonMIDpTHigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { return true; } } @@ -812,11 +826,11 @@ struct Kstar892LightIon { bool selectionMIDPtDepComp(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { - if (candidate.pt() >= pionPIDpTlow && candidate.pt() < pionPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < std::abs(candidate.tpcNSigmaKa())) { + if (candidate.pt() >= selectionConfig.pionMIDpTLow && candidate.pt() < selectionConfig.pionMIDpTHigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < std::abs(candidate.tpcNSigmaKa())) { return true; } } else if (PID == PIDParticle::kKaon) { - if (candidate.pt() >= kaonPIDpTlow && candidate.pt() < kaonPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < std::abs(candidate.tpcNSigmaPi())) { + if (candidate.pt() >= selectionConfig.kaonMIDpTLow && candidate.pt() < selectionConfig.kaonMIDpTHigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < std::abs(candidate.tpcNSigmaPi())) { return true; } } From 9014ae87022388b246e3db245d5a27cbe21e910c Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Wed, 3 Jun 2026 19:45:49 +0800 Subject: [PATCH 405/449] [PWGLF] higherMassResonances.cxx: add process with event plane (#16514) --- .../Tasks/Resonances/higherMassResonances.cxx | 224 +++++++++++++++++- 1 file changed, 222 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index de6dfacd7e2..792916cb6fd 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -20,12 +20,14 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/EventPlaneHelper.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" // #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" // #include "Common/DataModel/PIDResponseTPC.h" // +#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" #include @@ -69,7 +71,8 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::rctsel; -// using namespace o2::constants::physics; +using namespace o2::constants::physics; + using std::array; // FixME: Add INEL>0 selection for the derived data @@ -181,10 +184,16 @@ struct HigherMassResonances { // Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + // event plane configurables + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "Total number of detectors in qVectorsTable"}; + Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; + Configurable cfgRefAName{"cfgRefAName", "TPCPos", "The name of detector for reference A"}; + Configurable cfgRefBName{"cfgRefBName", "TPCNeg", "The name of detector for reference B"}; + // // Mass and pT axis as configurables ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 5., 10., 30., 50., 70., 100., 110., 150.}, "Binning of the centrality axis"}; ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; - ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {70, 0.0f, 7.0f}, "Phi axis"}; // 0 to 2pi + ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {12, 0.0f, o2::constants::math::TwoPI}, "Phi axis"}; // 0 to 2pi ConfigurableAxis ksMassBins{"ksMassBins", {200, 0.45f, 0.55f}, "K0s invariant mass axis"}; ConfigurableAxis cGlueMassBins{"cGlueMassBins", {200, 0.9f, 3.0f}, "Glueball invariant mass axis"}; ConfigurableAxis cPtBins{"cPtBins", {200, 0.0f, 20.0f}, "Glueball pT axis"}; @@ -218,6 +227,12 @@ struct HigherMassResonances { // const double massK0s = o2::constants::physics::MassK0Short; bool isMix = false; + EventPlaneHelper helperEP; + int detId; + int refAId; + int refBId; + float minQvecAmp = 1e-5; + void init(InitContext const&) { rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); @@ -233,6 +248,9 @@ struct HigherMassResonances { AxisSpec deltaMAxis = {config.configAxisDeltaM, "#Delta M (GeV/#it{c}^{2})"}; AxisSpec angleSepAxis = {config.configAxisAngleSep, "Angular separation between V0s"}; AxisSpec ptCorrAxis = {config.configAxisPtCorr, "Pt correlation between two K0s"}; + AxisSpec axisCentQA = {100, 0, 100, ""}; + AxisSpec axisEvtPlQA = {100, -o2::constants::math::PI, o2::constants::math::PI, ""}; + AxisSpec axisEvtResPlQA = {102, -1.02, 1.02, ""}; // THnSparses std::array sparses = {config.activateHelicityFrame, config.activateCollinsSoperFrame, config.activateProductionFrame, config.activateBeamAxisFrame, config.activateRandomFrame}; @@ -341,6 +359,10 @@ struct HigherMassResonances { hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, deltaMAxis, angleSepAxis, ptCorrAxis}, true); hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, deltaMAxis, angleSepAxis, ptCorrAxis}, true); hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, deltaMAxis, angleSepAxis, ptCorrAxis}, true); + if (doprocessSEEP) { + hglue.add("h3glueInvMassEPDS", "h3glueInvMassEPDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPhi}, true); + hglue.add("h3glueInvMassEPRot", "h3glueInvMassEPRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPhi}, true); + } } // K0s topological/PID cuts @@ -417,6 +439,42 @@ struct HigherMassResonances { hMChists.add("MCcorrections/hSignalLossNumerator3", "Kstar generated after event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); hMChists.add("MCcorrections/hMultvsCent", "Kstar generated after event selection", kTH2F, {{multiplicityAxis}, {multiplicityAxis}}); } + + if (doprocessSEEP) { + detId = getdetId(config.cfgDetName); + refAId = getdetId(config.cfgRefAName); + refBId = getdetId(config.cfgRefBName); + + hglue.add("EpDet", "", {HistType::kTH2F, {axisCentQA, axisEvtPlQA}}); + hglue.add("EpRefA", "", {HistType::kTH2F, {axisCentQA, axisEvtPlQA}}); + hglue.add("EpRefB", "", {HistType::kTH2F, {axisCentQA, axisEvtPlQA}}); + + hglue.add("EpResDetRefA", "", {HistType::kTH2F, {axisCentQA, axisEvtResPlQA}}); + hglue.add("EpResDetRefB", "", {HistType::kTH2F, {axisCentQA, axisEvtResPlQA}}); + hglue.add("EpResRefARefB", "", {HistType::kTH2F, {axisCentQA, axisEvtResPlQA}}); + } + } + + template + int getdetId(const T& name) + { + if (name.value == "FT0C") { + return 0; + } else if (name.value == "FT0A") { + return 1; + } else if (name.value == "FT0M") { + return 2; + } else if (name.value == "FV0A") { + return 3; + } else if (name.value == "TPCPos") { + return 4; + } else if (name.value == "TPCNeg") { + return 5; + } else if (name.value == "TPCTot") { + return 6; + } else { + return 0; + } } template @@ -799,6 +857,7 @@ struct HigherMassResonances { using EventCandidates = soa::Filtered>; using TrackCandidates = soa::Filtered>; using V0TrackCandidate = soa::Join; + using EventCandidateEPs = soa::Filtered>; // For Monte Carlo using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; @@ -1157,6 +1216,167 @@ struct HigherMassResonances { } PROCESS_SWITCH(HigherMassResonances, processSE, "same event process", true); + void processSEEP(EventCandidateEPs::iterator const& collision, TrackCandidates const& /*tracks*/, V0TrackCandidate const& V0s) + { + multiplicity = 0.0; + + if (config.cSelectMultEstimator == kFT0M) { + multiplicity = collision.centFT0M(); + } else if (config.cSelectMultEstimator == kFT0A) { + multiplicity = collision.centFT0A(); + } else if (config.cSelectMultEstimator == kFT0C) { + multiplicity = collision.centFT0C(); + } else if (config.cSelectMultEstimator == kFV0A) { + multiplicity = collision.centFV0A(); + } else { + multiplicity = collision.centFT0C(); // default + } + + if (!selectionEvent(collision, true)) { + return; + } + + if (collision.qvecAmp()[detId] < minQvecAmp || collision.qvecAmp()[refAId] < minQvecAmp || collision.qvecAmp()[refBId] < minQvecAmp) { + return; + } + + if (config.qAevents) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + rEventSelection.fill(HIST("hmultiplicity"), multiplicity); + } + + float eps[3] = {0.}; + eps[0] = helperEP.GetEventPlane(collision.qvecRe()[4 * detId + 3], collision.qvecIm()[4 * detId + 3], 2); + eps[1] = helperEP.GetEventPlane(collision.qvecRe()[4 * refAId + 3], collision.qvecIm()[4 * refAId + 3], 2); + eps[2] = helperEP.GetEventPlane(collision.qvecRe()[4 * refBId + 3], collision.qvecIm()[4 * refBId + 3], 2); + + float resNumA = helperEP.GetResolution(eps[0], eps[1], 2); + float resNumB = helperEP.GetResolution(eps[0], eps[2], 2); + float resDenom = helperEP.GetResolution(eps[1], eps[2], 2); + + hglue.fill(HIST("EpDet"), multiplicity, eps[0]); + hglue.fill(HIST("EpRefA"), multiplicity, eps[1]); + hglue.fill(HIST("EpRefB"), multiplicity, eps[2]); + + hglue.fill(HIST("EpResDetRefA"), multiplicity, resNumA); + hglue.fill(HIST("EpResDetRefB"), multiplicity, resNumB); + hglue.fill(HIST("EpResRefARefB"), multiplicity, resDenom); + + std::vector v0indexes; + + for (const auto& [v1, v2] : combinations(CombinationsFullIndexPolicy(V0s, V0s))) { + + if (v1.size() == 0 || v2.size() == 0) { + continue; + } + + if (!selectionV0(collision, v1, multiplicity)) { + continue; + } + if (!selectionV0(collision, v2, multiplicity)) { + continue; + } + + auto postrack1 = v1.template posTrack_as(); + auto negtrack1 = v1.template negTrack_as(); + auto postrack2 = v2.template posTrack_as(); + auto negtrack2 = v2.template negTrack_as(); + + double nTPCSigmaPos1{postrack1.tpcNSigmaPi()}; + double nTPCSigmaNeg1{negtrack1.tpcNSigmaPi()}; + double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; + double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; + + if (!(isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, v1) && isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, v1))) { + continue; + } + if (!(isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, v2) && isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, v2))) { + continue; + } + + if (std::find(v0indexes.begin(), v0indexes.end(), v1.globalIndex()) == v0indexes.end()) { + v0indexes.push_back(v1.globalIndex()); + } + + if (v2.globalIndex() <= v1.globalIndex()) { + continue; + } + + if (postrack1.globalIndex() == postrack2.globalIndex()) { + continue; + } + if (negtrack1.globalIndex() == negtrack2.globalIndex()) { + continue; + } + + double deltaRDaugherPos = std::sqrt(TVector2::Phi_mpi_pi(postrack1.phi() - negtrack1.phi()) * TVector2::Phi_mpi_pi(postrack1.phi() - negtrack1.phi()) + (postrack1.eta() - negtrack1.eta()) * (postrack1.eta() - negtrack1.eta())); + double deltaRDaugherNeg = std::sqrt(TVector2::Phi_mpi_pi(postrack2.phi() - negtrack2.phi()) * TVector2::Phi_mpi_pi(postrack2.phi() - negtrack2.phi()) + (postrack2.eta() - negtrack2.eta()) * (postrack2.eta() - negtrack2.eta())); + + if (config.qAv0) { + rKzeroShort.fill(HIST("hDauDeltaR"), deltaRDaugherPos, deltaRDaugherNeg); + } + + if (deltaRDaugherPos < config.deltaRDaugherCut || deltaRDaugherNeg < config.deltaRDaugherCut) { + continue; + } + + if (config.isApplyEtaCutK0s && (v1.eta() < config.confDaughEta || v2.eta() < config.confDaughEta)) { + continue; + } + + daughter1 = ROOT::Math::PxPyPzMVector(v1.px(), v1.py(), v1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(v2.px(), v2.py(), v2.pz(), o2::constants::physics::MassK0Short); // Kshort + + mother = daughter1 + daughter2; // invariant mass of Kshort pair + isMix = false; + + const double deltaMass = deltaM(v1.mK0Short(), v2.mK0Short()); + if (config.qAv0) { + rKzeroShort.fill(HIST("hK0ShortMassCorr"), v1.mK0Short(), v2.mK0Short(), deltaMass); + } + + if (!config.qAOptimisation) { + if (deltaMass > config.cMaxDeltaM) { + continue; + } + } + + const double ptCorr = (mother.Pt() - daughter1.Pt() != 0.) ? daughter1.Pt() / (mother.Pt() - daughter1.Pt()) : 0.; + if (config.qAv0) { + rKzeroShort.fill(HIST("hK0sPtCorrelation"), ptCorr); + } + + double deltaRvalue = std::sqrt(TVector2::Phi_mpi_pi(v1.phi() - v2.phi()) * TVector2::Phi_mpi_pi(v1.phi() - v2.phi()) + (v1.eta() - v2.eta()) * (v1.eta() - v2.eta())); + + if (!config.qAOptimisation) { + if (deltaRvalue < config.deltaRK0sCut) { + continue; + } + } + + if (!config.isselectTWOKsOnly && config.qAOptimisation) { + + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassEPDS"), multiplicity, mother.Pt(), mother.M(), RecoDecay::constrainAngle(2.0 * mother.Phi() - 2.0 * eps[0])); + } + + for (int i = 0; i < config.cRotations; i++) { + double theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); + + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + + motherRot = daughterRot + daughter2; + + if (motherRot.Rapidity() < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassEPRot"), multiplicity, motherRot.Pt(), motherRot.M(), RecoDecay::constrainAngle(2.0 * motherRot.Phi() - 2.0 * eps[0])); + } + } + } + } + v0indexes.clear(); + } + PROCESS_SWITCH(HigherMassResonances, processSEEP, "same event process with EP table", true); + ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for ME mixing"}; // ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {10, 0, 100}, "multiplicity percentile for ME mixing"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity axis for ME mixing"}; From 90cc07d43e662091240d5c53a343856d53783105 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 3 Jun 2026 15:48:51 +0200 Subject: [PATCH 406/449] [PWGEM/Dilepton] update taggingHFE.cxx (#16521) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 8 +++++--- PWGEM/Dilepton/Tasks/taggingHFE.cxx | 24 ++++++++++++------------ PWGEM/Dilepton/Utils/SemiCharmTag.h | 9 ++++++++- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index c6ffc2bb93c..c3d67aed178 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -260,6 +260,8 @@ DECLARE_SOA_COLUMN(CascadeType, cascadeType, uint8_t); //! cascade type, 0 = XiM DECLARE_SOA_COLUMN(MassLH, massLH, float); //! invariant mass of LH assuming kaon DECLARE_SOA_COLUMN(PtLH, ptLH, float); //! pt of LH DECLARE_SOA_COLUMN(PLH, pLH, float); //! p of LH +DECLARE_SOA_COLUMN(DEtaLH, dEtaLH, float); //! deta between LH at SV +DECLARE_SOA_COLUMN(DPhiLH, dPhiLH, float); //! dphi between LH at SV DECLARE_SOA_COLUMN(PtSVL, ptSVL, float); //! pT of lepton at SV // DECLARE_SOA_COLUMN(PlSVL, plSVL, float); //! pL of lepton at SV @@ -305,7 +307,7 @@ DECLARE_SOA_TABLE(EMMLLTPairs, "AOD", "EMMLLTPAIR", //! // pidtpc::TPCNSigmaPi, pidtof::TOFNSigmaPi, pidtpc::TPCNSigmaKa, pidtof::TOFNSigmaKa, // pidtpc::TPCNSigmaPr, pidtof::TOFNSigmaPr, - emmllhpair::MassLH, emmllhpair::PLH, + emmllhpair::MassLH, emmllhpair::PLH, emmllhpair::DEtaLH, emmllhpair::DPhiLH, // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, @@ -319,7 +321,7 @@ DECLARE_SOA_TABLE(EMMLLV0Pairs, "AOD", "EMMLLV0PAIR", //! emmllhpair::PtH, emmllhpair::RapidityV0, emmllhpair::V0CPA, emmllhpair::V0CPAXY, emmllhpair::V0CPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PLH, + emmllhpair::MassLH, emmllhpair::PLH, emmllhpair::DEtaLH, emmllhpair::DPhiLH, // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, @@ -333,7 +335,7 @@ DECLARE_SOA_TABLE(EMMLLCascPairs, "AOD", "EMMLLCPAIR", //! emmllhpair::Signed1PtH, emmllhpair::RapidityC, emmllhpair::CascCPA, emmllhpair::CascCPAXY, emmllhpair::CascCPARZ, emmllhpair::ImpParXYH, emmllhpair::ImpParZH, emmllhpair::ImpParCYYH, emmllhpair::ImpParCZYH, emmllhpair::ImpParCZZH, - emmllhpair::MassLH, emmllhpair::PLH, + emmllhpair::MassLH, emmllhpair::PLH, emmllhpair::DEtaLH, emmllhpair::DPhiLH, // emmllhpair::PtSVL, emmllhpair::PtSVH, emmllhpair::PtFD, emmllhpair::PlFD, emmllhpair::Chi2PCA, emmllhpair::CPA, emmllhpair::CPAXY, emmllhpair::CPARZ, emmllhpair::Lxy, emmllhpair::Lz, emmllhpair::Lxyz, emmllhpair::LxyErr, emmllhpair::LzErr, emmllhpair::LxyzErr, diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 9ed7bd73aae..52490df74ec 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -1770,7 +1770,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.p, + eKpair.mass, eKpair.p, eKpair.deta, eKpair.dphi, // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -1831,7 +1831,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.p, + eKpair.mass, eKpair.p, eKpair.deta, eKpair.dphi, // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -1910,7 +1910,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.p, + eV0pair.mass, eV0pair.p, eV0pair.deta, eV0pair.dphi, // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -1973,7 +1973,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.p, + eV0pair.mass, eV0pair.p, eV0pair.deta, eV0pair.dphi, // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2041,7 +2041,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.p, + eCpair.mass, eCpair.p, eCpair.deta, eCpair.dphi, // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2109,7 +2109,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.p, + eCpair.mass, eCpair.p, eCpair.deta, eCpair.dphi, // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2206,7 +2206,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.p, + eKpair.mass, eKpair.p, eKpair.deta, eKpair.dphi, // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -2268,7 +2268,7 @@ struct taggingHFE { // kaon.tpcNSigmaPi(), tofNSigmaPi, kaon.tpcNSigmaKa(), tofNSigmaKa, // kaon.tpcNSigmaPr(), tofNSigmaPr, - eKpair.mass, eKpair.p, + eKpair.mass, eKpair.p, eKpair.deta, eKpair.dphi, // eKpair.ptSVL, eKpair.ptSVH, eKpair.ptFD, eKpair.plFD, eKpair.chi2PCA, eKpair.cospa, eKpair.cospaXY, eKpair.cospaRZ, eKpair.lxy, eKpair.lz, eKpair.lxyz, eKpair.lxyErr, eKpair.lzErr, eKpair.lxyzErr, @@ -2346,7 +2346,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.p, + eV0pair.mass, eV0pair.p, eV0pair.deta, eV0pair.dphi, // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2409,7 +2409,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0.x(), v0.y(), v0.z()}, std::array{v0.px(), v0.py(), v0.pz()}), impactParameterV0.getY(), impactParameterV0.getZ(), impactParameterV0.getSigmaY2(), impactParameterV0.getSigmaYZ(), impactParameterV0.getSigmaZ2(), - eV0pair.mass, eV0pair.p, + eV0pair.mass, eV0pair.p, eV0pair.deta, eV0pair.dphi, // eV0pair.ptSVL, eV0pair.ptSVH, eV0pair.ptFD, eV0pair.plFD, eV0pair.chi2PCA, eV0pair.cospa, eV0pair.cospaXY, eV0pair.cospaRZ, eV0pair.lxy, eV0pair.lz, eV0pair.lxyz, eV0pair.lxyErr, eV0pair.lzErr, eV0pair.lxyzErr, @@ -2477,7 +2477,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.p, + eCpair.mass, eCpair.p, eCpair.deta, eCpair.dphi, // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, @@ -2545,7 +2545,7 @@ struct taggingHFE { RecoDecay::cpaXY(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), RecoDecay::cpaRZ(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{cascade.x(), cascade.y(), cascade.z()}, std::array{cascade.px(), cascade.py(), cascade.pz()}), impactParameterCasc.getY(), impactParameterCasc.getZ(), impactParameterCasc.getSigmaY2(), impactParameterCasc.getSigmaYZ(), impactParameterCasc.getSigmaZ2(), - eCpair.mass, eCpair.p, + eCpair.mass, eCpair.p, eCpair.deta, eCpair.dphi, // eCpair.ptSVL, eCpair.ptSVH, eCpair.ptFD, eCpair.plFD, eCpair.chi2PCA, eCpair.cospa, eCpair.cospaXY, eCpair.cospaRZ, eCpair.lxy, eCpair.lz, eCpair.lxyz, eCpair.lxyErr, eCpair.lzErr, eCpair.lxyzErr, diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index d390940398a..8f3610e1e23 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -37,6 +37,8 @@ struct LHPair { // struct to store electron-hadron pair information float mass{-999.f}; float pt{-999.f}; float p{-999.f}; + float deta{-999.f}; + float dphi{-999.f}; float dca2legs{-999.f}; float chi2PCA{-999.f}; float cospa{-999.f}; @@ -173,7 +175,8 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); - + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron pair.isOK = true; return pair; } @@ -299,6 +302,8 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron pair.isOK = true; return pair; @@ -429,6 +434,8 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron pair.isOK = true; return pair; From b11664c46c5912eaf1605455ea0369a65af2bf2c Mon Sep 17 00:00:00 2001 From: MRazza <118839113+MRazza879@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:27:14 +0200 Subject: [PATCH 407/449] [PWGHF] Update task for deuteron from Lb analysis (#16519) Co-authored-by: Marta Razza --- PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx | 89 ++++++++++++++------------ 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx b/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx index 1a1f25d5372..1dc6f54dbe4 100644 --- a/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx +++ b/PWGHF/D2H/Tasks/taskDeuteronFromLb.cxx @@ -9,9 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // +/// \file taskDeuteronFromLb.cxx /// \brief A filter task for non prompt deuterons from beauty-hadron decays -/// \author Marta Razza marta.razza@cern.ch -/// \author Francesca Ercolessi francesca.ercolessi@cern.ch +/// \author Marta Razza +/// \author Francesca Ercolessi /// \since May 25, 2026 #include "Common/Core/Zorro.h" @@ -69,7 +70,9 @@ struct HfTaskDeuteronFromLb { Configurable cfgTPCNsigma{"cfgTPCNsigma", 4.0f, "TPC n sigma for deuteron PID"}; Configurable cfgTofNsigmaMin{"cfgTofNsigmaMin", 3.0f, "TOF n sigma min for deuteron PID"}; Configurable cfgTofNsigmaMax{"cfgTofNsigmaMax", 4.0f, "TOF n sigma max for deuteron PID"}; - Configurable ptThresholdPid{"ptThresholdPid", 1.0f, "pT threshold to switch between 4 and 3 sigmas for TOF PID"}; + Configurable ptThresholdPid{"ptThresholdPid", 0.5f, "pT threshold to switch between 4 and 3 sigmas for TOF PID"}; + Configurable cfgDCAmin{"cfgDCAmin", 0.05f, "Minimum DCA for deuteron PID"}; + Configurable cfgDCAmax{"cfgDCAmax", 1000.0f, "Maximum DCA for deuteron PID"}; Configurable rapidityCut{"rapidityCut", 0.5f, "Rapidity cut"}; // PDG codes Configurable pdgCodeMother{"pdgCodeMother", -5122, "PDG code of the mother particle (default: anti-Lambda_b)"}; @@ -88,6 +91,11 @@ struct HfTaskDeuteronFromLb { Preslice trackIndicesPerCollision = o2::aod::track_association::collisionId; + ConfigurableAxis ptAxis{"ptAxis", {100, 0., 10.f}, "p_{T} GeV/c"}; + ConfigurableAxis nSigmaAxis{"nSigmaAxis", {200, -10.f, 10.f}, "nSigma"}; + ConfigurableAxis dcaXyAxis{"dcaXyAxis", {1000, -0.2f, 0.2f}, "DCA xy (cm)"}; + ConfigurableAxis dcaZAxis{"dcaZAxis", {1000, -0.2f, 0.2f}, "DCA z (cm)"}; + HistogramRegistry QAHistos{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -105,23 +113,18 @@ struct HfTaskDeuteronFromLb { zorroSummary.setObject(zorro.getZorroSummary()); } - ConfigurableAxis ptAxis{"ptAxis", {100, 0., 10.f}, "p_{T} GeV/c"}; - ConfigurableAxis nSigmaAxis{"nSigmaAxis", {200, -10.f, 10.f}, "nSigma"}; - ConfigurableAxis dcaXyAxis{"dcaXyAxis", {1000, -0.2f, 0.2f}, "DCA xy (cm)"}; - ConfigurableAxis dcaZAxis{"dcaZAxis", {1000, -0.2f, 0.2f}, "DCA z (cm)"}; - - QAHistos.add("hVtxZ", "Z-Vertex distribution after selection;Z (cm)", HistType::kTH1F, {{100, -50, 50}}); - QAHistos.add("ptGeneratedLb", "ptGeneratedLb", HistType::kTH1F, {ptAxis}); - QAHistos.add("ptAntiDeuteronPrimary", "ptAntiDeuteronPrimaryReco", HistType::kTH1F, {ptAxis}); - QAHistos.add("ptAntiDeuteronFromLb", "ptAntiDeuteronFromLbReco", HistType::kTH1F, {ptAxis}); - QAHistos.add("hDCAxy-Primary", "DCAxy-Primary", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); - QAHistos.add("hDCAxy-FromLb", "DCAxy-FromLb", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); - QAHistos.add("hDCAxyVsPt", "DCAxy #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaXyAxis}}); - QAHistos.add("hDCAzVsPt", "DCAz #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaZAxis}}); - QAHistos.add("hnSigmaTPCVsPt", "n#sigma TPC vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TPC", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); - QAHistos.add("hnSigmaTOFVsPt", "n#sigma TOF vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TOF", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); - QAHistos.add("ptAntiDeuteron", "ptAntiDeuteron", {HistType::kTH1F, {ptAxis}}); - QAHistos.add("etaAntideuteron", "etaAntideuteron", {HistType::kTH1F, {{100, -1.0f, 1.0f, "eta #bar{d}"}}}); + QAHistos.add("MC/ptGeneratedLb", "ptGeneratedLb", HistType::kTH1F, {ptAxis}); + QAHistos.add("MC/ptAntiDeuteronPrimary", "ptAntiDeuteronPrimaryReco", HistType::kTH1F, {ptAxis}); + QAHistos.add("MC/ptAntiDeuteronFromLb", "ptAntiDeuteronFromLbReco", HistType::kTH1F, {ptAxis}); + QAHistos.add("MC/hDCAxy-Primary", "DCAxy-Primary", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); + QAHistos.add("MC/hDCAxy-FromLb", "DCAxy-FromLb", {HistType::kTH1D, {{400, -0.2f, 0.2f, "DCA xy (cm)"}}}); + QAHistos.add("Data/hDCAxyVsPt", "DCAxy #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaXyAxis}}); + QAHistos.add("Data/hDCAzVsPt", "DCAz #bar{d} vs p_{T}", {HistType::kTH2D, {ptAxis, dcaZAxis}}); + QAHistos.add("Data/hnSigmaTPCVsPt", "n#sigma TPC vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TPC", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); + QAHistos.add("Data/hnSigmaTOFVsPt", "n#sigma TOF vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TOF", {HistType::kTH2D, {ptAxis, nSigmaAxis}}); + QAHistos.add("Data/ptAntiDeuteron", "ptAntiDeuteron", {HistType::kTH1F, {ptAxis}}); + QAHistos.add("Data/etaAntideuteron", "etaAntideuteron", {HistType::kTH1F, {{100, -1.0f, 1.0f, "eta #bar{d}"}}}); + QAHistos.add("Data/hVtxZ", "Z-Vertex distribution after selection;Z (cm)", HistType::kTH1F, {{100, -50, 50}}); hProcessedEvents->GetXaxis()->SetBinLabel(1, "Events processed"); hProcessedEvents->GetXaxis()->SetBinLabel(2, "ZORRO"); @@ -147,6 +150,8 @@ struct HfTaskDeuteronFromLb { { if (std::abs(track.eta()) > cfgEta) return false; + if (std::abs(track.dcaXY()) < cfgDCAmin || std::abs(track.dcaXY()) > cfgDCAmax) + return false; if (!track.hasITS()) return false; if (!track.hasTPC()) @@ -200,7 +205,7 @@ struct HfTaskDeuteronFromLb { continue; } hProcessedEvents->Fill(3.5); - QAHistos.fill(HIST("hVtxZ"), collision.posZ()); + QAHistos.fill(HIST("Data/hVtxZ"), collision.posZ()); const auto& trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); @@ -223,27 +228,27 @@ struct HfTaskDeuteronFromLb { if (track.pt() < ptThresholdPid) { if (isTPCDe && isTOFDe_max) { - QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); - QAHistos.fill(HIST("etaAntideuteron"), track.eta()); - QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); - QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); - QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); - QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + QAHistos.fill(HIST("Data/ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("Data/etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("Data/hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("Data/hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("Data/hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("Data/hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); } } else { if (isTPCDe && isTOFDe_min && isTOFDe_max) { - QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); - QAHistos.fill(HIST("etaAntideuteron"), track.eta()); - QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); - QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); - QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); - QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + QAHistos.fill(HIST("Data/ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("Data/etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("Data/hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("Data/hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("Data/hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("Data/hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); } } } } } - PROCESS_SWITCH(HfTaskDeuteronFromLb, processData, "processData", false); + PROCESS_SWITCH(HfTaskDeuteronFromLb, processData, "processData", true); void processMC(MCCollisionCandidates::iterator const&, MCTrackCandidates const& tracks, o2::aod::McParticles const&) { @@ -272,17 +277,17 @@ struct HfTaskDeuteronFromLb { } } if (isFromLb) { - QAHistos.fill(HIST("hDCAxy-FromLb"), track.dcaXY()); - QAHistos.fill(HIST("ptAntiDeuteronFromLb"), track.pt()); + QAHistos.fill(HIST("MC/hDCAxy-FromLb"), track.dcaXY()); + QAHistos.fill(HIST("MC/ptAntiDeuteronFromLb"), track.pt()); } else { - QAHistos.fill(HIST("hDCAxy-Primary"), track.dcaXY()); - QAHistos.fill(HIST("ptAntiDeuteronPrimary"), track.pt()); + QAHistos.fill(HIST("MC/hDCAxy-Primary"), track.dcaXY()); + QAHistos.fill(HIST("MC/ptAntiDeuteronPrimary"), track.pt()); } } } } } - PROCESS_SWITCH(HfTaskDeuteronFromLb, processMC, "processMC", true); + PROCESS_SWITCH(HfTaskDeuteronFromLb, processMC, "processMC", false); void processGen(o2::aod::McCollision const&, o2::aod::McParticles const& mcParticles) { @@ -290,7 +295,7 @@ struct HfTaskDeuteronFromLb { for (const auto& mcParticle : mcParticles) { if (mcParticle.pdgCode() == pdgCodeMother) { if (std::abs(mcParticle.y()) <= rapidityCut) { - QAHistos.fill(HIST("ptGeneratedLb"), mcParticle.pt()); + QAHistos.fill(HIST("MC/ptGeneratedLb"), mcParticle.pt()); } } @@ -309,9 +314,9 @@ struct HfTaskDeuteronFromLb { } if (isFromLb) { - QAHistos.fill(HIST("ptAntiDeuteronFromLb"), mcParticle.pt()); + QAHistos.fill(HIST("MC/ptAntiDeuteronFromLb"), mcParticle.pt()); } else if (mcParticle.isPhysicalPrimary()) { - QAHistos.fill(HIST("ptAntiDeuteronPrimary"), mcParticle.pt()); + QAHistos.fill(HIST("MC/ptAntiDeuteronPrimary"), mcParticle.pt()); } } } From 928ad82678cb17ccb0b6f46d047eeb952aa75112 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Wed, 3 Jun 2026 16:35:43 +0200 Subject: [PATCH 408/449] [PWGLF,PWGMM] Add event selection on ITS layers (#16451) --- PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index 8ecdaafd555..575470dc8af 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -90,6 +90,8 @@ using namespace o2::aod::rctsel; auto static constexpr CminCharge = 3.f; auto static constexpr CintZero = 0; +auto static constexpr CintOne = 1; +auto static constexpr CintTwo = 2; auto static constexpr Czero = 0.f; auto static constexpr Cninety = 90.f; auto static constexpr ConeHeighty = 180.f; @@ -98,7 +100,7 @@ auto static constexpr CmaxAccFT0A = 4.9f; auto static constexpr CminAccFT0C = -3.3f; auto static constexpr CmaxAccFT0C = -2.1f; -constexpr int CevtSel = 15; +constexpr int CevtSel = 16; constexpr int CtrkSel = 7; constexpr int CtrkTrkBestSel = 6; constexpr int CambTrkType = 7; @@ -120,6 +122,7 @@ enum class EvtSel { evtNoCollInRofStrict, evtNoCollInRofStandard, evtNoHighMultCollInPrevRof, + evtGoodITSLayersAll, evtBelowMinOccup, evtAboveMaxOccup, evtRCTFlagChecker, @@ -428,6 +431,7 @@ struct DndetaMFTPbPb { Configurable requireNoCollInRofStrict{"requireNoCollInRofStrict", true, "requireNoCollInRofStrict"}; Configurable requireNoCollInRofStandard{"requireNoCollInRofStandard", false, "requireNoCollInRofStandard"}; Configurable requireNoHighMultCollInPrevRof{"requireNoHighMultCollInPrevRof", false, "requireNoHighMultCollInPrevRof"}; + Configurable requireGoodITSLayersAll{"requireGoodITSLayersAll", true, "requireGoodITSLayersAll"}; Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds"}; Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds"}; Configurable occupancyEstimator{"occupancyEstimator", 1, "Occupancy estimator: 1 = trackOccupancyInTimeRange, 2 = ft0cOccupancyInTimeRange"}; @@ -577,6 +581,7 @@ struct DndetaMFTPbPb { labelEvtSel[static_cast(EvtSel::evtNoCollInRofStrict)] = "kNoCollInRofStrict"; labelEvtSel[static_cast(EvtSel::evtNoCollInRofStandard)] = "kNoCollInRofStandard"; labelEvtSel[static_cast(EvtSel::evtNoHighMultCollInPrevRof)] = "kNoHighMultCollInPrevRof"; + labelEvtSel[static_cast(EvtSel::evtGoodITSLayersAll)] = "kIsGoodITSLayersAll"; labelEvtSel[static_cast(EvtSel::evtBelowMinOccup)] = "Below min occup."; labelEvtSel[static_cast(EvtSel::evtAboveMaxOccup)] = "Above max occup."; labelEvtSel[static_cast(EvtSel::evtRCTFlagChecker)] = "RCT Flag Checker"; @@ -2241,6 +2246,12 @@ struct DndetaMFTPbPb { if constexpr (fillHis) { registry.fill(HIST("Events/hEvtSel"), static_cast(EvtSel::evtNoHighMultCollInPrevRof)); } + if (eventCuts.requireGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + if constexpr (fillHis) { + registry.fill(HIST("Events/hEvtSel"), static_cast(EvtSel::evtGoodITSLayersAll)); + } if (eventCuts.minOccupancy >= 0 && getOccupancy(collision, eventCuts.occupancyEstimator) < eventCuts.minOccupancy) { @@ -4960,9 +4971,9 @@ struct DndetaMFTPbPb { if (gConf.cfgDCAtype == 0) { dcaInfo[0] = dcaInfOrig[0]; - } else if (gConf.cfgDCAtype == 1) { + } else if (gConf.cfgDCAtype == CintOne) { dcaInfo[0] = dcaInfOrig[1]; - } else if (gConf.cfgDCAtype == 2) { + } else if (gConf.cfgDCAtype == CintTwo) { dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); } dcaInfo[1] = dcaInfOrig[2]; From 93be5abc11bf0d9523a6796037a95f96039e8946 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:08:57 +0200 Subject: [PATCH 409/449] [Common] Avoid recalculating BB over and over (#16432) --- Common/Core/PID/TPCPIDResponse.h | 48 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/Common/Core/PID/TPCPIDResponse.h b/Common/Core/PID/TPCPIDResponse.h index 7831039f4d8..5120950fa5f 100644 --- a/Common/Core/PID/TPCPIDResponse.h +++ b/Common/Core/PID/TPCPIDResponse.h @@ -90,12 +90,17 @@ class Response /// Gets the deviation to the expected signal template float GetSignalDelta(const TrackType& trk, const o2::track::PID::ID id) const; + /// Gets relative dEdx resolution contribution due to relative pt resolution float GetRelativeResolutiondEdx(const float p, const float mass, const float charge, const float resol) const; void PrintAll() const; private: + /// Compute expected sigma given a pre-computed expected signal, avoiding a redundant Bethe-Bloch call. + template + float sigmaFromSignal(float expectedSignal, const long multTPC, const TrackType& track, const o2::track::PID::ID id) const; + std::array mBetheBlochParams = {0.03209809958934784, 19.9768009185791, 2.5266601063857674e-16, 2.7212300300598145, 6.080920219421387}; std::array mResolutionParamsDefault = {0.07, 0.0}; std::vector mResolutionParams = {5.43799e-7, 0.053044, 0.667584, 0.0142667, 0.00235175, 1.22482, 2.3501e-7, 0.031585}; @@ -135,13 +140,18 @@ inline float Response::GetExpectedSigmaAtMultiplicity(const long multTPC, const if (!track.hasTPC()) { return -999.f; } - float resolution = 0.; + return sigmaFromSignal(GetExpectedSignal(track, id), multTPC, track, id); +} + +template +inline float Response::sigmaFromSignal(float expectedSignal, const long multTPC, const TrackType& track, const o2::track::PID::ID id) const +{ + float resolution = 0.f; if (mUseDefaultResolutionParam) { - const float reso = GetExpectedSignal(track, id) * mResolutionParamsDefault[0] * (static_cast(track.tpcNClsFound()) > 0 ? std::sqrt(1. + mResolutionParamsDefault[1] / static_cast(track.tpcNClsFound())) : 1.f); + const float reso = expectedSignal * mResolutionParamsDefault[0] * (static_cast(track.tpcNClsFound()) > 0 ? std::sqrt(1. + mResolutionParamsDefault[1] / static_cast(track.tpcNClsFound())) : 1.f); reso >= 0.f ? resolution = reso : resolution = -999.f; } else { - - const double ncl = nClNorm / track.tpcNClsFound(); // + const double ncl = nClNorm / track.tpcNClsFound(); const double p = track.tpcInnerParam(); const double mass = o2::track::pid_constants::sMasses[id]; const double bg = p / mass; @@ -160,16 +170,15 @@ inline float Response::GetExpectedSigmaAtMultiplicity(const long multTPC, const template inline float Response::GetNumberOfSigma(const CollisionType& collision, const TrackType& trk, const o2::track::PID::ID id) const { - if (GetExpectedSigma(collision, trk, id) < 0.) { - return -999.f; - } - if (GetExpectedSignal(trk, id) < 0.) { + const float signal = GetExpectedSignal(trk, id); + if (signal < 0.f) { return -999.f; } - if (!trk.hasTPC()) { + const float sigma = sigmaFromSignal(signal, collision.multTPC(), trk, id); + if (sigma < 0.f) { return -999.f; } - return ((trk.tpcSignal() - GetExpectedSignal(trk, id)) / GetExpectedSigma(collision, trk, id)); + return (trk.tpcSignal() - signal) / sigma; } template @@ -181,29 +190,26 @@ inline float Response::GetNumberOfSigmaMCTuned(const CollisionType& collision, c template inline float Response::GetNumberOfSigmaMCTunedAtMultiplicity(const long multTPC, const TrackType& trk, const o2::track::PID::ID id, float mcTunedTPCSignal) const { - if (GetExpectedSigmaAtMultiplicity(multTPC, trk, id) < 0.) { + const float signal = GetExpectedSignal(trk, id); + if (signal < 0.f) { return -999.f; } - if (GetExpectedSignal(trk, id) < 0.) { + const float sigma = sigmaFromSignal(signal, multTPC, trk, id); + if (sigma < 0.f) { return -999.f; } - if (!trk.hasTPC()) { - return -999.f; - } - return ((mcTunedTPCSignal - GetExpectedSignal(trk, id)) / GetExpectedSigmaAtMultiplicity(multTPC, trk, id)); + return (mcTunedTPCSignal - signal) / sigma; } /// Gets the deviation between the actual signal and the expected signal template inline float Response::GetSignalDelta(const TrackType& trk, const o2::track::PID::ID id) const { - if (GetExpectedSignal(trk, id) < 0.) { - return -999.f; - } - if (!trk.hasTPC()) { + const float signal = GetExpectedSignal(trk, id); + if (signal < 0.f) { return -999.f; } - return (trk.tpcSignal() - GetExpectedSignal(trk, id)); + return trk.tpcSignal() - signal; } //// Gets relative dEdx resolution contribution due relative pt resolution From 935cbffe804484376b338edb39b43bcc7bf7757b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 3 Jun 2026 21:37:06 +0200 Subject: [PATCH 410/449] [Common,PWGEM,PWGLF,PWGUD] Make sure converters invoke reserve to avoid memory churn (#16522) --- Common/TableProducer/Converters/bcConverter.cxx | 1 + Common/TableProducer/Converters/bcFlagsCreator.cxx | 1 + Common/TableProducer/Converters/caloLabelConverter.cxx | 1 + Common/TableProducer/Converters/collisionConverter.cxx | 1 + Common/TableProducer/Converters/fddConverter.cxx | 1 + Common/TableProducer/Converters/hmpConverter.cxx | 1 + Common/TableProducer/Converters/mcCollisionConverter.cxx | 1 + Common/TableProducer/Converters/mcConverter.cxx | 1 + Common/TableProducer/Converters/mftTracksConverter.cxx | 1 + Common/TableProducer/Converters/multMCExtrasConverter.cxx | 1 + Common/TableProducer/Converters/multsExtraConverter.cxx | 1 + Common/TableProducer/Converters/run2bcinfosConverter.cxx | 1 + Common/TableProducer/Converters/run2tracksExtraConverter.cxx | 1 + Common/TableProducer/Converters/trackQA002Converter.cxx | 2 ++ Common/TableProducer/Converters/trackQA003Converter.cxx | 3 +++ Common/TableProducer/Converters/trackQAConverter.cxx | 1 + Common/TableProducer/Converters/tracksExtraConverter.cxx | 1 + Common/TableProducer/Converters/tracksExtraV002Converter.cxx | 2 ++ Common/TableProducer/Converters/v0converter.cxx | 1 + Common/TableProducer/Converters/zdcConverter.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx | 1 + .../Dilepton/TableProducer/Converters/electronConverter2.cxx | 1 + .../Dilepton/TableProducer/Converters/electronConverter3.cxx | 1 + .../Dilepton/TableProducer/Converters/electronConverter4.cxx | 2 ++ .../Dilepton/TableProducer/Converters/electronConverter5.cxx | 3 +++ .../Dilepton/TableProducer/Converters/electronConverter6.cxx | 1 + .../Dilepton/TableProducer/Converters/eventCentConverter1.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx | 2 ++ PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx | 1 + .../Dilepton/TableProducer/Converters/eventMultConverter1.cxx | 1 + .../Dilepton/TableProducer/Converters/eventNormConverter1.cxx | 1 + .../Dilepton/TableProducer/Converters/eventNormConverter2.cxx | 1 + .../TableProducer/Converters/mcParticleConverter1.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx | 1 + .../TableProducer/Converters/muonSelfIdConverter1.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/qvecConverter.cxx | 1 + PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx | 1 + .../TableProducer/Converters/converterEmeventPmevent.cxx | 1 + .../PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx | 1 + .../PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx | 1 + .../TableProducer/Converters/v0photonIdConverter1.cxx | 1 + .../Tasks/Converters/electronFromDalitzConverter1.cxx | 1 + PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx | 2 ++ .../PhotonMeson/Tasks/Converters/skimEmcClusterConverter.cxx | 1 + .../Strangeness/Converters/stracentconverter.cxx | 1 + .../Strangeness/Converters/stracentconverter2.cxx | 1 + .../Strangeness/Converters/stradautracksconverter.cxx | 1 + .../Strangeness/Converters/stradautracksextraconverter.cxx | 1 + .../Strangeness/Converters/stradautracksextraconverter2.cxx | 1 + .../Strangeness/Converters/stradautracksextraconverter3.cxx | 1 + .../Strangeness/Converters/stradautrackstofpidconverter.cxx | 1 + .../Strangeness/Converters/stradautrackstofpidconverter2.cxx | 2 ++ .../Strangeness/Converters/stradautrackstofpidconverter3.cxx | 2 ++ .../Strangeness/Converters/stradautrackstpcpidconverter.cxx | 1 + .../Strangeness/Converters/straevselsconverter.cxx | 1 + .../Strangeness/Converters/straevselsconverter2.cxx | 1 + .../Strangeness/Converters/straevselsconverter2rawcents.cxx | 1 + .../Strangeness/Converters/straevselsconverter2rawcents2.cxx | 1 + .../Strangeness/Converters/straevselsconverter2rawcents3.cxx | 1 + .../Strangeness/Converters/straevselsconverter3.cxx | 1 + .../Strangeness/Converters/straevselsconverter4.cxx | 1 + .../Strangeness/Converters/straevselsconverter5.cxx | 1 + .../Strangeness/Converters/stramccollisionconverter.cxx | 1 + .../Strangeness/Converters/stramccollisionconverter2.cxx | 1 + .../Strangeness/Converters/stramccollmultconverter.cxx | 1 + .../Strangeness/Converters/strarawcentsconverter.cxx | 2 ++ .../Strangeness/Converters/strarawcentsconverter2v4.cxx | 1 + .../Strangeness/Converters/strastampsconverter.cxx | 1 + .../TableProducer/Strangeness/Converters/v0coresconverter.cxx | 1 + .../Strangeness/Converters/v0coresconverter2.cxx | 1 + .../Strangeness/Converters/v0mlscoresconverter.cxx | 4 ++++ .../Converters/UDCollisionSelExtrasConverter.cxx | 1 + .../Converters/UDCollisionSelExtrasV002Converter.cxx | 2 ++ .../Converters/UDCollisionSelExtrasV003Converter.cxx | 3 +++ PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx | 1 + PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx | 1 + 81 files changed, 99 insertions(+) diff --git a/Common/TableProducer/Converters/bcConverter.cxx b/Common/TableProducer/Converters/bcConverter.cxx index a8d8ab7d6ed..c0dfb69ec7b 100644 --- a/Common/TableProducer/Converters/bcConverter.cxx +++ b/Common/TableProducer/Converters/bcConverter.cxx @@ -24,6 +24,7 @@ struct bcConverter { void process(aod::BCs_000 const& bcTable) { + bc_001.reserve(bcTable.size()); for (auto& bc : bcTable) { constexpr uint64_t lEmptyTriggerInputs = 0; bc_001(bc.runNumber(), bc.globalBC(), bc.triggerMask(), lEmptyTriggerInputs); diff --git a/Common/TableProducer/Converters/bcFlagsCreator.cxx b/Common/TableProducer/Converters/bcFlagsCreator.cxx index 4d10272e1d7..54b434ee139 100644 --- a/Common/TableProducer/Converters/bcFlagsCreator.cxx +++ b/Common/TableProducer/Converters/bcFlagsCreator.cxx @@ -25,6 +25,7 @@ struct bcFlagsCreator { void process(aod::BCs const& bcTable) { + bcFlags.reserve(bcTable.size()); for (int64_t i = 0; i < bcTable.size(); ++i) { bcFlags(0); } diff --git a/Common/TableProducer/Converters/caloLabelConverter.cxx b/Common/TableProducer/Converters/caloLabelConverter.cxx index 7716abf964f..03b4b1fbec1 100644 --- a/Common/TableProducer/Converters/caloLabelConverter.cxx +++ b/Common/TableProducer/Converters/caloLabelConverter.cxx @@ -27,6 +27,7 @@ struct caloLabelConverter { { std::vector amplitude = {0}; std::vector particleId = {0}; + McCaloLabels_001.reserve(mccalolabelTable.size()); for (auto& mccalolabel : mccalolabelTable) { particleId[0] = mccalolabel.mcParticleId(); // Repopulate new table diff --git a/Common/TableProducer/Converters/collisionConverter.cxx b/Common/TableProducer/Converters/collisionConverter.cxx index d6d27dcdaf3..0f92b09065f 100644 --- a/Common/TableProducer/Converters/collisionConverter.cxx +++ b/Common/TableProducer/Converters/collisionConverter.cxx @@ -41,6 +41,7 @@ struct collisionConverter { void process(aod::Collisions_000 const& collisionTable) { float negtolerance = -1.0f * tolerance; + Collisions_001.reserve(collisionTable.size()); for (auto& collision : collisionTable) { float lYY = collision.covXZ(); float lXZ = collision.covYY(); diff --git a/Common/TableProducer/Converters/fddConverter.cxx b/Common/TableProducer/Converters/fddConverter.cxx index d7f359e6f68..b3d0e42ab1c 100644 --- a/Common/TableProducer/Converters/fddConverter.cxx +++ b/Common/TableProducer/Converters/fddConverter.cxx @@ -25,6 +25,7 @@ struct FddConverter { void process(aod::FDDs_000 const& fdd_000) { + fdd_001.reserve(fdd_000.size()); for (auto& p : fdd_000) { int16_t chargeA[8] = {0u}; int16_t chargeC[8] = {0u}; diff --git a/Common/TableProducer/Converters/hmpConverter.cxx b/Common/TableProducer/Converters/hmpConverter.cxx index ae423c0c9e8..4c34c42eb6e 100644 --- a/Common/TableProducer/Converters/hmpConverter.cxx +++ b/Common/TableProducer/Converters/hmpConverter.cxx @@ -25,6 +25,7 @@ struct hmpConverter { void process(aod::HMPID_000 const& hmpLegacy, aod::Tracks const&) { + HMPID_001.reserve(hmpLegacy.size()); for (auto& hmpData : hmpLegacy) { float phots[] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; diff --git a/Common/TableProducer/Converters/mcCollisionConverter.cxx b/Common/TableProducer/Converters/mcCollisionConverter.cxx index 290ce3d13dd..b37bd9da719 100644 --- a/Common/TableProducer/Converters/mcCollisionConverter.cxx +++ b/Common/TableProducer/Converters/mcCollisionConverter.cxx @@ -21,6 +21,7 @@ struct mcCollisionConverter { void process(aod::McCollisions_000 const& mcCollisionTable) { + mcCollisions_001.reserve(mcCollisionTable.size()); for (auto& mcCollision : mcCollisionTable) { // Repopulate new table diff --git a/Common/TableProducer/Converters/mcConverter.cxx b/Common/TableProducer/Converters/mcConverter.cxx index 4f18556f8a9..f166ef3d485 100644 --- a/Common/TableProducer/Converters/mcConverter.cxx +++ b/Common/TableProducer/Converters/mcConverter.cxx @@ -25,6 +25,7 @@ struct McConverter { void process(aod::StoredMcParticles_000 const& mcParticles_000) { + mcParticles_001.reserve(mcParticles_000.size()); for (auto& p : mcParticles_000) { std::vector mothers; diff --git a/Common/TableProducer/Converters/mftTracksConverter.cxx b/Common/TableProducer/Converters/mftTracksConverter.cxx index 175e9610f4f..4b1d9950b37 100644 --- a/Common/TableProducer/Converters/mftTracksConverter.cxx +++ b/Common/TableProducer/Converters/mftTracksConverter.cxx @@ -33,6 +33,7 @@ struct MftTracksConverter { Produces mftTracks_001; void process(aod::MFTTracks_000 const& mftTracks_000) { + mftTracks_001.reserve(mftTracks_000.size()); for (const auto& track0 : mftTracks_000) { uint64_t mftClusterSizesAndTrackFlags = 0; diff --git a/Common/TableProducer/Converters/multMCExtrasConverter.cxx b/Common/TableProducer/Converters/multMCExtrasConverter.cxx index 56d6233690d..bb65e450465 100644 --- a/Common/TableProducer/Converters/multMCExtrasConverter.cxx +++ b/Common/TableProducer/Converters/multMCExtrasConverter.cxx @@ -23,6 +23,7 @@ struct MultMCExtrasConverter { Produces multMCExtras_001; void process(aod::MultMCExtras_000 const& multMCExtras_000) { + multMCExtras_001.reserve(multMCExtras_000.size()); for (const auto& r : multMCExtras_000) { multMCExtras_001(r.multMCFT0A(), r.multMCFT0C(), 0, 0, 0, r.multMCNParticlesEta05(), diff --git a/Common/TableProducer/Converters/multsExtraConverter.cxx b/Common/TableProducer/Converters/multsExtraConverter.cxx index 36b7f70d33a..4f9aeb73f12 100644 --- a/Common/TableProducer/Converters/multsExtraConverter.cxx +++ b/Common/TableProducer/Converters/multsExtraConverter.cxx @@ -23,6 +23,7 @@ struct MultsExtraConverter { Produces multsExtra_001; void process(aod::MultsExtra_000 const& multsExtra_000) { + multsExtra_001.reserve(multsExtra_000.size()); for (const auto& r : multsExtra_000) { multsExtra_001(r.multPVTotalContributors(), r.multPVChi2(), r.multCollisionTimeRes(), r.multRunNumber(), r.multPVz(), r.multSel8(), diff --git a/Common/TableProducer/Converters/run2bcinfosConverter.cxx b/Common/TableProducer/Converters/run2bcinfosConverter.cxx index fd0f43f3fda..7f08c814df7 100644 --- a/Common/TableProducer/Converters/run2bcinfosConverter.cxx +++ b/Common/TableProducer/Converters/run2bcinfosConverter.cxx @@ -21,6 +21,7 @@ struct Run2BCInfosConverter { Produces Run2BCInfos_001; void process(aod::Run2BCInfos_000 const& Run2BCInfos_000) { + Run2BCInfos_001.reserve(Run2BCInfos_000.size()); for (const auto& entry : Run2BCInfos_000) { Run2BCInfos_001(entry.eventCuts(), diff --git a/Common/TableProducer/Converters/run2tracksExtraConverter.cxx b/Common/TableProducer/Converters/run2tracksExtraConverter.cxx index 2d321ee06fb..7b288c1f1d7 100644 --- a/Common/TableProducer/Converters/run2tracksExtraConverter.cxx +++ b/Common/TableProducer/Converters/run2tracksExtraConverter.cxx @@ -21,6 +21,7 @@ struct Run2TracksExtraConverter { Produces Run2TrackExtras_001; void process(aod::Run2TrackExtras_000 const& Run2TrackExtras_000) { + Run2TrackExtras_001.reserve(Run2TrackExtras_000.size()); for (const auto& track0 : Run2TrackExtras_000) { Run2TrackExtras_001(track0.itsSignal(), 0); diff --git a/Common/TableProducer/Converters/trackQA002Converter.cxx b/Common/TableProducer/Converters/trackQA002Converter.cxx index 34e1bac2363..f0b53d8b91f 100644 --- a/Common/TableProducer/Converters/trackQA002Converter.cxx +++ b/Common/TableProducer/Converters/trackQA002Converter.cxx @@ -25,6 +25,7 @@ struct TrackQAConverter002 { void process000(aod::TracksQA_000 const& tracksQA_000) { + tracksQA_002.reserve(tracksQA_000.size()); for (const auto& trackQA : tracksQA_000) { tracksQA_002( trackQA.trackId(), @@ -59,6 +60,7 @@ struct TrackQAConverter002 { void process001(aod::TracksQA_001 const& tracksQA_001) { + tracksQA_002.reserve(tracksQA_001.size()); for (const auto& trackQA : tracksQA_001) { tracksQA_002( trackQA.trackId(), diff --git a/Common/TableProducer/Converters/trackQA003Converter.cxx b/Common/TableProducer/Converters/trackQA003Converter.cxx index 4b6e0c7b2bd..407c37c6727 100644 --- a/Common/TableProducer/Converters/trackQA003Converter.cxx +++ b/Common/TableProducer/Converters/trackQA003Converter.cxx @@ -25,6 +25,7 @@ struct TrackQAConverter003 { void process000(aod::TracksQA_000 const& tracksQA_000) { + tracksQA_003.reserve(tracksQA_000.size()); for (const auto& trackQA : tracksQA_000) { tracksQA_003( trackQA.trackId(), @@ -60,6 +61,7 @@ struct TrackQAConverter003 { void process001(aod::TracksQA_001 const& tracksQA_001) { + tracksQA_003.reserve(tracksQA_001.size()); for (const auto& trackQA : tracksQA_001) { tracksQA_003( trackQA.trackId(), @@ -95,6 +97,7 @@ struct TrackQAConverter003 { void process002(aod::TracksQA_002 const& tracksQA_002) { + tracksQA_003.reserve(tracksQA_002.size()); for (const auto& trackQA : tracksQA_002) { tracksQA_003( trackQA.trackId(), diff --git a/Common/TableProducer/Converters/trackQAConverter.cxx b/Common/TableProducer/Converters/trackQAConverter.cxx index 25200812076..5a3b3cad4e0 100644 --- a/Common/TableProducer/Converters/trackQAConverter.cxx +++ b/Common/TableProducer/Converters/trackQAConverter.cxx @@ -24,6 +24,7 @@ struct trackQAConverter { void process(aod::TracksQA_000 const& tracksQA_000) { + tracksQA_001.reserve(tracksQA_000.size()); for (const auto& trackQA : tracksQA_000) { tracksQA_001( trackQA.trackId(), diff --git a/Common/TableProducer/Converters/tracksExtraConverter.cxx b/Common/TableProducer/Converters/tracksExtraConverter.cxx index 0366a84dd8f..5aced20d1de 100644 --- a/Common/TableProducer/Converters/tracksExtraConverter.cxx +++ b/Common/TableProducer/Converters/tracksExtraConverter.cxx @@ -33,6 +33,7 @@ struct TracksExtraConverter { Produces tracksExtra_001; void process(aod::TracksExtra_000 const& tracksExtra_000) { + tracksExtra_001.reserve(tracksExtra_000.size()); for (const auto& track0 : tracksExtra_000) { diff --git a/Common/TableProducer/Converters/tracksExtraV002Converter.cxx b/Common/TableProducer/Converters/tracksExtraV002Converter.cxx index d45eb6e2c09..b6070faa636 100644 --- a/Common/TableProducer/Converters/tracksExtraV002Converter.cxx +++ b/Common/TableProducer/Converters/tracksExtraV002Converter.cxx @@ -36,6 +36,7 @@ struct TracksExtraV002Converter { void processV000ToV002(aod::TracksExtra_000 const& tracksExtra_000) { + tracksExtra_002.reserve(tracksExtra_000.size()); for (const auto& track0 : tracksExtra_000) { @@ -75,6 +76,7 @@ struct TracksExtraV002Converter { void processV001ToV002(aod::TracksExtra_001 const& tracksExtra_001) { + tracksExtra_002.reserve(tracksExtra_001.size()); for (const auto& track1 : tracksExtra_001) { diff --git a/Common/TableProducer/Converters/v0converter.cxx b/Common/TableProducer/Converters/v0converter.cxx index 38c513681b4..ffe1fc35472 100644 --- a/Common/TableProducer/Converters/v0converter.cxx +++ b/Common/TableProducer/Converters/v0converter.cxx @@ -25,6 +25,7 @@ struct V0Converter { void process(aod::V0s_001 const& v0s) { + v0s_002.reserve(v0s.size()); for (auto& v0 : v0s) { uint8_t bitMask = static_cast(1); // first bit on v0s_002(v0.collisionId(), v0.posTrackId(), v0.negTrackId(), bitMask); diff --git a/Common/TableProducer/Converters/zdcConverter.cxx b/Common/TableProducer/Converters/zdcConverter.cxx index 99a88d2b6ca..b03707fe150 100644 --- a/Common/TableProducer/Converters/zdcConverter.cxx +++ b/Common/TableProducer/Converters/zdcConverter.cxx @@ -30,6 +30,7 @@ struct zdcConverter { void process(aod::Zdcs_000 const& zdcLegacy, aod::BCs const&) { + Zdcs_001.reserve(zdcLegacy.size()); for (auto& zdcData : zdcLegacy) { // Get legacy information, please auto bc = zdcData.bc(); diff --git a/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx index 33aed751377..32d14783f02 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx @@ -31,6 +31,7 @@ struct bcConverter1 { void process(aod::EMBCs_000 const& bcs) { + bc_001.reserve(bcs.size()); for (const auto& bc : bcs) { bc_001(o2::aod::emevsel::reduceSelectionBit(bc), bc.rct_raw()); } // end of bc loop diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx index 86ed8dde8bd..7fd694068e4 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx @@ -31,6 +31,7 @@ struct electronConverter2 { void process(aod::EMPrimaryElectrons_001 const& tracks) { + track_002.reserve(tracks.size()); for (const auto& track : tracks) { track_002(track.collisionId(), track.trackId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx index c543037fbd1..a77f8a61be5 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx @@ -31,6 +31,7 @@ struct electronConverter3 { void process(aod::EMPrimaryElectrons_002 const& tracks) { + track_003.reserve(tracks.size()); for (const auto& track : tracks) { track_003(track.collisionId(), track.trackId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx index e9bc1fd78b2..968f7525764 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx @@ -34,6 +34,7 @@ struct electronConverter4 { using MyElectrons002 = soa::Join; void process002to004(MyElectrons002 const& tracks) { + track_004.reserve(tracks.size()); for (const auto& track : tracks) { track_004(track.collisionId(), track.trackId(), @@ -78,6 +79,7 @@ struct electronConverter4 { using MyElectrons003 = soa::Join; void process003to004(MyElectrons003 const& tracks) { + track_004.reserve(tracks.size()); for (const auto& track : tracks) { track_004(track.collisionId(), track.trackId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx index 5367e71f597..faf52e3ff99 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx @@ -34,6 +34,7 @@ struct electronConverter5 { using MyElectrons002 = soa::Join; void process002to005(MyElectrons002 const& tracks) { + track_005.reserve(tracks.size()); for (const auto& track : tracks) { track_005(track.collisionId(), track.trackId(), @@ -79,6 +80,7 @@ struct electronConverter5 { using MyElectrons003 = soa::Join; void process003to005(MyElectrons003 const& tracks) { + track_005.reserve(tracks.size()); for (const auto& track : tracks) { track_005(track.collisionId(), track.trackId(), @@ -123,6 +125,7 @@ struct electronConverter5 { void process004to005(aod::EMPrimaryElectrons_004 const& tracks) { + track_005.reserve(tracks.size()); for (const auto& track : tracks) { track_005(track.collisionId(), track.trackId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx index 7506fe10688..f5113e7aae9 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx @@ -31,6 +31,7 @@ struct electronConverter6 { void process(aod::EMPrimaryElectrons_005 const& tracks) { + track_006.reserve(tracks.size()); for (const auto& track : tracks) { track_006(track.collisionId(), track.trackId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx index ed040916f03..143a92f353b 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx @@ -31,6 +31,7 @@ struct eventCentConverter1 { void process(aod::EMEventsCent_000 const& collisions) { + cent_001.reserve(collisions.size()); for (const auto& collision : collisions) { cent_001( collision.centFT0M(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx index 414241dea5c..7b9fdb57058 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx @@ -31,6 +31,7 @@ struct eventConverter2 { void process(aod::EMEvents_001 const& collisions) { + event_002.reserve(collisions.size()); for (const auto& collision : collisions) { event_002( collision.globalIndex(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx index 894d3d2984c..141ba63382c 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx @@ -31,6 +31,7 @@ struct eventConverter3 { void process(aod::EMEvents_002 const& collisions) { + event_003.reserve(collisions.size()); for (const auto& collision : collisions) { event_003( collision.globalIndex(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx index ff12b6a1405..f4521c0ca6e 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx @@ -33,6 +33,7 @@ struct eventConverter4 { void process003to004(aod::EMEvents_003 const& collisions) { + event_004.reserve(collisions.size()); for (const auto& collision : collisions) { event_004( collision.globalIndex(), @@ -51,6 +52,7 @@ struct eventConverter4 { void processAlias(aod::EMEvents_003 const& collisions) { + eventalias_000.reserve(collisions.size()); for (const auto& collision : collisions) { eventalias_000( collision.alias_raw()); diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx index f4298c119c6..46a26e300e2 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx @@ -91,6 +91,7 @@ struct eventConverter5 { void process004to005(aod::EMEvents_004 const& collisions) { + event_005.reserve(collisions.size()); for (const auto& collision : collisions) { event_005( collision.globalIndex(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx index c1c8cd61a2a..e666375387d 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx @@ -31,6 +31,7 @@ struct eventMultConverter1 { void process(aod::EMEventsMult_000 const& collisions) { + mult_001.reserve(collisions.size()); for (const auto& collision : collisions) { mult_001( collision.multFT0A(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx index f51122a77a2..e2a848c3fbb 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx @@ -33,6 +33,7 @@ struct eventNormConverter1 { void process(aod::EMEventNormInfos_000 const& collisions) { + event_001.reserve(collisions.size()); for (const auto& collision : collisions) { event_001( collision.selection_raw(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx index 79dc86b136c..b42f9aa04fc 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx @@ -33,6 +33,7 @@ struct eventNormConverter2 { void process(aod::EMEventNormInfos_001 const& collisions) { + event_002.reserve(collisions.size()); for (const auto& collision : collisions) { int8_t posZint8 = static_cast(collision.posZ() * 2.f); diff --git a/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx index 92df1709c3d..6b92eee9a8e 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx @@ -33,6 +33,7 @@ struct mcParticleConverter1 { void process(aod::EMMCParticles_000 const& mcParticles) { + mcParticle_001.reserve(mcParticles.size()); for (const auto& mcParticle : mcParticles) { // LOGF(info, "mcParticles.emmceventId() = %d, mcParticle.mothersIds().size() = %d, mcParticle.daughtersIds().size() = %d", mcParticle.emmceventId(), mcParticle.mothersIds().size(), mcParticle.daughtersIds().size()); diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx index d0f5596f445..4cf40d3fe88 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx @@ -31,6 +31,7 @@ struct muonConverter1 { void process(aod::EMPrimaryMuons_000 const& muons) { + muon_001.reserve(muons.size()); for (const auto& muon : muons) { muon_001( muon.collisionId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx index 7bc2a63916b..e0f214bca00 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx @@ -31,6 +31,7 @@ struct muonConverter2 { void process(aod::EMPrimaryMuons_001 const& muons) { + muon_002.reserve(muons.size()); for (const auto& muon : muons) { muon_002( muon.collisionId(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx index 031c853b12d..fdf440d1ead 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx @@ -33,6 +33,7 @@ struct muonSelfIdConverter1 { void process(aod::EMGlobalMuonSelfIds_000 const& muons) { + muon_001.reserve(muons.size()); for (const auto& muon : muons) { muon_001(std::vector{}, muon.globalMuonsWithSameMFTIds()); } // end of muon loop diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx index 340b74077c9..edf53c43f75 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx @@ -31,6 +31,7 @@ struct qvec2Converter0 { void process(aod::EMEventsQvec_001 const& collisions) { + qvec2_000.reserve(collisions.size()); for (const auto& collision : collisions) { qvec2_000( collision.q2xft0m(), collision.q2yft0m(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx index 2775c7275f7..27b7b1bf038 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx @@ -31,6 +31,7 @@ struct qvec3Converter0 { void process(aod::EMEventsQvec_001 const& collisions) { + qvec3_000.reserve(collisions.size()); for (const auto& collision : collisions) { qvec3_000( collision.q3xft0m(), collision.q3yft0m(), diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvecConverter.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvecConverter.cxx index d0164dac5ab..ca80548669b 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/qvecConverter.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/qvecConverter.cxx @@ -29,6 +29,7 @@ struct QvecConverter { void process(aod::EMEventsQvec_000 const& emEventsQVec) { + qvec001.reserve(emEventsQVec.size()); for (const auto& qvec : emEventsQVec) { constexpr float EmptyV0 = -999.f; qvec001(qvec.q2xft0m(), qvec.q2yft0m(), qvec.q2xft0a(), qvec.q2yft0a(), qvec.q2xft0c(), qvec.q2yft0c(), EmptyV0, EmptyV0, qvec.q2xbpos(), qvec.q2ybpos(), qvec.q2xbneg(), qvec.q2ybneg(), qvec.q2xbtot(), qvec.q2ybtot(), qvec.q3xft0m(), qvec.q3yft0m(), qvec.q3xft0a(), qvec.q3yft0a(), qvec.q3xft0c(), qvec.q3yft0c(), EmptyV0, EmptyV0, qvec.q3xbpos(), qvec.q3ybpos(), qvec.q3xbneg(), qvec.q3ybneg(), qvec.q3xbtot(), qvec.q3ybtot()); diff --git a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx index bcdce816813..061affca561 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx @@ -31,6 +31,7 @@ struct trackConverter1 { void process(aod::EMPrimaryTracks_000 const& tracks) { + track_001.reserve(tracks.size()); for (const auto& track : tracks) { track_001( // track.collisionId(), diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx index cd159115d4f..4909b000e3e 100644 --- a/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx @@ -31,6 +31,7 @@ struct ConverterEmeventPmevent { void process(EMEvents_004 const& collisions) { + pmEvents.reserve(collisions.size()); for (const auto& collision : collisions) { pmEvents( collision.collisionId(), diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx index 9c7027076de..f409f11c0bf 100644 --- a/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx @@ -26,6 +26,7 @@ struct emcIdConverter1 { void process(aod::EMCEMEventIds_000 const& ids) { + id_001.reserve(ids.size()); for (const auto& id : ids) { id_001(id.emeventId()); } // end of id loop diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx index d6d188abb96..4e69d5e6541 100644 --- a/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx @@ -26,6 +26,7 @@ struct phosIdConverter1 { void process(aod::PHOSEMEventIds_000 const& ids) { + id_001.reserve(ids.size()); for (const auto& id : ids) { id_001(id.emeventId()); } // end of id loop diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx index c3b82a8b204..15a1b2c2fca 100644 --- a/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx @@ -26,6 +26,7 @@ struct v0photonIdConverter1 { void process(aod::V0KFEMEventIds_000 const& ids) { + id_001.reserve(ids.size()); for (const auto& id : ids) { id_001(id.emeventId()); } // end of id loop diff --git a/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx index cd54adedfb3..de371f4db9a 100644 --- a/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx +++ b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx @@ -31,6 +31,7 @@ struct electronFromDalitzConverter1 { void process(aod::EMPrimaryElectronsFromDalitz_000 const& tracks) { + electron_001.reserve(tracks.size()); for (const auto& track : tracks) { electron_001(track.collisionId(), track.trackId(), diff --git a/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx index a8277d122db..35f3c5c24d3 100644 --- a/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx +++ b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx @@ -32,6 +32,7 @@ struct pcmConverter1 { void process(aod::V0PhotonsKF_000 const& v0s, aod::V0Legs_000 const& v0legs) { + v0photon_001.reserve(v0s.size()); for (auto& v0 : v0s) { v0photon_001( v0.collisionId(), @@ -56,6 +57,7 @@ struct pcmConverter1 { v0.chiSquareNDF()); } // end of v0 loop + v0leg_001.reserve(v0legs.size()); for (auto& v0leg : v0legs) { v0leg_001( v0leg.collisionId(), diff --git a/PWGEM/PhotonMeson/Tasks/Converters/skimEmcClusterConverter.cxx b/PWGEM/PhotonMeson/Tasks/Converters/skimEmcClusterConverter.cxx index d1809162bbc..11721c5d12c 100644 --- a/PWGEM/PhotonMeson/Tasks/Converters/skimEmcClusterConverter.cxx +++ b/PWGEM/PhotonMeson/Tasks/Converters/skimEmcClusterConverter.cxx @@ -41,6 +41,7 @@ struct SkimEmcClusterConverter { { std::vector vDummy = {}; std::vector vPhi, vEta, vPt, vP; + tableGammaEMCReco001.reserve(emcClusters.size()); for (const auto& emcCluster : emcClusters) { // using convertSpanToVector is just a temporal solution, since right now tables return gsl::span // while filling a table needs std::span which can not be transformed. So going over std::vector diff --git a/PWGLF/TableProducer/Strangeness/Converters/stracentconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter.cxx index da4a817f834..b0da93f7686 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stracentconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter.cxx @@ -24,6 +24,7 @@ struct stracentconverter { void process(aod::StraCents_000 const& straCents_000) { + straCents_001.reserve(straCents_000.size()); for (auto& values : straCents_000) { straCents_001(values.centFT0M(), values.centFT0A(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx index a56d834c697..1d9fe4f3f36 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx @@ -24,6 +24,7 @@ struct stracentconverter2 { void process(aod::StraCents_001 const& straCents_001) { + straCents_002.reserve(straCents_001.size()); for (auto& values : straCents_001) { straCents_002(values.centFT0M(), values.centFT0A(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautracksconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautracksconverter.cxx index 26a68b115f2..3ae50ec076a 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautracksconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautracksconverter.cxx @@ -35,6 +35,7 @@ struct stradautracksconverter { void process(soa::Join const& v0s, soa::Join const& cascs, aod::DauTrackExtras const& dauTracks) { // prepare arrays with the relevant information + dautracktofpids.reserve(dauTracks.size()); std::vector lLengths(dauTracks.size(), 1.e+6), lTOFSignals(dauTracks.size(), -1e+3f), lTOFEvTimes(dauTracks.size(), -1e+3f); for (const auto& v0 : v0s) { lLengths[v0.posTrackExtraId()] = v0.posTOFLengthToPV(); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter.cxx index 6ec2cffbbc9..ebbeb37acd7 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter.cxx @@ -24,6 +24,7 @@ struct stradautracksextraconverter { void process(aod::DauTrackExtras_000 const& dauTrackExtras_000) { + dauTrackExtras_001.reserve(dauTrackExtras_000.size()); for (auto& values : dauTrackExtras_000) { dauTrackExtras_001(0, values.detectorMap(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter2.cxx index c6e373898d4..f22fea5ef47 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter2.cxx @@ -26,6 +26,7 @@ struct stradautracksextraconverter2 { void process(aod::DauTrackExtras_001 const& dauTrackExtras_001) { + dauTrackExtras_002.reserve(dauTrackExtras_001.size()); for (auto& values : dauTrackExtras_001) { const int maxFindable = 130; // synthetic findable to ensure range is ok int findableMinusFound = maxFindable - values.tpcClusters(); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter3.cxx index 1697f64705e..432303ffd1d 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautracksextraconverter3.cxx @@ -24,6 +24,7 @@ struct stradautracksextraconverter3 { void process(aod::DauTrackExtras_002 const& dauTrackExtras_002) { + dauTrackExtras_003.reserve(dauTrackExtras_002.size()); for (auto& values : dauTrackExtras_002) { dauTrackExtras_003(values.itsChi2PerNcl(), -1 /* dummy tpcChi2PerNcl value */, diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx index a3cabe45b2d..185bf7017fc 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter.cxx @@ -35,6 +35,7 @@ struct stradautrackstofpidconverter { void process(soa::Join const& v0s, soa::Join const& cascs, aod::DauTrackExtras const& dauTracks) { // prepare arrays with the relevant information + dautracktofpids.reserve(dauTracks.size()); std::vector lLengths(dauTracks.size(), 1.e+6), lTOFSignals(dauTracks.size(), -1e+3f), lTOFEvTimes(dauTracks.size(), -1e+3f); for (const auto& v0 : v0s) { lLengths[v0.posTrackExtraId()] = v0.posTOFLengthToPV(); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx index de6dde54201..5c1b9b508c2 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter2.cxx @@ -37,6 +37,7 @@ struct stradautrackstofpidconverter2 { void process(aod::StraCollisions const& collisions, soa::Join const& dauTracks, soa::Join const& v0s) { // create new TOFPIDs + dautracktofpids.reserve(dauTracks.size()); for (int ii = 0; ii < dauTracks.size(); ii++) { auto dauTrack = dauTracks.rawIteratorAt(ii); dautracktofpids(-1, -1, dauTrack.tofSignal(), dauTrack.tofEvTime(), dauTrack.length(), 0.0f); @@ -59,6 +60,7 @@ struct stradautrackstofpidconverter2 { collisionNtracks[v0.straCollisionId()]++; } } + straEvTimes.reserve(collisions.size()); for (const auto& collision : collisions) { if (collisionNtracks[collision.globalIndex()] > 0) { collisionEventTime[collision.globalIndex()] /= static_cast(collisionNtracks[collision.globalIndex()]); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx index c03cbead81e..620e8cfad43 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstofpidconverter3.cxx @@ -33,6 +33,7 @@ struct stradautrackstofpidconverter3 { void process(aod::DauTrackTOFPIDs_001 const& dauTracks, aod::StraEvTimes_000 const& straEvTimes_000) { // create new TOFPIDs + dautracktofpids.reserve(dauTracks.size()); for (const auto& dauTrack : dauTracks) { dautracktofpids( -1, @@ -43,6 +44,7 @@ struct stradautrackstofpidconverter3 { dauTrack.length(), 0.0f); } + straEvTimes.reserve(straEvTimes_000.size()); for (const auto& value : straEvTimes_000) { straEvTimes(value.eventTime(), 999.0f /*dummy event time error for TOF*/); } diff --git a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstpcpidconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstpcpidconverter.cxx index bba6043dad4..8aef7eacd92 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stradautrackstpcpidconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stradautrackstpcpidconverter.cxx @@ -24,6 +24,7 @@ struct stradautrackstpcpidconverter { void process(aod::DauTrackTPCPIDs_000 const& v000s) { + dautrackpcpids.reserve(v000s.size()); for (int ii = 0; ii < v000s.size(); ii++) { auto dauTrackTPCPID = v000s.rawIteratorAt(ii); dautrackpcpids(dauTrackTPCPID.tpcSignal(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx index bdcbc4b5f68..c75002e9280 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter.cxx @@ -24,6 +24,7 @@ struct straevselsconverter { void process(soa::Join const& straEvSels_000_RawCents_004) { + straEvSels_001.reserve(straEvSels_000_RawCents_004.size()); for (auto& values : straEvSels_000_RawCents_004) { straEvSels_001(values.sel8(), values.selection_raw(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx index 147a3c986fa..5c6293f07ab 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx @@ -25,6 +25,7 @@ struct straevselsconverter2 { void process(aod::StraEvSels_001 const& straEvSels_001) { + straEvSels_002.reserve(straEvSels_001.size()); for (auto& values : straEvSels_001) { straEvSels_002(values.sel8(), values.selection_raw(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents.cxx index 5a706d83cc6..42d9eedc133 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents.cxx @@ -24,6 +24,7 @@ struct straevselsconverter2rawcents { void process(aod::StraEvSels_001 const& straEvSels_001) { + straRawCents_004.reserve(straEvSels_001.size()); for (auto& values : straEvSels_001) { straRawCents_004(values.multFT0A(), values.multFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents2.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents2.cxx index edccbbfb5fe..7cd834daeba 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents2.cxx @@ -24,6 +24,7 @@ struct straevselsconverter2rawcents2 { void process(aod::StraEvSels_002 const& straEvSels_002) { + straRawCents_004.reserve(straEvSels_002.size()); for (auto& values : straEvSels_002) { straRawCents_004(values.multFT0A(), values.multFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents3.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents3.cxx index 157b40ffd24..a3419abeee7 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2rawcents3.cxx @@ -24,6 +24,7 @@ struct straevselsconverter2rawcents3 { void process(aod::StraEvSels_003 const& straEvSels_003) { + straRawCents_004.reserve(straEvSels_003.size()); for (auto& values : straEvSels_003) { straRawCents_004(values.multFT0A(), values.multFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx index e4ac27b2d59..9afd1c5e555 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx @@ -25,6 +25,7 @@ struct straevselsconverter3 { void process(aod::StraEvSels_002 const& straEvSels_002) { + straEvSels_003.reserve(straEvSels_002.size()); for (auto& values : straEvSels_002) { straEvSels_003(values.sel8(), values.selection_raw(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx index 7d092e76a65..a99fe4fc009 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx @@ -24,6 +24,7 @@ struct straevselsconverter4 { void process(aod::StraEvSels_003 const& straEvSels_003) { + straEvSels_004.reserve(straEvSels_003.size()); for (auto& values : straEvSels_003) { straEvSels_004(values.sel8(), values.selection_raw(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx index 17dc9544b14..d044b1fe842 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx @@ -90,6 +90,7 @@ struct straevselsconverter5 { void process(soa::Join const& straEvSels_004) { + straEvSels_005.reserve(straEvSels_004.size()); for (auto& values : straEvSels_004) { straEvSels_005(values.sel8(), values.selection_raw(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter.cxx index 8f35332bc8c..19d905712c5 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter.cxx @@ -24,6 +24,7 @@ struct stramccollisionconverter { void process(aod::StraMCCollisions_000 const& straMCcoll) { + straMCCollisions_001.reserve(straMCcoll.size()); for (auto& mccollision : straMCcoll) { straMCCollisions_001(mccollision.posX(), mccollision.posY(), mccollision.posZ(), mccollision.impactParameter(), 0.0f); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter2.cxx index c9c27af9a2b..fcb260477eb 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stramccollisionconverter2.cxx @@ -32,6 +32,7 @@ struct stramccollisionconverter2 { void process(aod::StraMCCollisions_001 const& straMCcoll) { + straMCCollisions_002.reserve(straMCcoll.size()); for (auto& mccollision : straMCcoll) { straMCCollisions_002(mccollision.posX(), mccollision.posY(), mccollision.posZ(), mccollision.impactParameter(), mccollision.eventPlaneAngle(), 0); diff --git a/PWGLF/TableProducer/Strangeness/Converters/stramccollmultconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/stramccollmultconverter.cxx index fbf6047b9fc..9566629cbcd 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/stramccollmultconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/stramccollmultconverter.cxx @@ -24,6 +24,7 @@ struct stramccollmultconverter { void process(aod::StraMCCollMults_000 const& straMCcolls) { + straMCCollMults_001.reserve(straMCcolls.size()); for (auto& straMCcoll : straMCcolls) { straMCCollMults_001(straMCcoll.multMCFT0A(), straMCcoll.multMCFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter.cxx index ad3f7d7a290..3eeb2d190cb 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter.cxx @@ -26,12 +26,14 @@ struct strarawcentsconverter { void process000to001(aod::StraRawCents_000 const& straRawCents_000) { + straRawCents_001.reserve(straRawCents_000.size()); for (auto& values : straRawCents_000) { straRawCents_001(values.multFT0A(), values.multFT0C(), values.multFV0A(), values.multNTracksPVeta1(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); } } void process002to003(aod::StraRawCents_002 const& straRawCents_002) { + straRawCents_003.reserve(straRawCents_002.size()); for (auto& values : straRawCents_002) { straRawCents_003(values.multFT0A(), values.multFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter2v4.cxx b/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter2v4.cxx index 656102b5fe4..38cf47b6e31 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter2v4.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/strarawcentsconverter2v4.cxx @@ -24,6 +24,7 @@ struct strarawcentsconverter2v4 { void process(aod::StraRawCents_003 const& straRawCents_003) { + straRawCents_004.reserve(straRawCents_003.size()); for (auto& values : straRawCents_003) { straRawCents_004(values.multFT0A(), values.multFT0C(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/strastampsconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/strastampsconverter.cxx index a99f769250f..49f739420b0 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/strastampsconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/strastampsconverter.cxx @@ -24,6 +24,7 @@ struct strastampsconverter { void process(aod::StraStamps_000 const& straStamps_000) { + straStamps_001.reserve(straStamps_000.size()); for (auto& values : straStamps_000) { straStamps_001(values.runNumber(), values.timestamp(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter.cxx index 78f09ec339a..1e3c6c46609 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter.cxx @@ -24,6 +24,7 @@ struct v0coresconverter { void process(aod::V0MCCores_000 const& v0MCCores_000) { + v0MCCores_001.reserve(v0MCCores_000.size()); for (auto& values : v0MCCores_000) { v0MCCores_001(0, values.pdgCode(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx index 3e0570c78bd..eb748858498 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/v0coresconverter2.cxx @@ -24,6 +24,7 @@ struct v0coresconverter2 { void process(aod::V0MCCores_001 const& v0MCCores_001) { + v0MCCores_002.reserve(v0MCCores_001.size()); for (auto& values : v0MCCores_001) { v0MCCores_002(0, values.pdgCode(), diff --git a/PWGLF/TableProducer/Strangeness/Converters/v0mlscoresconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/v0mlscoresconverter.cxx index c4ca9d75584..156c420b8a8 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/v0mlscoresconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/v0mlscoresconverter.cxx @@ -29,6 +29,10 @@ struct v0mlscoresconverter { void process(aod::V0Cores const& v0cores) { + gammaMLSelections.reserve(v0cores.size()); + lambdaMLSelections.reserve(v0cores.size()); + antiLambdaMLSelections.reserve(v0cores.size()); + k0ShortMLSelections.reserve(v0cores.size()); for (int64_t i = 0; i < v0cores.size(); ++i) { gammaMLSelections(-1); lambdaMLSelections(-1); diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx index 38ecb5abeb3..b6dc788f5a5 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx @@ -36,6 +36,7 @@ struct UDCollisionSelExtrasConverter { void process(o2::aod::UDCollisionSelExtras_000 const& collisions) { + udCollisionSelExtras_001.reserve(collisions.size()); for (const auto& collision : collisions) { diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx index d2b4d6408b4..4755212a975 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx @@ -41,6 +41,7 @@ struct UDCollisionSelExtrasV002Converter { void processV000ToV002(o2::aod::UDCollisionSelExtras_000 const& collisions) { + udCollisionSelExtras_002.reserve(collisions.size()); for (const auto& collision : collisions) { @@ -65,6 +66,7 @@ struct UDCollisionSelExtrasV002Converter { void processV001ToV002(o2::aod::UDCollisionSelExtras_001 const& collisions) { + udCollisionSelExtras_002.reserve(collisions.size()); for (const auto& collision : collisions) { diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx index e52b6fce784..dbd0f96b755 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx @@ -41,6 +41,7 @@ struct UDCollisionSelExtrasV003Converter { void processV000ToV003(o2::aod::UDCollisionSelExtras_000 const& collisions) { + udCollisionSelExtras_003.reserve(collisions.size()); for (const auto& collision : collisions) { @@ -66,6 +67,7 @@ struct UDCollisionSelExtrasV003Converter { void processV001ToV003(o2::aod::UDCollisionSelExtras_001 const& collisions) { + udCollisionSelExtras_003.reserve(collisions.size()); for (const auto& collision : collisions) { @@ -91,6 +93,7 @@ struct UDCollisionSelExtrasV003Converter { void processV002ToV003(o2::aod::UDCollisionSelExtras_002 const& collisions) { + udCollisionSelExtras_003.reserve(collisions.size()); for (const auto& collision : collisions) { diff --git a/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx index 99de6088fb4..7d9a218c174 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx @@ -36,6 +36,7 @@ struct UDCollisionsConverter { void process(o2::aod::UDCollisions_000 const& collisions) { + udCollisions_001.reserve(collisions.size()); for (const auto& collision : collisions) { diff --git a/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx index 4806232f490..d28bda5d962 100644 --- a/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx @@ -41,6 +41,7 @@ struct UDFwdTracksExtraConverter { { int trkType = 3; // trackType of MCH-MID tracks is 3 + udFwdTracksExtra_001.reserve(tracks.size()); for (const auto& track : tracks) { if (track.chi2MatchMCHMID() > 0) From fc19224ad1fc4d1ffb00a9fa8d7c858bac560fa7 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 3 Jun 2026 22:45:09 +0200 Subject: [PATCH 411/449] [PWGEM/Dilepton] add down sampling pion (#16526) --- .../treeCreatorElectronMLDDA.cxx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index 9f1019c3583..3df99ab199d 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -157,19 +157,21 @@ struct TreeCreatorElectronMLDDA { Configurable downscaling_kaon_highP{"downscaling_kaon_highP", 1.1, "down scaling factor to store kaon at high p"}; Configurable downscaling_proton_highP{"downscaling_proton_highP", 1.1, "down scaling factor to store proton at high p"}; - Configurable downscaling_electron_midP{"downscaling_electron_midP", 0.1, "down scaling factor to store electron at intermediate p"}; + Configurable downscaling_electron_midP{"downscaling_electron_midP", 0.05, "down scaling factor to store electron at intermediate p"}; + Configurable downscaling_pion_midP{"downscaling_pion_midP", 0.1, "down scaling factor to store pion at intermediate p"}; - Configurable downscaling_electron_lowP{"downscaling_electron_lowP", 0.01, "down scaling factor to store electron at low p"}; + Configurable downscaling_electron_lowP{"downscaling_electron_lowP", 0.005, "down scaling factor to store electron at low p"}; Configurable downscaling_pion_lowP{"downscaling_pion_lowP", 0.01, "down scaling factor to store pion at low p"}; Configurable downscaling_kaon_lowP{"downscaling_kaon_lowP", 1.1, "down scaling factor to store kaon at low p"}; - Configurable downscaling_proton_lowP{"downscaling_proton_lowP", 0.01, "down scaling factor to store proton at low p"}; + Configurable downscaling_proton_lowP{"downscaling_proton_lowP", 0.002, "down scaling factor to store proton at low p"}; Configurable mid_p_for_downscaling_electron{"mid_p_for_downscaling_electron", 0.8, "intermediate p to apply down scaling factor to store electron"}; + Configurable mid_p_for_downscaling_pion{"mid_p_for_downscaling_pion", 0.25, "intermediate p to apply down scaling factor to store pion"}; Configurable max_p_for_downscaling_electron{"max_p_for_downscaling_electron", 2.0, "max p to apply down scaling factor to store electron"}; - Configurable max_p_for_downscaling_pion{"max_p_for_downscaling_pion", 2.0, "max p to apply down scaling factor to store pion"}; + Configurable max_p_for_downscaling_pion{"max_p_for_downscaling_pion", 0.4, "max p to apply down scaling factor to store pion"}; Configurable max_p_for_downscaling_kaon{"max_p_for_downscaling_kaon", 0.0, "max p to apply down scaling factor to store kaon"}; - Configurable max_p_for_downscaling_proton{"max_p_for_downscaling_proton", 2.0, "max p to apply down scaling factor to store proton"}; + Configurable max_p_for_downscaling_proton{"max_p_for_downscaling_proton", 1e+10, "max p to apply down scaling factor to store proton"}; Configurable store_ele_band_only{"store_ele_band_only", true, "flag to store tracks around electron band only to reduce output size"}; Configurable reject_v0leg_with_itsib{"reject_v0leg_with_itsib", true, "flag to reject v0 leg with ITSib hits"}; @@ -180,7 +182,7 @@ struct TreeCreatorElectronMLDDA { Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; @@ -675,10 +677,14 @@ struct TreeCreatorElectronMLDDA { } } } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion)) { - if (track.tpcInnerParam() < max_p_for_downscaling_pion) { + if (track.tpcInnerParam() < mid_p_for_downscaling_pion) { if (dist01(engine) > downscaling_pion_lowP) { return; } + } else if (track.tpcInnerParam() < max_p_for_downscaling_pion) { + if (dist01(engine) > downscaling_pion_midP) { + return; + } } else { if (dist01(engine) > downscaling_pion_highP) { return; From 88074c49321f91b37eeb1c11b97831bbb4a72639 Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Thu, 4 Jun 2026 00:21:07 +0200 Subject: [PATCH 412/449] [PWGHF] Optimize CPU usage in UPC Lc task (#16527) --- PWGHF/D2H/Tasks/taskUpcLc.cxx | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskUpcLc.cxx b/PWGHF/D2H/Tasks/taskUpcLc.cxx index 0a445cbe505..17dd660bd49 100644 --- a/PWGHF/D2H/Tasks/taskUpcLc.cxx +++ b/PWGHF/D2H/Tasks/taskUpcLc.cxx @@ -116,6 +116,7 @@ struct HfTaskUpcLc { Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; Configurable fillTreeOnlySingleGap{"fillTreeOnlySingleGap", false, "Only fill the tree for candidates that pass the single-gap UPC events"}; Configurable fillTreeUpcQa{"fillTreeUpcQa", false, "Fill Tree for UPC QA"}; + Configurable fillHistQa{"fillHistQa", false, "Fill histograms for UPC detector QA"}; Configurable verticesWithUpc{"verticesWithUpc", false, "Consider vertices with UPC settings"}; Configurable zdcTimeThreshold{"zdcTimeThreshold", 2., "Threshold for ZNA/ZNC time"}; // CCDB configuration @@ -154,7 +155,7 @@ struct HfTaskUpcLc { } auto vbins = (std::vector)binsPt; - registry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{500, 0., 500}, {500, 0., 500}}}); + registry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{200, 0., 200}, {200, 0., 200}}}); registry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{100, 0., 10}, {100, 0., 10}}}); registry.add("Data/zdc/timeZNA_vs_timeZNC", "ZNA vs ZNC time;ZNA Time;ZNC time", {HistType::kTH2F, {{200, -10., 10}, {200, -10., 10}}}); registry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); @@ -195,6 +196,9 @@ struct HfTaskUpcLc { } const auto thisCollId = collision.globalIndex(); const auto& groupedLcCandidates = candidates.sliceBy(candLcPerCollision, thisCollId); + if (!fillTreeUpcQa && !fillHistQa && groupedLcCandidates.size() == 0) { + continue; + } const auto numPvContributors = collision.numContrib(); const auto& bc = collision.template bc_as(); @@ -232,27 +236,30 @@ struct HfTaskUpcLc { zdcEnergyZNC = zdc.energyCommonZNC(); zdcTimeZNA = zdc.timeZNA(); zdcTimeZNC = zdc.timeZNC(); - registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); - registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); - registry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); + if (fillHistQa) { + registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); + registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); + registry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); + } registry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast(gap)); } const bool ignoreZdcTime = (zdcTimeThreshold < 0.f); - + const auto multNTracksPV = collision.multNTracksPV(); + const auto posZ = collision.posZ(); if (gap == o2::aod::sgselector::TrueGap::SingleGapA && (ignoreZdcTime || (std::abs(zdcTimeZNA) > zdcTimeThreshold && std::abs(zdcTimeZNC) < zdcTimeThreshold))) { gapA0nXn = true; } if (gap == o2::aod::sgselector::TrueGap::SingleGapC && (ignoreZdcTime || (std::abs(zdcTimeZNA) < zdcTimeThreshold && std::abs(zdcTimeZNC) > zdcTimeThreshold))) { gapCXn0n = true; } - if (fillTreeOnlySingleGap & !gapA0nXn & !gapCXn0n) { + if (fillTreeOnlySingleGap && !gapA0nXn && !gapCXn0n) { continue; } - registry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); - registry.fill(HIST("Data/hUpcVtz"), collision.posZ()); + registry.fill(HIST("Data/hUpcMulti"), multNTracksPV); + registry.fill(HIST("Data/hUpcVtz"), posZ); if (fillTreeUpcQa) { - rowUpcQa(numPvContributors, collision.multNTracksPV(), collision.posZ(), fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); + rowUpcQa(numPvContributors, multNTracksPV, posZ, fitInfo.ampFT0A, fitInfo.ampFT0C, zdcTimeZNA, zdcTimeZNC); } for (const auto& candidate : groupedLcCandidates) { @@ -272,10 +279,10 @@ struct HfTaskUpcLc { const auto eta = candidate.eta(); double outputBkg(-1); + registry.fill(HIST("Data/eta_vs_Multi"), eta, multNTracksPV); auto fillTHnData = [&](bool isPKPi) { const auto massLc = isPKPi ? HfHelper::invMassLcToPKPi(candidate) : HfHelper::invMassLcToPiKP(candidate); - registry.fill(HIST("Data/eta_vs_Multi"), eta, collision.multNTracksPV()); if constexpr (FillMl) { const auto& mlProb = isPKPi ? candidate.mlProbLcToPKPi() : candidate.mlProbLcToPiKP(); if (mlProb.size() == NumberOfMlClasses) { From 51509f88991f99fac0c532f09697babc8f4fd57f Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Thu, 4 Jun 2026 05:12:52 +0200 Subject: [PATCH 413/449] [PWGDQ] Adding functionality for event mixing across TFs (#16528) Co-authored-by: Ionut Cristian Arsene Co-authored-by: ALICE Action Bot --- PWGDQ/Core/MixingHandler.cxx | 88 +++++++-------- PWGDQ/Core/MixingHandler.h | 149 ++++++++++++++++++++++++-- PWGDQ/Core/MixingLibrary.cxx | 92 ++++++++-------- PWGDQ/Core/VarManager.h | 20 ++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 113 +++++++++++++++++++ 5 files changed, 359 insertions(+), 103 deletions(-) diff --git a/PWGDQ/Core/MixingHandler.cxx b/PWGDQ/Core/MixingHandler.cxx index 5fd601f67d0..5b769fed65d 100644 --- a/PWGDQ/Core/MixingHandler.cxx +++ b/PWGDQ/Core/MixingHandler.cxx @@ -27,9 +27,11 @@ ClassImp(MixingHandler); //_________________________________________________________________________ MixingHandler::MixingHandler() : TNamed(), - fIsInitialized(kFALSE), + fIsInitialized(false), fVariableLimits(), - fVariables() + fVariables(), + fPoolDepth(0), + fPools() { // // default constructor @@ -38,9 +40,11 @@ MixingHandler::MixingHandler() : TNamed(), //_________________________________________________________________________ MixingHandler::MixingHandler(const char* name, const char* title) : TNamed(name, title), - fIsInitialized(kFALSE), + fIsInitialized(false), fVariableLimits(), - fVariables() + fVariables(), + fPoolDepth(0), + fPools() { // // Named constructor @@ -56,29 +60,13 @@ MixingHandler::~MixingHandler() } //_________________________________________________________________________ -void MixingHandler::AddMixingVariable(int var, int nBins, float* binLims) +void MixingHandler::AddMixingVariable(int var, std::vector binLims) { - // - // add a mixing variable - // - fVariables.push_back(var); - TArrayF varBins; - varBins.Set(nBins, binLims); - fVariableLimits.push_back(varBins); - VarManager::SetUseVariable(var); -} - -//_________________________________________________________________________ -void MixingHandler::AddMixingVariable(int var, int nBins, std::vector binLims) -{ - - float* bins = new float[nBins]; - for (int i = 0; i < nBins; ++i) { - bins[i] = binLims[i]; - } - AddMixingVariable(var, nBins, bins); + fVariables[var] = fVariableLimits.size(); + fVariableLimits.push_back(binLims); } +/* //_________________________________________________________________________ int MixingHandler::GetMixingVariable(VarManager::Variables var) { @@ -90,7 +78,9 @@ int MixingHandler::GetMixingVariable(VarManager::Variables var) } return -1; } +*/ +/* //_________________________________________________________________________ std::vector MixingHandler::GetMixingVariableLimits(VarManager::Variables var) { @@ -105,21 +95,21 @@ std::vector MixingHandler::GetMixingVariableLimits(VarManager::Variables } } return binLimits; -} +}*/ //_________________________________________________________________________ void MixingHandler::Init() { - // - // Initialization of pools - // The correct event category will be retrieved using the function FindEventCategory() - // - int size = 1; - for (auto v : fVariableLimits) { - size *= (v.GetSize() - 1); + // loop over all variables and create a mixing pool for each category defined by the binning of the variables + int nCategories = 1; + for (auto& var : fVariables) { + nCategories *= (fVariableLimits[var.second].size() - 1); + } + // add elements in the map for each category (the key is the category and the value is an empty pool) + for (int i = 0; i < nCategories; i++) { + fPools[i] = MixingPool(); } - (void)size; - fIsInitialized = kTRUE; + fIsInitialized = true; } //_________________________________________________________________________ @@ -135,16 +125,21 @@ int MixingHandler::FindEventCategory(float* values) Init(); } + // loop over the variables and find out in which bin the value of the variable for the event is located std::vector bin; - int iVar = 0; - for (auto v = fVariableLimits.begin(); v != fVariableLimits.end(); v++, iVar++) { - int binValue = TMath::BinarySearch((*v).GetSize(), (*v).GetArray(), values[fVariables[iVar]]); - bin.push_back(binValue); - if (bin[iVar] == -1 || bin[iVar] == (*v).GetSize() - 1) { + for (auto [var, pos] : fVariables) { + // check that the value is within limits, if not return -1 to exclude the event from mixing + size_t binValue = std::distance(fVariableLimits[pos].begin(), std::upper_bound(fVariableLimits[pos].begin(), fVariableLimits[pos].end(), values[var])); + if (binValue == 0 || binValue == fVariableLimits[pos].size()) { return -1; // all variables must be inside limits } + bin.push_back(binValue - 1); } + // Hash the bin values to define a unique category + // The hashing is done such that the original bin values can be retrieved from the category + // For example, for 3 variables with n1, n2, n3 bins respectively, the category for bin values (b1, b2, b3) would be: + // category = b1*(n2*n3) + b2*(n3) + b3 int category = 0; int tempCategory = 1; int iv1 = 0; @@ -156,7 +151,7 @@ int MixingHandler::FindEventCategory(float* values) if (iv2 == iv1) { tempCategory *= bin[iv2]; } else { - tempCategory *= (fVariableLimits[iv2].GetSize() - 1); + tempCategory *= (fVariableLimits[iv2].size() - 1); } } category += tempCategory; @@ -175,19 +170,14 @@ int MixingHandler::GetBinFromCategory(VarManager::Variables var, int category) c } // Search for the position of the variable "var" in the internal variable list of the handler - int tempVar = 0; - for (auto v = fVariables.begin(); v != fVariables.end(); v++, tempVar++) { - if (*v == var) { - break; - } - } + int ivar = fVariables.at(var); // extract the bin position in variable "var" from the category int norm = 1; - for (int i = fVariables.size() - 1; i > tempVar; --i) { - norm *= (fVariableLimits[i].GetSize() - 1); + for (int i = fVariables.size() - 1; i > ivar; --i) { + norm *= (fVariableLimits[i].size() - 1); } int truncatedCategory = category - (category % norm); truncatedCategory /= norm; - return truncatedCategory % (fVariableLimits[tempVar].GetSize() - 1); + return truncatedCategory % (fVariableLimits[ivar].size() - 1); } diff --git a/PWGDQ/Core/MixingHandler.h b/PWGDQ/Core/MixingHandler.h index f73d5632895..2a396ab7d35 100644 --- a/PWGDQ/Core/MixingHandler.h +++ b/PWGDQ/Core/MixingHandler.h @@ -24,24 +24,153 @@ #include +#include +#include +#include #include class MixingHandler : public TNamed { public: + // Struct to define track properties relevant for mixing and few utility functions + struct MixingTrack { + float pt; + float eta; + float phi; + uint32_t filteringFlags; + // flip a bit to zero (needed when a track was already used in mixing for that bit for the required pool depth) + void FlipBit(int64_t mask) { filteringFlags ^= mask; } + void Print() const + { + std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", filteringFlags: " << filteringFlags << std::endl; + } + }; + + // Struct to define events used in mixing and few utility functions. + // An event is defined as two vectors of tracks (typically the legs of a two-body + // decay or the two-particles in a correlation analysis) + struct MixingEvent { + std::vector tracks1; + std::vector tracks2; + // bit map for active filtering bits of all the tracks + uint32_t filteringMask = 0; + // counters to keep track of how many times the event was used for mixing (for each track cut separately) + std::array counters = {0}; + // add a track to the event and update the filtering mask accordingly + void AddTrack1(const MixingTrack& track) + { + tracks1.push_back(track); + filteringMask |= track.filteringFlags; + } + void AddTrack2(const MixingTrack& track) + { + tracks2.push_back(track); + filteringMask |= track.filteringFlags; + } + // flip bits in the filtering mask + void FlipFilteringMask(int64_t mask) { filteringMask ^= mask; } + // 1) increment the counters for a given track cut bit mask and if the counters reached the pool depth, + // 2) flip the corresponding bit in the tracks filtering flags to exclude them from further mixing + // 3) for each track, if there are no more active bits in the filtering mask, then remove the track from the event + void IncrementCounters(uint32_t mask, short poolDepth) + { + for (int i = 0; i < 32; i++) { + if (mask & (1ULL << i)) { + counters[i]++; + if (counters[i] >= poolDepth) { + for (auto& track : tracks1) { + track.FlipBit(1ULL << i); + if (track.filteringFlags == 0) { + track = tracks1.back(); + tracks1.pop_back(); + } + } + for (auto& track : tracks2) { + track.FlipBit(1ULL << i); + if (track.filteringFlags == 0) { + track = tracks2.back(); + tracks2.pop_back(); + } + } + FlipFilteringMask(1ULL << i); + } + } + } + } + void Print() const + { + std::cout << "Event filtering mask: "; + for (int i = 0; i < 32; i++) { + if (filteringMask & (1ULL << i)) { + std::cout << "1"; + } else { + std::cout << "0"; + } + } + std::cout << std::endl; + for (int i = 0; i < 32; i++) { + if (filteringMask & (1ULL << i)) { + std::cout << "Counter " << i << ": " << counters[i] << std::endl; + } + } + std::cout << "Tracks 1: " << std::endl; + for (const auto& track : tracks1) { + track.Print(); + } + std::cout << "Tracks 2: " << std::endl; + for (const auto& track : tracks2) { + track.Print(); + } + } + }; + + struct MixingPool { + std::vector events; + + // check which events in the pool are empty (i.e. no active tracks for mixing) and remove them from the pool + void CleanPool() + { + events.erase(std::remove_if(events.begin(), events.end(), + [](const MixingEvent& event) { return event.tracks1.empty() && event.tracks2.empty(); }), + events.end()); + } + // The function that performs the mixing is called outside this class, but the pool provides the events and tracks to be mixed and takes care of updating the events after mixing + // (e.g. incrementing the counters and removing the tracks that reached the pool depth for a given cut) + void UpdatePool(const MixingEvent& event, short poolDepth) + { + for (auto& event : events) { + event.IncrementCounters(event.filteringMask, poolDepth); + } + CleanPool(); + events.push_back(event); + } + // getter for the events in the pool + const std::vector& GetEvents() const { return events; } + + void Print() const + { + std::cout << "Mixing pool with " << events.size() << " events:" << std::endl; + for (const auto& event : events) { + event.Print(); + } + } + }; + MixingHandler(); MixingHandler(const char* name, const char* title); virtual ~MixingHandler(); // setters - void AddMixingVariable(int var, int nBins, float* binLims); - void AddMixingVariable(int var, int nBins, std::vector binLims); + void AddMixingVariable(int var, std::vector binLims); + void SetPoolDepth(short depth) { fPoolDepth = depth; } // getters - int GetNMixingVariables() const { return fVariables.size(); } - int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly - std::vector GetMixingVariableLimits(VarManager::Variables var); + // int GetNMixingVariables() const { return fVariables.size(); } + // int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly + // std::vector GetMixingVariableLimits(VarManager::Variables var); + MixingPool& GetPool(int category) { return fPools[category]; } + short GetPoolDepth() const { return fPoolDepth; } void Init(); int FindEventCategory(float* values); @@ -54,10 +183,14 @@ class MixingHandler : public TNamed // User options bool fIsInitialized; // check if the mixing handler is initialized - std::vector fVariableLimits; - std::vector fVariables; + // bin limits for the variables used for mixing, the number of vectors corresponds to the number of variables and the content of each vector corresponds to the bin limits for that variable + std::vector> fVariableLimits; + std::map fVariables; // key: variable, value: position in the internal variable list of the handler (used to map the variables to the values passed to FindEventCategory) + + short fPoolDepth; // number of events to be kept in each pool + std::map fPools; // key: category, value: pool of events corresponding to that category - ClassDef(MixingHandler, 1); + ClassDef(MixingHandler, 2); }; #endif // PWGDQ_CORE_MIXINGHANDLER_H_ diff --git a/PWGDQ/Core/MixingLibrary.cxx b/PWGDQ/Core/MixingLibrary.cxx index 28e453b5479..b152de7d27c 100644 --- a/PWGDQ/Core/MixingLibrary.cxx +++ b/PWGDQ/Core/MixingLibrary.cxx @@ -31,183 +31,183 @@ void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible std::string nameStr = mixingVarible; if (!nameStr.compare("Centrality1")) { std::vector fCentLimsHashing = {0.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality2")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality3")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality4")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality5")) { std::vector fCentLimsHashing = {0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality6")) { std::vector fCentLimsHashing = {0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("CentralityFT0C1")) { std::vector fCentFT0CLimsHashing = {0.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C2")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C3")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C4")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C5")) { std::vector fCentFT0CLimsHashing = {0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C6")) { std::vector fCentFT0CLimsHashing = {0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("Mult1")) { std::vector fMultLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 120.0f, 160.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Mult2")) { std::vector fMultLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 120.0f, 140.0f, 180.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Mult3")) { std::vector fMultLimsHashing = {0.0f, 5.0f, 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 45.0f, 50.0f, 55.0f, 60.0f, 65.0f, 70.0f, 75.0f, 80.0f, 85.0f, 90.0f, 100.0f, 120.0f, 140.0f, 165.0f, 200.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Vtx1")) { std::vector fZLimsHashing = {-10.0f, 0.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx2")) { std::vector fZLimsHashing = {-10.0f, -5.0f, 0.0f, 5.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx3")) { std::vector fZLimsHashing = {-10.0f, -7.5f, -5.0f, -2.5f, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx4")) { std::vector fZLimsHashing = {-10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx5")) { std::vector fZLimsHashing = {-10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Occupancy1")) { std::vector fOccLimsHashing = {0.0f, 500.0f, 1000.0f, 2000.0f, 3000.0f, 6000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Occupancy2")) { std::vector fOccLimsHashing = {0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 6000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Occupancy3")) { std::vector fOccLimsHashing = {0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Psi2A1")) { std::vector fPsi2A = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A2")) { std::vector fPsi2A = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A3")) { std::vector fPsi2A = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A4")) { std::vector fPsi2A = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A5")) { std::vector fPsi2A = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2B1")) { std::vector fPsi2B = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B2")) { std::vector fPsi2B = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B3")) { std::vector fPsi2B = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B4")) { std::vector fPsi2B = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B5")) { std::vector fPsi2B = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2C1")) { std::vector fPsi2C = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C2")) { std::vector fPsi2C = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C3")) { std::vector fPsi2C = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C4")) { std::vector fPsi2C = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C5")) { std::vector fPsi2C = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("MedianTimeA1")) { std::vector fMTLimsHashing = {-100.0f, -40.0f, -20.0f, 20.0f, 40.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("MedianTimeA2")) { std::vector fMTLimsHashing = {-100.0f, -80.0f, -60.0f, -40.0f, -20.0f, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("MedianTimeA3")) { std::vector fMTLimsHashing = {-100.0f, -80.0f, -60.0f, -40.0f, -30.0f, -20.0f, -10.0f, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 60.0f, 80.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("PileUpA1")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 6000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA2")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 4000.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA3")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 3000.0f, 4000.0f, 5000.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA4")) { std::vector fPileUpLimsHashing = {0.0f, 500.0f, 1000.0f, 1500.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 5500.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } } @@ -250,6 +250,6 @@ void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json) } // set up mixing variable - mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits.size(), limits); + mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits); } } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 453c0e65860..d2de7e5e44c 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1397,6 +1397,8 @@ class VarManager : public TObject static void FillTriple(T1 const& t1, T2 const& t2, T3 const& t3, float* values = nullptr, PairCandidateType pairType = kTripleCandidateToEEPhoton); template static void FillPairME(T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillPairMEAcrossTFs(T const& t1, T const& t2, float* values = nullptr); template static void FillPairMC(T1 const& t1, T2 const& t2, float* values = nullptr); template @@ -4215,6 +4217,24 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) } } +template +void VarManager::FillPairMEAcrossTFs(T const& t1, T const& t2, float* values) +{ + if (!values) { + values = fgValues; + } + + float m1 = o2::constants::physics::MassElectron; + ROOT::Math::PtEtaPhiMVector v1(t1.pt, t1.eta, t1.phi, m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt, t2.eta, t2.phi, m1); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; + values[kRap] = -v12.Rapidity(); +} + template void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values) { diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index c1048c21c2c..0b916cef236 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1313,6 +1313,9 @@ struct AnalysisSameEventPairing { } fConfigCuts; Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; + Configurable fConfigRunMixingAcrossTFs{"cfgRunMixingAcrossTFs", false, "If true, run event mixing using the MixingHandler which accumulates events across multiple TFs"}; // Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; @@ -1360,6 +1363,7 @@ struct AnalysisSameEventPairing { Filter filterEventSelected = aod::dqanalysisflags::isEventSelected > static_cast(0); HistogramManager* fHistMan; + MixingHandler fMixingHandler; o2::analysis::DQMlResponse fDQMlResponse; std::vector fOutputMlPsi2ee = {}; // TODO: check this is needed or not @@ -1397,6 +1401,7 @@ struct AnalysisSameEventPairing { { fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra") || context.mOptions.get("processBarrelOnlyWithQvectorCentrSkimmedNoCov"); fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed") || context.mOptions.get("processMixingBarrelSkimmedFlow") || context.mOptions.get("processMixingBarrelWithQvectorCentrSkimmedNoCov"); + fEnableBarrelMixingHistos |= fConfigRunMixingAcrossTFs; fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMuonOnlySkimmedFlow"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed") || context.mOptions.get("processMixingMuonSkimmedFlow"); fEnableBarrelMuonHistos = context.mOptions.get("processElectronMuonSkimmed"); @@ -1627,6 +1632,25 @@ struct AnalysisSameEventPairing { } } + if (fConfigRunMixingAcrossTFs) { + TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; + std::unique_ptr objArray(mixVarsString.Tokenize(",")); + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { + // fMixingHandler = new MixingHandler("mixingHandler", "mixing handler"); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(&fMixingHandler, objArray->At(iVar)->GetName()); + } + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(&fMixingHandler, mixVarsJsonString.Data()); + } + fMixingHandler.SetPoolDepth(fConfigMixingDepth); + fMixingHandler.Init(); + } + fCurrentRun = 0; fCCDB->setURL(fConfigCCDB.url.value); @@ -2189,6 +2213,95 @@ struct AnalysisSameEventPairing { if (fEnableBarrelHistos && fConfigQA) { fHistMan->FillHistClass("PairingSEQA", VarManager::fgValues); } + + if (fConfigRunMixingAcrossTFs) { + // run event mixing across TFs + // 1) create a MixingEvent and fill it with the relevant tracks + MixingHandler::MixingEvent mixingEvent; + uint32_t trackFilterForMixing = 0; + for (auto& assoc : groupedAssocs) { + if constexpr (TPairType == VarManager::kDecayToEE) { + trackFilterForMixing = assoc.isBarrelSelected_raw() & assoc.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; + if (!trackFilterForMixing) { + continue; + } + auto t1 = assoc.template reducedtrack_as(); + MixingHandler::MixingTrack mixingTrack(t1.pt(), t1.eta(), t1.phi(), trackFilterForMixing); + if (t1.sign() > 0) { + mixingEvent.AddTrack1(mixingTrack); + } else { + mixingEvent.AddTrack2(mixingTrack); + } + } + } + // 2) run the mixing with the events in the pool corresponding to this event + auto& pool = fMixingHandler.GetPool(fMixingHandler.FindEventCategory(VarManager::fgValues)); + for (auto& poolEvent : pool.GetEvents()) { + for (auto& t1 : mixingEvent.tracks1) { + // run +- pairing + for (auto& t2 : poolEvent.tracks2) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + // run ++ pairing + for (auto& t2 : poolEvent.tracks1) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPP_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + } + for (auto& t1 : mixingEvent.tracks2) { + // run -+ pairing + for (auto& t2 : poolEvent.tracks1) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + // run -- pairing + for (auto& t2 : poolEvent.tracks2) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEMM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + } + } + // 3) add the current event to the pool + pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth()); + // pool.Print(); + } } // end loop over events } From 7c2ce96728b615e32595018e82e510163f96b30b Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Thu, 4 Jun 2026 07:57:56 +0200 Subject: [PATCH 414/449] [PWGHF] Improve tasks for B to JPsi analyses (#16500) --- PWGHF/Core/HfHelper.h | 77 ++++++++++++++----- .../candidateCreatorBToJpsiReduced.cxx | 4 +- PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx | 29 +++---- PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx | 31 ++++---- 4 files changed, 89 insertions(+), 52 deletions(-) diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 3eb3e8dd0b9..de1b537b3bf 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -172,9 +172,18 @@ struct HfHelper { } template - static auto invMassBplusToJpsiK(const T& candidate) + static auto invMassBplusToJpsiK(const T& candidate, const bool useJpsiPdgMass) { - return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + auto const pVecMuPos = candidate.pVectorProng0(); + auto const pVecMuNeg = candidate.pVectorProng1(); + auto const pVecKa = candidate.pVectorProng2(); + if (useJpsiPdgMass) { + return RecoDecay::m(std::array{RecoDecay::pVec(pVecMuPos, pVecMuNeg), pVecKa}, + std::array{o2::constants::physics::MassJPsi, o2::constants::physics::MassKPlus}); + } + // Do not use PDG mass for J/psi + return RecoDecay::m(std::array{pVecMuPos, pVecMuNeg, pVecKa}, + std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); } template @@ -684,9 +693,27 @@ struct HfHelper { } template - static auto invMassBsToJpsiPhi(const T& candidate) + static auto invMassBsToJpsiPhi(const T& candidate, const bool useJpsiPdgMass, const bool usePhiPdgMass) { - return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + auto const pVecMuPos = candidate.pVectorProng0(); + auto const pVecMuNeg = candidate.pVectorProng1(); + auto const pVecKaPos = candidate.pVectorProng2(); + auto const pVecKaNeg = candidate.pVectorProng3(); + if (useJpsiPdgMass && usePhiPdgMass) { + return RecoDecay::m(std::array{RecoDecay::pVec(pVecMuPos, pVecMuNeg), RecoDecay::pVec(pVecKaPos, pVecKaNeg)}, + std::array{o2::constants::physics::MassJPsi, o2::constants::physics::MassPhi}); + } + if (useJpsiPdgMass && !usePhiPdgMass) { + return RecoDecay::m(std::array{RecoDecay::pVec(pVecMuPos, pVecMuNeg), pVecKaPos, pVecKaNeg}, + std::array{o2::constants::physics::MassJPsi, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + } + if (!useJpsiPdgMass && usePhiPdgMass) { + return RecoDecay::m(std::array{pVecMuPos, pVecMuNeg, RecoDecay::pVec(pVecKaPos, pVecKaNeg)}, + std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassPhi}); + } + // Do not use PDG mass for either J/psi or phi + return RecoDecay::m(std::array{pVecMuPos, pVecMuNeg, pVecKaPos, pVecKaNeg}, + std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); } template @@ -905,14 +932,18 @@ struct HfHelper { /// \param candBp B+ candidate /// \param cuts B+ candidate selection per pT bin /// \param binsPt pT bin limits + /// \param useJpsiPdgMass Use PDG mass for J/psi when calculating Bs candidate mass /// \return true if candidate passes all selections template - static bool selectionBplusToJpsiKTopol(const T1& candBp, const T2& cuts, const T3& binsPt) + static bool selectionBplusToJpsiKTopol(const T1& candBp, const T2& cuts, const T3& binsPt, const bool useJpsiPdgMass) { auto ptCandBp = candBp.pt(); - auto mCandBp = invMassBplusToJpsiK(candBp); - auto ptJpsi = RecoDecay::pt(candBp.pxProng0(), candBp.pyProng0()); - auto ptKa = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1()); + auto mCandBp = invMassBplusToJpsiK(candBp, useJpsiPdgMass); + auto const pVecMu0 = candBp.pVectorProng0(); + auto const pVecMu1 = candBp.pVectorProng1(); + auto const pVecKa = candBp.pVectorProng2(); + auto ptJpsi = RecoDecay::pt(pVecMu0, pVecMu1); + auto ptKa = RecoDecay::pt(pVecKa); auto candJpsi = candBp.jpsi(); float pseudoPropDecLen = candBp.decayLengthXY() * mCandBp / ptCandBp; @@ -937,7 +968,7 @@ struct HfHelper { } // J/Psi mass - if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) { + if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) > cuts->get(binPt, "DeltaM J/Psi")) { return false; } @@ -1088,20 +1119,24 @@ struct HfHelper { // Apply topological cuts as defined in SelectorCuts.h /// \param candBs Bs candidate - /// \param candKa0 kaon candidate 0 (phi daughter) - /// \param candKa1 kaon candidate 1 (phi daughter) /// \param cuts Bs candidate selection per pT bin /// \param binsPt pT bin limits + /// \param useJpsiPdgMass Use PDG mass for J/psi when calculating Bs candidate mass + /// \param usePhiPdgMass Use PDG mass for phi when calculating Bs candidate mass /// \return true if candidate passes all selections - template - static bool selectionBsToJpsiPhiTopol(const T1& candBs, const T2& candKa0, const T3& candKa1, const T4& cuts, const T5& binsPt) + template + static bool selectionBsToJpsiPhiTopol(const T1& candBs, const T2& cuts, const T3& binsPt, const bool useJpsiPdgMass, const bool usePhiPdgMass) { auto ptCandBs = candBs.pt(); - auto mCandBs = invMassBsToJpsiPhi(candBs); - std::array pVecKa0 = candKa0.pVector(); - std::array pVecKa1 = candKa1.pVector(); + auto mCandBs = invMassBsToJpsiPhi(candBs, useJpsiPdgMass, usePhiPdgMass); + auto const pVecMu0 = candBs.pVectorProng0(); + auto const pVecMu1 = candBs.pVectorProng1(); + auto const pVecKa0 = candBs.pVectorProng2(); + auto const pVecKa1 = candBs.pVectorProng3(); auto mCandPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); - auto ptJpsi = RecoDecay::pt(candBs.pxProng0(), candBs.pyProng0()); + auto ptJpsi = RecoDecay::pt(pVecMu0, pVecMu1); + auto ptKa0 = RecoDecay::pt(pVecKa0); + auto ptKa1 = RecoDecay::pt(pVecKa1); auto candJpsi = candBs.jpsi(); float pseudoPropDecLen = candBs.decayLengthXY() * mCandBs / ptCandBs; @@ -1116,8 +1151,8 @@ struct HfHelper { } // kaon pt - if (candKa0.pt() < cuts->get(binPt, "pT K") && - candKa1.pt() < cuts->get(binPt, "pT K")) { + if (ptKa0 < cuts->get(binPt, "pT K") && + ptKa1 < cuts->get(binPt, "pT K")) { return false; } @@ -1127,12 +1162,12 @@ struct HfHelper { } // phi mass - if (std::abs(mCandPhi - o2::constants::physics::MassPhi) < cuts->get(binPt, "DeltaM phi")) { + if (std::abs(mCandPhi - o2::constants::physics::MassPhi) > cuts->get(binPt, "DeltaM phi")) { return false; } // J/Psi mass - if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) { + if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) > cuts->get(binPt, "DeltaM J/Psi")) { return false; } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx index b3777ae9012..e5b2865c3e2 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -343,9 +343,9 @@ struct HfCandidateCreatorBToJpsiReduced { errorDecayLength, errorDecayLengthXY, chi2PCA, pVecDauPos[0], pVecDauPos[1], pVecDauPos[2], - pVecDauNeg[0], pVecDauNeg[1], pVecDauPos[2], + pVecDauNeg[0], pVecDauNeg[1], pVecDauNeg[2], pVecTrackLf0[0], pVecTrackLf0[1], pVecTrackLf0[2], - pVecTrackLf1[0], pVecTrackLf1[1], pVecTrackLf0[2], + pVecTrackLf1[0], pVecTrackLf1[1], pVecTrackLf1[2], dcaDauPos.getY(), dcaDauNeg.getY(), dcaTrackLf0.getY(), dcaTrackLf1.getY(), std::sqrt(dcaDauPos.getSigmaY2()), std::sqrt(dcaDauNeg.getSigmaY2()), std::sqrt(dcaTrackLf0.getSigmaY2()), std::sqrt(dcaTrackLf1.getSigmaY2())); rowCandidateBsProngs(candJpsi.globalIndex(), trackLf0.globalIndex(), trackLf1.globalIndex()); diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx index 31fae6a389d..134dc6b529b 100644 --- a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -141,7 +141,6 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplustojpsik_lite::PtJpsi, hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauPos, hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauNeg, - hf_cand_bplustojpsik_lite::ImpactParameterLfTrack0, // Jpsi daughter features hf_cand_bplustojpsik_lite::ItsNClsJpsiDauPos, hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsJpsiDauPos, @@ -155,6 +154,7 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplustojpsik_lite::AbsEtaJpsiDauNeg, // kaon features hf_cand_bplustojpsik_lite::PtBach, + hf_cand_bplustojpsik_lite::ImpactParameterLfTrack0, hf_cand_bplustojpsik_lite::ItsNClsLfTrack0, hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsLfTrack0, hf_cand_bplustojpsik_lite::ItsChi2NClLfTrack0, @@ -207,6 +207,7 @@ struct HfTaskBplusToJpsiKReduced { Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + Configurable useJpsiPdgMass{"useJpsiPdgMass", true, "Whether to use J/Psi PDG mass for B+ candidate mass evaluation or to use the invariant mass of the two prongs"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_jpsi_k::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_bplus_to_jpsi_k::Cuts[0], hf_cuts_bplus_to_jpsi_k::NBinsPt, hf_cuts_bplus_to_jpsi_k::NCutVars, hf_cuts_bplus_to_jpsi_k::labelsPt, hf_cuts_bplus_to_jpsi_k::labelsCutVar}, "B+ candidate selection per pT bin"}; @@ -339,11 +340,13 @@ struct HfTaskBplusToJpsiKReduced { aod::HfRedBach0Tracks const&) { auto ptCandBplus = candidate.pt(); - auto invMassBplus = HfHelper::invMassBplusToJpsiK(candidate); + auto invMassBplus = HfHelper::invMassBplusToJpsiK(candidate, useJpsiPdgMass); auto candJpsi = candidate.template jpsi_as(); auto candKa = candidate.template bachKa_as(); - auto ptJpsi = candidate.ptProng0(); - auto invMassJpsi = candJpsi.m(); + auto const pVecMu0 = candidate.pVectorProng0(); + auto const pVecMu1 = candidate.pVectorProng1(); + auto ptJpsi = RecoDecay::pt(pVecMu0, pVecMu1); + auto invMassJpsi = RecoDecay::m(std::array{pVecMu0, pVecMu1}, std::array{o2::constants::physics::MassMuonPlus, o2::constants::physics::MassMuonMinus}); uint8_t statusBplus = 0; int8_t flagMcMatchRec{0}, flagMcDecayChanRec{0}, flagWrongCollision{0}; @@ -356,7 +359,7 @@ struct HfTaskBplusToJpsiKReduced { } SETBIT(statusBplus, SelectionStep::RecoSkims); - if (HfHelper::selectionBplusToJpsiKTopol(candidate, cuts, binsPt)) { + if (HfHelper::selectionBplusToJpsiKTopol(candidate, cuts, binsPt, useJpsiPdgMass)) { SETBIT(statusBplus, SelectionStep::RecoTopol); } else if (selectionFlagBplus >= BIT(SelectionStep::RecoTopol) * 2 - 1) { return; @@ -391,17 +394,17 @@ struct HfTaskBplusToJpsiKReduced { } registry.fill(HIST("hMass"), invMassBplus, ptCandBplus); - registry.fill(HIST("hMassJpsi"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hd0K"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsi"), invMassJpsi, ptJpsi); + registry.fill(HIST("hd0K"), candidate.impactParameter2(), candidate.ptProng2()); if constexpr (DoMc) { if (isSignal) { registry.fill(HIST("hMassRecSig"), invMassBplus, ptCandBplus); - registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hd0KRecSig"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, ptJpsi); + registry.fill(HIST("hd0KRecSig"), candidate.impactParameter2(), candidate.ptProng2()); } else if (fillBackground) { registry.fill(HIST("hMassRecBg"), invMassBplus, ptCandBplus); - registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, ptJpsi); + registry.fill(HIST("hd0KRecBg"), candidate.impactParameter2(), candidate.ptProng2()); } } @@ -436,7 +439,6 @@ struct HfTaskBplusToJpsiKReduced { ptJpsi, candidate.impactParameter0(), candidate.impactParameter1(), - candidate.impactParameter2(), candJpsi.itsNClsDauPos(), candJpsi.tpcNClsCrossedRowsDauPos(), candJpsi.itsChi2NClDauPos(), @@ -448,7 +450,8 @@ struct HfTaskBplusToJpsiKReduced { candJpsi.tpcChi2NClDauNeg(), absEta(candJpsi.tglDauNeg()), // kaon features - candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter2(), candKa.itsNCls(), candKa.tpcNClsCrossedRows(), candKa.itsChi2NCl(), diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx index ab44c6f7dbe..039bc79b980 100644 --- a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -232,6 +232,8 @@ struct HfTaskBsToJpsiPhiReduced { Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + Configurable useJpsiPdgMass{"useJpsiPdgMass", true, "Whether to use J/Psi PDG mass for B+ candidate mass evaluation or to use the invariant mass of the two prongs"}; + Configurable usePhiPdgMass{"usePhiPdgMass", true, "Whether to use Phi PDG mass for B+ candidate mass evaluation or to use the invariant mass of the two prongs"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_bs_to_jpsi_phi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_bs_to_jpsi_phi::Cuts[0], hf_cuts_bs_to_jpsi_phi::NBinsPt, hf_cuts_bs_to_jpsi_phi::NCutVars, hf_cuts_bs_to_jpsi_phi::labelsPt, hf_cuts_bs_to_jpsi_phi::labelsCutVar}, "Bs candidate selection per pT bin"}; @@ -310,7 +312,6 @@ struct HfTaskBsToJpsiPhiReduced { registry.add("hMass", bSCandTitle + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); registry.add("hMassJpsi", bSCandTitle + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); registry.add("hMassPhi", bSCandTitle + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); - registry.add("hd0K", bSCandTitle + "Kaon DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); // histograms processMC if (doprocessMc || doprocessMcWithBsMl) { @@ -321,11 +322,9 @@ struct HfTaskBsToJpsiPhiReduced { registry.add("hMassRecSig", bSCandMatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); registry.add("hMassJpsiRecSig", bSCandMatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); registry.add("hMassPhiRecSig", bSCandMatch + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2}); #phi " + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); - registry.add("hd0KRecSig", bSCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); registry.add("hMassRecBg", bSCandUnmatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); registry.add("hMassJpsiRecBg", bSCandUnmatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); registry.add("hMassPhiRecBg", bSCandMatch + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2}); #phi " + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); - registry.add("hd0KRecBg", bSCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); } if (doprocessDataWithBsMl || doprocessMcWithBsMl) { @@ -371,14 +370,17 @@ struct HfTaskBsToJpsiPhiReduced { aod::HfRedBach1Tracks const&) { auto ptCandBs = candidate.pt(); - auto invMassBs = HfHelper::invMassBsToJpsiPhi(candidate); + auto invMassBs = HfHelper::invMassBsToJpsiPhi(candidate, useJpsiPdgMass, usePhiPdgMass); auto candJpsi = candidate.template jpsi_as(); auto candKa0 = candidate.template prong0Phi_as(); auto candKa1 = candidate.template prong1Phi_as(); - std::array const pVecKa0 = {candKa0.px(), candKa0.py(), candKa0.pz()}; - std::array const pVecKa1 = {candKa1.px(), candKa1.py(), candKa1.pz()}; - auto ptJpsi = candidate.ptProng0(); - auto invMassJpsi = candJpsi.m(); + auto const pVecMu0 = candidate.pVectorProng0(); + auto const pVecMu1 = candidate.pVectorProng1(); + auto const pVecKa0 = candidate.pVectorProng2(); + auto const pVecKa1 = candidate.pVectorProng3(); + auto ptJpsi = RecoDecay::pt(pVecMu0, pVecMu1); + auto ptPhi = RecoDecay::pt(pVecKa0, pVecKa1); + auto invMassJpsi = RecoDecay::m(std::array{pVecMu0, pVecMu1}, std::array{o2::constants::physics::MassMuonPlus, o2::constants::physics::MassMuonMinus}); auto invMassPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); uint8_t statusBs = 0; @@ -393,7 +395,7 @@ struct HfTaskBsToJpsiPhiReduced { } SETBIT(statusBs, SelectionStep::RecoSkims); - if (HfHelper::selectionBsToJpsiPhiTopol(candidate, candKa0, candKa1, cuts, binsPt)) { + if (HfHelper::selectionBsToJpsiPhiTopol(candidate, cuts, binsPt, useJpsiPdgMass, usePhiPdgMass)) { SETBIT(statusBs, SelectionStep::RecoTopol); } else if (selectionFlagBs >= BIT(SelectionStep::RecoTopol) * 2 - 1) { return; @@ -432,18 +434,15 @@ struct HfTaskBsToJpsiPhiReduced { } registry.fill(HIST("hMass"), invMassBs, ptCandBs); - registry.fill(HIST("hMassJpsi"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hMassPhi"), invMassPhi, candidate.ptProng0()); - registry.fill(HIST("hd0K"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsi"), invMassJpsi, ptJpsi); + registry.fill(HIST("hMassPhi"), invMassPhi, ptPhi); if constexpr (DoMc) { if (isSignal) { registry.fill(HIST("hMassRecSig"), invMassBs, ptCandBs); - registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hd0KRecSig"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, ptJpsi); } else if (fillBackground) { registry.fill(HIST("hMassRecBg"), invMassBs, ptCandBs); - registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); - registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, ptJpsi); } } From 482138a632e494afee0a928b184a4545fad07909 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Thu, 4 Jun 2026 09:20:50 +0200 Subject: [PATCH 415/449] [PWGCF] split v02 and v0 subevent configurations (#16520) --- .../Tasks/flowGenericFramework.cxx | 937 +++++++++++------- 1 file changed, 565 insertions(+), 372 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 25b4ef4d963..b403bf1a9ad 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -61,6 +61,7 @@ #include #include +#include #include #include #include @@ -168,10 +169,13 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)"); - Configurable> cfgEta{"cfgEta", {-0.8, 0.8}, "eta cut"}; - Configurable> cfgEtaNch{"cfgEtaNch", {-0.5, 0.5}, "eta cut for nch selection"}; - Configurable> cfgEtaPtPt{"cfgEtaPtPt", {-0.5, 0.5}, "eta for pt-pt correlation"}; - Configurable> cfgEtaV0Daughters{"cfgEtaV0Daughters", {-0.5, 0.5}, "eta cut on V0 daughter particles"}; + struct : ConfigurableGroup { + Configurable> cfgEtaNptV02{"cfgEtaNptV02", {-0.5, 0.5}, "eta cut for v02 fractional spectra"}; + Configurable> cfgEtaNptV0{"cfgEtaNptV0", {-0.5, 0.5}, "eta cut for v0 fractional spectra"}; + Configurable> cfgEta{"cfgEta", {-0.8, 0.8}, "eta cut"}; + Configurable> cfgEtaNch{"cfgEtaNch", {-0.5, 0.5}, "eta cut for nch selection"}; + Configurable> cfgEtaPtPt{"cfgEtaPtPt", {-0.5, 0.5}, "eta for pt-pt correlation"}; + } cfgKinematics; Configurable> cfgPtPtGaps{"cfgPtPtGaps", {LongArrayDouble[0], 4, 2, {"subevent 1", "subevent 2", "subevent 3", "subevent 4"}, {"etamin", "etamax"}}, "{etamin,etamax} for all ptpt-subevents"}; O2_DEFINE_CONFIGURABLE(cfgUsePIDTotal, bool, false, "use fraction of PID total"); O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); @@ -281,11 +285,17 @@ struct FlowGenericFramework { std::array itsNsigmaCut; std::array tpcNsigmaCut; + enum FractionSetup { + FractionV02 = 0, + FractionV0, + FractionSetupCount + }; + // QA outputs std::map>> th1sList; std::map>> th3sList; - std::vector> histosNpt; - std::vector> histosResoNpt; + std::array>, FractionSetupCount> histosNpt; + std::array>, FractionSetupCount> histosResoNpt; enum OutputTH1Names { Phi = 0, Eta, @@ -394,7 +404,7 @@ struct FlowGenericFramework { UseArmPodCut, UseCompetingMassRejection }; - enum V0Selection { + enum V0SelectionFlags { FillCandidate = 1, FillDaughterPt, FillMassCut, @@ -406,7 +416,8 @@ struct FlowGenericFramework { FillProperLifetime, FillArmPodCut, FillCompetingMass, - FillDaughterTrackSelection + FillV02DaughterTrackSelection, + FillV0DaughterTrackSelection }; // Define global variables @@ -499,7 +510,7 @@ struct FlowGenericFramework { o2::analysis::gfw::nchup = cfgGFWBinning->GetNchMax(); o2::analysis::gfw::centbinning = cfgGFWBinning->GetCentBinning(); cfgGFWBinning->Print(); - LOGF(info, "Eta cuts: Filter [%.1f,%.1f] | Nch [%.1f,%.1f] | Pt-Pt [%.1f, %.1f] | V0 daughters [%.1f, %.1f]", cfgEta->first, cfgEta->second, cfgEtaNch->first, cfgEtaNch->second, cfgEtaPtPt->first, cfgEtaPtPt->second, cfgEtaV0Daughters->first, cfgEtaV0Daughters->second); + LOGF(info, "Eta cuts: Filter [%.1f,%.1f] | Nch [%.1f,%.1f] | Npt v02 [%.1f, %.1f] | Npt v0 [%.1f, %.1f] | Pt-Pt [%.1f, %.1f]", cfgKinematics.cfgEta->first, cfgKinematics.cfgEta->second, cfgKinematics.cfgEtaNch->first, cfgKinematics.cfgEtaNch->second, cfgKinematics.cfgEtaNptV02->first, cfgKinematics.cfgEtaNptV02->second, cfgKinematics.cfgEtaNptV0->first, cfgKinematics.cfgEtaNptV0->second, cfgKinematics.cfgEtaPtPt->first, cfgKinematics.cfgEtaPtPt->second); o2::analysis::gfw::multGlobalCorrCutPars = cfgMultCorrCuts.cfgMultGlobalCutPars; o2::analysis::gfw::multPVCorrCutPars = cfgMultCorrCuts.cfgMultPVCutPars; o2::analysis::gfw::multGlobalPVCorrCutPars = cfgMultCorrCuts.cfgMultGlobalPVCutPars; @@ -538,7 +549,7 @@ struct FlowGenericFramework { AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; - AxisSpec etaAxis = {o2::analysis::gfw::etabins, cfgEta->first, cfgEta->second, "#eta"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, cfgKinematics.cfgEta->first, cfgKinematics.cfgEta->second, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; std::string sCentralityEstimator = centNamesMap[cfgCentEstimator] + " centrality (%)"; @@ -606,7 +617,8 @@ struct FlowGenericFramework { registryQA.add("trackQA/after/Nch_uncorrected", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); registryQA.add("trackQA/after/etaNch", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); registryQA.add("trackQA/after/etaPtPt", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); - registryQA.add("trackQA/after/etaV0Daughters", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); + registryQA.add("trackQA/after/etaV02", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); + registryQA.add("trackQA/after/etaV0", "; #eta; Counts", {HistType::kTH1D, {etaAxis}}); if (doprocessMCReco) { registry.add("trackQA/after/pt_centrality_K0", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); registry.add("trackQA/after/pt_centrality_K0_pion", "; #it{p}_{T}; Centrality (%)", {HistType::kTH2D, {ptAxis, centAxis}}); @@ -674,7 +686,7 @@ struct FlowGenericFramework { registryQA.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); registryQA.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); } - registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); + registryQA.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{13, 0.5, 13.5}}}); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate, "K0 candidates"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); @@ -686,7 +698,8 @@ struct FlowGenericFramework { registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); - registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelection, "Daughter track selection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV02DaughterTrackSelection, "v02 Daughter track selection"); + registryQA.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(FillV0DaughterTrackSelection, "v0 Daughter track selection"); } if (resoSwitchVals[UseParticle][Lambda]) { @@ -708,7 +721,7 @@ struct FlowGenericFramework { registryQA.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); registryQA.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); } - registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{12, 0.5, 12.5}}}); + registryQA.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{13, 0.5, 13.5}}}); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate, "Lambda candidates"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt, "Daughter pt"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillMassCut, "Mass cut"); @@ -720,33 +733,48 @@ struct FlowGenericFramework { registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillProperLifetime, "Proper lifetime"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillArmPodCut, "Armenteros-Podolanski cut"); registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillCompetingMass, "Competing mass rejection"); - registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelection, "Daughter track selection"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillV02DaughterTrackSelection, "v02 Daughter track selection"); + registryQA.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(FillV0DaughterTrackSelection, "v0 Daughter track selection"); } } - registry.add("npt_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - registry.add("npt_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); - - histosNpt.resize(SpeciesCount); - histosNpt[ChargedID] = std::make_unique("nptCh", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptCh", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[PionID] = std::make_unique("nptPi", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptPi", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[KaonID] = std::make_unique("nptKa", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptKa", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosNpt[ProtonID] = std::make_unique("nptPr", "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptPr", "; #it{p}_{T} (GeV/#it{c}; Count)", {HistType::kTH1D, {ptAxis}}); - histosResoNpt.resize(ResonanceCount); - histosResoNpt[K0Sideband1] = std::make_unique("nptK0SB1", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0SB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[K0Signal] = std::make_unique("nptK0Sig", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0Sig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[K0Sideband2] = std::make_unique("nptK0SB2", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptK0SB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LambdaSideband1] = std::make_unique("nptLambdaSB1", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSB1", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LambdaSignal] = std::make_unique("nptLambdaSig", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSig", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); - histosResoNpt[LambdaSideband2] = std::make_unique("nptLambdaSB2", "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); // registry.add("nptLambdaSB2", "; #it{p}_{T} (GeV/#it{c}; Count", {HistType::kTH1D, {ptAxis}}); + registry.add("npt_v02_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v02_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_v0_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + + for (auto setup = 0; setup < FractionSetupCount; ++setup) { + const char* setupName = (setup == FractionV02) ? "V02" : "V0"; + histosNpt[setup].resize(SpeciesCount); + histosNpt[setup][ChargedID] = std::make_unique(Form("npt%sCh", setupName), "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosNpt[setup][PionID] = std::make_unique(Form("npt%sPi", setupName), "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosNpt[setup][KaonID] = std::make_unique(Form("npt%sKa", setupName), "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosNpt[setup][ProtonID] = std::make_unique(Form("npt%sPr", setupName), "; #it{p}_{T} (GeV/#it{c}; Count)", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + + histosResoNpt[setup].resize(ResonanceCount); + histosResoNpt[setup][K0Sideband1] = std::make_unique(Form("npt%sK0SB1", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosResoNpt[setup][K0Signal] = std::make_unique(Form("npt%sK0Sig", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosResoNpt[setup][K0Sideband2] = std::make_unique(Form("npt%sK0SB2", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosResoNpt[setup][LambdaSideband1] = std::make_unique(Form("npt%sLambdaSB1", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosResoNpt[setup][LambdaSignal] = std::make_unique(Form("npt%sLambdaSig", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + histosResoNpt[setup][LambdaSideband2] = std::make_unique(Form("npt%sLambdaSB2", setupName), "; #it{p}_{T} (GeV/#it{c}; Count", ptAxis.binEdges.size() - 1, ptAxis.binEdges.data()); + } if (o2::analysis::gfw::regions.GetSize() < 0) LOGF(error, "Configuration contains vectors of different size - check the GFWRegions configurable"); @@ -1312,7 +1340,7 @@ struct FlowGenericFramework { LOGF(info, "Creating histograms for run %d", run); AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; - AxisSpec etaAxis = {o2::analysis::gfw::etabins, cfgEta->first, cfgEta->second, "#eta"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, cfgKinematics.cfgEta->first, cfgKinematics.cfgEta->second, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec nchAxis = {o2::analysis::gfw::nchbins, o2::analysis::gfw::nchlow, o2::analysis::gfw::nchup, "N_{ch}"}; AxisSpec centAxis = {o2::analysis::gfw::centbinning, "Centrality (%)"}; @@ -1360,6 +1388,66 @@ struct FlowGenericFramework { unsigned int totaluncorr = 0; }; + using NptHistos = std::vector>; + using NptDenominators = std::array; + + NptDenominators getNptDenominators(const NptHistos& nptHistos) + { + NptDenominators dns = {nptHistos[ChargedID]->Integral(), nptHistos[ChargedID]->Integral(), nptHistos[ChargedID]->Integral(), nptHistos[ChargedID]->Integral()}; + if (cfgUsePIDTotal) { + dns[PionID] = nptHistos[PionID]->Integral(); + dns[KaonID] = nptHistos[KaonID]->Integral(); + dns[ProtonID] = nptHistos[ProtonID]->Integral(); + } + return dns; + } + + void fillNptRegistry(FractionSetup setup, const float& centmult, const NptHistos& nptHistos, const NptDenominators& dns) + { + if (dns[ChargedID] <= 0) + return; + + for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { + if (setup == FractionV02) { + registry.fill(HIST("npt_v02_ch"), fPtAxis->GetBinCenter(i), centmult, nptHistos[ChargedID]->GetBinContent(i) / dns[ChargedID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[ChargedID] : 1.0); + if (dns[PionID] > 0) + registry.fill(HIST("npt_v02_pi"), fPtAxis->GetBinCenter(i), centmult, nptHistos[PionID]->GetBinContent(i) / dns[PionID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[PionID] : 1.0); + if (dns[KaonID] > 0) + registry.fill(HIST("npt_v02_ka"), fPtAxis->GetBinCenter(i), centmult, nptHistos[KaonID]->GetBinContent(i) / dns[KaonID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[KaonID] : 1.0); + if (dns[ProtonID] > 0) + registry.fill(HIST("npt_v02_pr"), fPtAxis->GetBinCenter(i), centmult, nptHistos[ProtonID]->GetBinContent(i) / dns[ProtonID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[ProtonID] : 1.0); + } else { + registry.fill(HIST("npt_v0_ch"), fPtAxis->GetBinCenter(i), centmult, nptHistos[ChargedID]->GetBinContent(i) / dns[ChargedID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[ChargedID] : 1.0); + if (dns[PionID] > 0) + registry.fill(HIST("npt_v0_pi"), fPtAxis->GetBinCenter(i), centmult, nptHistos[PionID]->GetBinContent(i) / dns[PionID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[PionID] : 1.0); + if (dns[KaonID] > 0) + registry.fill(HIST("npt_v0_ka"), fPtAxis->GetBinCenter(i), centmult, nptHistos[KaonID]->GetBinContent(i) / dns[KaonID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[KaonID] : 1.0); + if (dns[ProtonID] > 0) + registry.fill(HIST("npt_v0_pr"), fPtAxis->GetBinCenter(i), centmult, nptHistos[ProtonID]->GetBinContent(i) / dns[ProtonID], cfgEventWeight.cfgUseMultiplicityFractionWeights ? dns[ProtonID] : 1.0); + } + } + } + + void fillNptHistos(NptHistos& nptHistos, const float pt, const int pidIndex, const double weightCh, const double weightPid) + { + if (weightCh > 0) + nptHistos[ChargedID]->Fill(pt, weightCh); + if (pidIndex == PionID && weightPid > 0) + nptHistos[PionID]->Fill(pt, weightPid); + if (pidIndex == KaonID && weightPid > 0) + nptHistos[KaonID]->Fill(pt, weightPid); + if (pidIndex == ProtonID && weightPid > 0) + nptHistos[ProtonID]->Fill(pt, weightPid); + } + + void fillNptHistosForEta(const float eta, const float pt, const int pidIndex, const double weightCh, const double weightPid) + { + if (eta > cfgKinematics.cfgEtaNptV02->first && eta < cfgKinematics.cfgEtaNptV02->second) + fillNptHistos(histosNpt[FractionV02], pt, pidIndex, weightCh, weightPid); + if (eta > cfgKinematics.cfgEtaNptV0->first && eta < cfgKinematics.cfgEtaNptV0->second) + fillNptHistos(histosNpt[FractionV0], pt, pidIndex, weightCh, weightPid); + } + template void fillOutputContainers(const float& centmult, const double& rndm) { @@ -1380,7 +1468,7 @@ struct FlowGenericFramework { auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; if (std::abs(val) < 1) { if (corrconfigs.at(l_ind).Head.find("3pcW") != std::string::npos && cfgEventWeight.cfgUseMultiplicityFractionWeights) - dnx *= histosNpt[ChargedID]->Integral(); + dnx *= histosNpt[FractionV02][ChargedID]->Integral(); (dt == Gen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); if (cfgUseGapMethod) { fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); @@ -1398,46 +1486,29 @@ struct FlowGenericFramework { } } - double dnCh = histosNpt[ChargedID]->Integral(); - if (dnCh <= 0) - return; - - double dnPi = dnCh; - double dnKa = dnCh; - double dnPr = dnCh; + const auto& nptV02 = histosNpt[FractionV02]; + const auto& nptV0 = histosNpt[FractionV0]; + auto dnsV02 = getNptDenominators(nptV02); + auto dnsV0 = getNptDenominators(nptV0); - if (cfgUsePIDTotal) { - dnPi = histosNpt[PionID]->Integral(); - dnKa = histosNpt[KaonID]->Integral(); - dnPr = histosNpt[ProtonID]->Integral(); - } - - for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { - registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ChargedID]->GetBinContent(i) / dnCh, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnCh : 1.0); - if (dnPi > 0) - registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i), centmult, histosNpt[PionID]->GetBinContent(i) / dnPi, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnPi : 1.0); - if (dnKa > 0) - registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i), centmult, histosNpt[KaonID]->GetBinContent(i) / dnKa, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnKa : 1.0); - if (dnPr > 0) - registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i), centmult, histosNpt[ProtonID]->GetBinContent(i) / dnPr, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnPr : 1.0); - } + fillNptRegistry(FractionV02, centmult, nptV02, dnsV02); + fillNptRegistry(FractionV0, centmult, nptV0, dnsV0); if (corrconfigsV02.size() < SpeciesCount) return; - // For alternative normalisation with integrated pid spectra - std::vector dns = {dnCh, dnPi, dnKa, dnPr}; - - for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { - for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); - if (dnx == 0) - continue; - auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; - if (std::abs(val) < 1 && dns[l_ind] > 0) { - if (cfgEventWeight.cfgUseMultiplicityFractionWeights) - dnx *= dns[l_ind]; - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + if (dnsV02[ChargedID] > 0) { + for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1 && dnsV02[l_ind] > 0) { + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dnsV02[l_ind]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * nptV02[l_ind]->GetBinContent(i) / dnsV02[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * nptV02[l_ind]->GetBinContent(i) / dnsV02[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + } } } } @@ -1447,7 +1518,7 @@ struct FlowGenericFramework { double mpt = 0; double dnx = 0; - if (cfgEtaPtPt->first * cfgEtaPtPt->second >= 0) { + if (cfgKinematics.cfgEtaPtPt->first * cfgKinematics.cfgEtaPtPt->second >= 0) { if (fFCpt->corrDen[1] == 0.) return; dnx = fFCpt->corrDen[1]; @@ -1465,16 +1536,140 @@ struct FlowGenericFramework { for (uint l_ind = 0; l_ind < SpeciesCount; ++l_ind) { for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - if (dns[l_ind] > 0) { + if (dnsV0[l_ind] > 0) { + double profileWeight = dnx; if (cfgEventWeight.cfgUseMultiplicityFractionWeights) - dnx *= dns[l_ind]; - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], (cfgEventWeight.cfgUseMultiplicityFlowWeights) ?: 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * histosNpt[l_ind]->GetBinContent(i) / dns[l_ind], (cfgEventWeight.cfgUseMultiplicityFlowWeights) ?: 1., rndm); + profileWeight *= dnsV0[l_ind]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * nptV0[l_ind]->GetBinContent(i) / dnsV0[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? profileWeight : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * nptV0[l_ind]->GetBinContent(i) / dnsV0[l_ind], cfgEventWeight.cfgUseMultiplicityFlowWeights ? profileWeight : 1.0, rndm); } } } return; } + template + void fillResonanceOutput(FractionSetup setup, const float& centrality, const double& rndm) + { + if (setup == FractionV02) { + if (histosNpt[FractionV02][ChargedID]->Integral() <= 0) + return; + + double dnK0SB1 = histosNpt[FractionV02][ChargedID]->Integral(); + double dnK0Sig = histosNpt[FractionV02][ChargedID]->Integral(); + double dnK0SB2 = histosNpt[FractionV02][ChargedID]->Integral(); + double dnLambdaSB1 = histosNpt[FractionV02][ChargedID]->Integral(); + double dnLambdaSig = histosNpt[FractionV02][ChargedID]->Integral(); + double dnLambdaSB2 = histosNpt[FractionV02][ChargedID]->Integral(); + + if (cfgUsePIDTotal) { + dnK0SB1 = histosResoNpt[FractionV02][K0Sideband1]->Integral(); + dnK0Sig = histosResoNpt[FractionV02][K0Signal]->Integral(); + dnK0SB2 = histosResoNpt[FractionV02][K0Sideband2]->Integral(); + dnLambdaSB1 = histosResoNpt[FractionV02][LambdaSideband1]->Integral(); + dnLambdaSig = histosResoNpt[FractionV02][LambdaSignal]->Integral(); + dnLambdaSB2 = histosResoNpt[FractionV02][LambdaSideband2]->Integral(); + } + + for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { + if (dnK0SB1 > 0) + registry.fill(HIST("npt_v02_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][K0Sideband1]->GetBinContent(i) / dnK0SB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB1 : 1.); + if (dnK0Sig > 0) + registry.fill(HIST("npt_v02_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][K0Signal]->GetBinContent(i) / dnK0Sig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0Sig : 1.); + if (dnK0SB2 > 0) + registry.fill(HIST("npt_v02_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][K0Sideband2]->GetBinContent(i) / dnK0SB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB2 : 1.); + if (dnLambdaSB1 > 0) + registry.fill(HIST("npt_v02_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][LambdaSideband1]->GetBinContent(i) / dnLambdaSB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB1 : 1.); + if (dnLambdaSig > 0) + registry.fill(HIST("npt_v02_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][LambdaSignal]->GetBinContent(i) / dnLambdaSig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSig : 1.); + if (dnLambdaSB2 > 0) + registry.fill(HIST("npt_v02_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV02][LambdaSideband2]->GetBinContent(i) / dnLambdaSB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB2 : 1.); + } + + std::vector dns = {dnK0SB1, dnK0Sig, dnK0SB2, dnLambdaSB1, dnLambdaSig, dnLambdaSB2}; + + for (uint l_ind = 4; l_ind < corrconfigsV02.size(); ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1 && dns[l_ind - 4] > 0) { + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind - 4]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[FractionV02][l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[FractionV02][l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, rndm); + } + } + } + } else { + if (histosNpt[FractionV0][ChargedID]->Integral() <= 0) + return; + + double dnK0SB1 = histosNpt[FractionV0][ChargedID]->Integral(); + double dnK0Sig = histosNpt[FractionV0][ChargedID]->Integral(); + double dnK0SB2 = histosNpt[FractionV0][ChargedID]->Integral(); + double dnLambdaSB1 = histosNpt[FractionV0][ChargedID]->Integral(); + double dnLambdaSig = histosNpt[FractionV0][ChargedID]->Integral(); + double dnLambdaSB2 = histosNpt[FractionV0][ChargedID]->Integral(); + + if (cfgUsePIDTotal) { + dnK0SB1 = histosResoNpt[FractionV0][K0Sideband1]->Integral(); + dnK0Sig = histosResoNpt[FractionV0][K0Signal]->Integral(); + dnK0SB2 = histosResoNpt[FractionV0][K0Sideband2]->Integral(); + dnLambdaSB1 = histosResoNpt[FractionV0][LambdaSideband1]->Integral(); + dnLambdaSig = histosResoNpt[FractionV0][LambdaSignal]->Integral(); + dnLambdaSB2 = histosResoNpt[FractionV0][LambdaSideband2]->Integral(); + } + + for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { + if (dnK0SB1 > 0) + registry.fill(HIST("npt_v0_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][K0Sideband1]->GetBinContent(i) / dnK0SB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB1 : 1.); + if (dnK0Sig > 0) + registry.fill(HIST("npt_v0_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][K0Signal]->GetBinContent(i) / dnK0Sig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0Sig : 1.); + if (dnK0SB2 > 0) + registry.fill(HIST("npt_v0_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][K0Sideband2]->GetBinContent(i) / dnK0SB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB2 : 1.); + if (dnLambdaSB1 > 0) + registry.fill(HIST("npt_v0_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][LambdaSideband1]->GetBinContent(i) / dnLambdaSB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB1 : 1.); + if (dnLambdaSig > 0) + registry.fill(HIST("npt_v0_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][LambdaSignal]->GetBinContent(i) / dnLambdaSig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSig : 1.); + if (dnLambdaSB2 > 0) + registry.fill(HIST("npt_v0_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[FractionV0][LambdaSideband2]->GetBinContent(i) / dnLambdaSB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB2 : 1.); + } + + std::vector dns = {dnK0SB1, dnK0Sig, dnK0SB2, dnLambdaSB1, dnLambdaSig, dnLambdaSB2}; + + if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) + return; + + double mpt = 0; + double dnx = 0; + if (cfgKinematics.cfgEtaPtPt->first * cfgKinematics.cfgEtaPtPt->second >= 0) { + if (fFCpt->corrDen[1] == 0.) + return; + dnx = fFCpt->corrDen[1]; + mpt = fFCpt->corrNum[1] / dnx; + } else { + if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) + return; + double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; + double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; + dnx = 0.5 * (fFCpt->corrDenSub[0][1] + fFCpt->corrDenSub[1][1]); + mpt = 0.5 * (mptSub1 + mptSub2); + } + + if (std::isnan(mpt)) + return; + + for (uint l_ind = 4; l_ind < corrconfigsV0.size(); ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + if (dns[l_ind - 4] > 0) + if (cfgEventWeight.cfgUseMultiplicityFractionWeights) + dnx *= dns[l_ind - 4]; + (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[FractionV0][l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[FractionV0][l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, rndm); + } + } + } + } + template void processCollision(TCollision collision, TTracks tracks, TV0s v0s, const float& centrality, const int field, const int run) { @@ -1534,8 +1729,10 @@ struct FlowGenericFramework { // process tracks AcceptedTracks acceptedTracks; // Reset fraction histograms per event - for (const auto& h : histosNpt) - h->Reset("ICESM"); + for (const auto& vec : histosNpt) { + for (const auto& h : vec) + h->Reset("ICESM"); + } for (const auto& track : tracks) { processTrack(track, vtxz, field, run, densitycorrections, centrality, acceptedTracks); } @@ -1566,168 +1763,22 @@ struct FlowGenericFramework { fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom); // Reset fraction histograms per event - for (const auto& h : histosResoNpt) - h->Reset("ICESM"); + for (const auto& vec : histosResoNpt) + for (const auto& h : vec) + h->Reset("ICESM"); // Process V0s only for reconstructed-track workflows. if constexpr (dt != Gen) { - for (const auto& v0 : v0s) { - if (resoSwitchVals[UseParticle][K0]) { - double weff = 1; - if (selectK0(collision, v0, tracks, centrality)) { - if (cfgFill.cfgFillQA) - registryQA.fill(HIST("K0/hK0s"), 0.5, 1); - if (cfgEfficiency.cfgUsePIDEfficiencies) { - weff = getEfficiency(v0, centrality, 4); - if (weff < 0) - continue; - if (cfgFill.cfgFillQA) - registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); - } - if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) - histosResoNpt[K0Sideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) - histosResoNpt[K0Signal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand2Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand2Max) - histosResoNpt[K0Sideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - } - } - if (resoSwitchVals[UseParticle][Lambda]) { - double weff = 1.; - if (selectLambda(collision, v0, tracks, centrality)) { - if (cfgFill.cfgFillQA) - registryQA.fill(HIST("Lambda/hLambdas"), 0.5, 1); - if (cfgEfficiency.cfgUsePIDEfficiencies) { - weff = getEfficiency(v0, centrality, 5); - if (weff < 0) - continue; - if (cfgFill.cfgFillQA) - registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); - } - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) - histosResoNpt[LambdaSideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) - histosResoNpt[LambdaSignal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand2Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand2Max) - histosResoNpt[LambdaSideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); - } - } - } - } else { - for (const auto& particle : tracks) { - if (!particle.isPhysicalPrimary()) - continue; - if (!particle.has_daughters()) - continue; - - bool isK0 = (particle.pdgCode() == PDG_t::kK0Short); - bool isLambda = (particle.pdgCode() == PDG_t::kLambda0); - - if (!isK0 && !isLambda) - continue; - - if (isK0) { - histosResoNpt[K0Signal]->Fill(particle.pt(), 1.0); - registry.fill(HIST("MCGen/after/pt_centrality_K0_gen"), particle.pt(), centrality); - } - if (isLambda) { - histosResoNpt[LambdaSignal]->Fill(particle.pt(), 1.0); - registry.fill(HIST("MCGen/after/pt_centrality_Lambda_gen"), particle.pt(), centrality); - } - - // For efficiency - for (const auto& d : particle.template daughters_as()) { - if (std::abs(d.pdgCode()) == PDG_t::kPiPlus) { - if (isK0) - registry.fill(HIST("MCGen/after/pt_centrality_K0_pion_gen"), d.pt(), centrality); - if (isLambda) - registry.fill(HIST("MCGen/after/pt_centrality_Lambda_pion_gen"), d.pt(), centrality); - } - if (std::abs(d.pdgCode()) == PDG_t::kProton) - registry.fill(HIST("MCGen/after/pt_centrality_Lambda_proton_gen"), d.pt(), centrality); - } - } - } - - if (histosNpt[ChargedID]->Integral() <= 0) - return; - - double dnK0SB1 = histosNpt[ChargedID]->Integral(); - double dnK0Sig = histosNpt[ChargedID]->Integral(); - double dnK0SB2 = histosNpt[ChargedID]->Integral(); - double dnLambdaSB1 = histosNpt[ChargedID]->Integral(); - double dnLambdaSig = histosNpt[ChargedID]->Integral(); - double dnLambdaSB2 = histosNpt[ChargedID]->Integral(); - - if (cfgUsePIDTotal) { - dnK0SB1 = histosResoNpt[K0Sideband1]->Integral(); - dnK0Sig = histosResoNpt[K0Signal]->Integral(); - dnK0SB2 = histosResoNpt[K0Sideband2]->Integral(); - dnLambdaSB1 = histosResoNpt[LambdaSideband1]->Integral(); - dnLambdaSig = histosResoNpt[LambdaSignal]->Integral(); - dnLambdaSB2 = histosResoNpt[LambdaSideband2]->Integral(); - } - - for (int i = 1; i <= fPtAxis->GetNbins(); ++i) { - if (dnK0SB1 > 0) - registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband1]->GetBinContent(i) / dnK0SB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB1 : 1.); - if (dnK0Sig > 0) - registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Signal]->GetBinContent(i) / dnK0Sig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0Sig : 1.); - if (dnK0SB2 > 0) - registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[K0Sideband2]->GetBinContent(i) / dnK0SB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnK0SB2 : 1.); - if (dnLambdaSB1 > 0) - registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband1]->GetBinContent(i) / dnLambdaSB1, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB1 : 1.); - if (dnLambdaSig > 0) - registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSignal]->GetBinContent(i) / dnLambdaSig, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSig : 1.); - if (dnLambdaSB2 > 0) - registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i), centrality, histosResoNpt[LambdaSideband2]->GetBinContent(i) / dnLambdaSB2, cfgEventWeight.cfgUseMultiplicityFractionWeights ? dnLambdaSB2 : 1.); - } - - std::vector dns = {dnK0SB1, dnK0Sig, dnK0SB2, dnLambdaSB1, dnLambdaSig, dnLambdaSB2}; - - for (uint l_ind = 4; l_ind < corrconfigsV02.size(); ++l_ind) { - for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); - if (dnx == 0) - continue; - auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; - if (std::abs(val) < 1 && dns[l_ind - 4] > 0) { - if (cfgEventWeight.cfgUseMultiplicityFractionWeights) - dnx *= dns[l_ind - 4]; - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], cfgEventWeight.cfgUseMultiplicityFlowWeights ? dnx : 1.0, lRandom); - } - } - } - - if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) - return; - - double mpt = 0; - double dnx = 0; - if (cfgEtaPtPt->first * cfgEtaPtPt->second >= 0) { - if (fFCpt->corrDen[1] == 0.) - return; - dnx = fFCpt->corrDen[1]; - mpt = fFCpt->corrNum[1] / dnx; + for (const auto& v0 : v0s) + processV0(v0, tracks, collision, centrality); } else { - if (fFCpt->corrDenSub[0][1] == 0. || fFCpt->corrDenSub[1][1] == 0.) - return; - double mptSub1 = fFCpt->corrNumSub[0][1] / fFCpt->corrDenSub[0][1]; - double mptSub2 = fFCpt->corrNumSub[1][1] / fFCpt->corrDenSub[1][1]; - dnx = 0.5 * (fFCpt->corrDenSub[0][1] + fFCpt->corrDenSub[1][1]); - mpt = 0.5 * (mptSub1 + mptSub2); + for (const auto& particle : tracks) + processV0(particle, tracks, collision, centrality); } - if (std::isnan(mpt)) - return; - - for (uint l_ind = 4; l_ind < corrconfigsV0.size(); ++l_ind) { - for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - if (dns[l_ind] > 0) - if (cfgEventWeight.cfgUseMultiplicityFractionWeights) - dnx *= dns[l_ind - 4]; - (dt == Gen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * histosResoNpt[l_ind - 4]->GetBinContent(i) / dns[l_ind - 4], 1.0, lRandom); - } + for (auto setup = 0; setup < FractionSetupCount; ++setup) { + auto fractionSetup = static_cast(setup); + fillResonanceOutput
(fractionSetup, centrality, lRandom); } } @@ -1748,7 +1799,7 @@ struct FlowGenericFramework { if (!nchSelected(track)) return; double weffCh = getEfficiency(track, centrality, 0); - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { + if (track.eta() > cfgKinematics.cfgEtaNch->first && track.eta() < cfgKinematics.cfgEtaNch->second) { if (weffCh > 0) acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; ++acceptedTracks.totaluncorr; @@ -1771,18 +1822,10 @@ struct FlowGenericFramework { pidIndex = ProtonID; registry.fill(HIST("trackQA/after/pt_centrality_proton"), track.pt(), centrality); } - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { - double weff = getEfficiency(track, centrality, pidIndex); - - if (weffCh > 0) - histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); - if (pidIndex == PionID && weff > 0) - histosNpt[PionID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == KaonID && weff > 0) - histosNpt[KaonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == ProtonID && weff > 0) - histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - } + double weff = getEfficiency(track, centrality, pidIndex); + double nptWeightCh = (weffCh > 0) ? ((cfgUseNchCorrection) ? weffCh : 1.0) : -1.0; + double nptWeightPid = (weff > 0) ? ((cfgUseNchCorrection) ? weff : 1.0) : -1.0; + fillNptHistosForEta(track.eta(), track.pt(), pidIndex, nptWeightCh, nptWeightPid); if (cfgFill.cfgFillWeights) { fillWeights(mcParticle, vtxz, 0, run); } else { @@ -1820,18 +1863,11 @@ struct FlowGenericFramework { registry.fill(HIST("MCGen/after/pt_centrality_proton_gen"), track.pt(), centrality); } - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { + if (track.eta() > cfgKinematics.cfgEtaNch->first && track.eta() < cfgKinematics.cfgEtaNch->second) { ++acceptedTracks.total; ++acceptedTracks.totaluncorr; - - histosNpt[ChargedID]->Fill(track.pt()); - if (pidIndex == PionID) - histosNpt[PionID]->Fill(track.pt()); - if (pidIndex == KaonID) - histosNpt[KaonID]->Fill(track.pt()); - if (pidIndex == ProtonID) - histosNpt[ProtonID]->Fill(track.pt()); } + fillNptHistosForEta(track.eta(), track.pt(), pidIndex, 1.0, 1.0); fillPtSums(track, centrality, vtxz); fillGFW(track, centrality, vtxz, pidIndex, densitycorrections); @@ -1844,33 +1880,22 @@ struct FlowGenericFramework { // Select tracks with nominal cuts always if (!nchSelected(track)) return; - double weffCh = getEfficiency(track, centrality, 0); - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { + if (track.eta() > cfgKinematics.cfgEtaNch->first && track.eta() < cfgKinematics.cfgEtaNch->second) { if (weffCh > 0) acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; ++acceptedTracks.totaluncorr; } - if (!trackSelected(track, field)) return; // int pidIndex = 0; // if (cfgUsePID) Need PID for v02 int pidIndex = getNsigmaPID(track); - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) { - double weff = getEfficiency(track, centrality, pidIndex); - - if (weffCh > 0) - histosNpt[ChargedID]->Fill(track.pt(), (cfgUseNchCorrection) ? weffCh : 1.0); - if (pidIndex == PionID && weff > 0) - histosNpt[PionID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == KaonID && weff > 0) - histosNpt[KaonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - if (pidIndex == ProtonID && weff > 0) - histosNpt[ProtonID]->Fill(track.pt(), (cfgUseNchCorrection) ? weff : 1.0); - } - + double weff = getEfficiency(track, centrality, pidIndex); + double nptWeightCh = (weffCh > 0) ? ((cfgUseNchCorrection) ? weffCh : 1.0) : -1.0; + double nptWeightPid = (weff > 0) ? ((cfgUseNchCorrection) ? weff : 1.0) : -1.0; + fillNptHistosForEta(track.eta(), track.pt(), pidIndex, nptWeightCh, nptWeightPid); if (cfgFill.cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { @@ -1887,6 +1912,142 @@ struct FlowGenericFramework { } } + template + inline void processV0(TV0 v0, TTracks tracks, TCollision collision, const float& centrality) + { + if constexpr (dt == Reco) { + using V0TrackTable = std::decay_t; + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + if (resoSwitchVals[UseParticle][K0]) { + double weff = 1; + bool fillK0 = true; + if (cfgEfficiency.cfgUsePIDEfficiencies) { + weff = getEfficiency(v0, centrality, 4); + if (weff < 0) + fillK0 = false; + } + if (fillK0) { + auto K0Selection = selectK0(collision, v0, tracks); + if (K0Selection.selected) { + for (auto setup = 0; setup < FractionSetupCount; ++setup) { + auto fractionSetup = static_cast(setup); + if (!selectionV0DaughterEta(postrack, fractionSetup) || !selectionV0DaughterEta(negtrack, fractionSetup)) + continue; + + if (cfgFill.cfgFillQA && fractionSetup == FractionV02) + fillV0QA(K0Selection, v0, postrack, negtrack, centrality, weff); + registryQA.fill(HIST("K0/hK0Count"), (fractionSetup == FractionV02) ? FillV02DaughterTrackSelection : FillV0DaughterTrackSelection); + + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) + histosResoNpt[fractionSetup][K0Sideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) + histosResoNpt[fractionSetup][K0Signal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand2Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand2Max) + histosResoNpt[fractionSetup][K0Sideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + } + } + } + } + if (resoSwitchVals[UseParticle][Lambda]) { + double weff = 1.; + bool fillLambda = true; + if (cfgEfficiency.cfgUsePIDEfficiencies) { + weff = getEfficiency(v0, centrality, 5); + if (weff < 0) + fillLambda = false; + } + if (fillLambda) { + auto lambdaSelection = selectLambda(collision, v0, tracks); + if (lambdaSelection.selected) { + for (auto setup = 0; setup < FractionSetupCount; ++setup) { + auto fractionSetup = static_cast(setup); + if (!selectionLambdaDaughterEta(postrack, negtrack, lambdaSelection, fractionSetup)) + continue; + registryQA.fill(HIST("Lambda/hLambdaCount"), (fractionSetup == FractionV02) ? FillV02DaughterTrackSelection : FillV0DaughterTrackSelection); + + if (cfgFill.cfgFillQA && fractionSetup == FractionV02) + fillV0QA(lambdaSelection, v0, postrack, negtrack, centrality, weff); + + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) + histosResoNpt[fractionSetup][LambdaSideband1]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) + histosResoNpt[fractionSetup][LambdaSignal]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand2Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand2Max) + histosResoNpt[fractionSetup][LambdaSideband2]->Fill(v0.pt(), (cfgUseNchCorrection) ? weff : 1.0); + } + } + } + } + } else { + if (!v0.isPhysicalPrimary()) + return; + if (!v0.has_daughters()) + return; + + bool isK0 = (v0.pdgCode() == PDG_t::kK0Short); + bool isLambda = (v0.pdgCode() == PDG_t::kLambda0); + + if (!isK0 && !isLambda) + return; + + // To match reconstructed - check that daughters are within v02/v0 eta acceptance + bool isWithinV0Acceptance = true; + bool isWithinV02Acceptance = true; + for (const auto& d : v0.template daughters_as()) { + + if (d.eta() < cfgKinematics.cfgEtaNptV02->first || d.eta() > cfgKinematics.cfgEtaNptV02->second) + isWithinV02Acceptance = false; + if (d.eta() < cfgKinematics.cfgEtaNptV0->first || d.eta() > cfgKinematics.cfgEtaNptV0->second) { + isWithinV0Acceptance = false; + } + } + + if (isK0) { + if (isWithinV02Acceptance) { + histosResoNpt[FractionV02][K0Signal]->Fill(v0.pt(), 1.0); + registry.fill(HIST("MCGen/after/pt_centrality_K0_gen"), v0.pt(), centrality); + } + if (isWithinV0Acceptance) + histosResoNpt[FractionV0][K0Signal]->Fill(v0.pt(), 1.0); + } + if (isLambda) { + if (isWithinV02Acceptance) { + histosResoNpt[FractionV02][LambdaSignal]->Fill(v0.pt(), 1.0); + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_gen"), v0.pt(), centrality); + } + if (isWithinV0Acceptance) + histosResoNpt[FractionV0][LambdaSignal]->Fill(v0.pt(), 1.0); + } + // For efficiency + if (cfgFill.cfgFillQA && isWithinV02Acceptance) { + for (const auto& d : v0.template daughters_as()) { + if (std::abs(d.pdgCode()) == PDG_t::kPiPlus) { + if (isK0) + registry.fill(HIST("MCGen/after/pt_centrality_K0_pion_gen"), d.pt(), centrality); + if (isLambda) + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_pion_gen"), d.pt(), centrality); + } + if (std::abs(d.pdgCode()) == PDG_t::kProton) + registry.fill(HIST("MCGen/after/pt_centrality_Lambda_proton_gen"), d.pt(), centrality); + } + } + } + } + + std::pair getFractionEtaRange(FractionSetup setup) + { + return (setup == FractionV02) ? std::make_pair(cfgKinematics.cfgEtaNptV02->first, cfgKinematics.cfgEtaNptV02->second) : std::make_pair(cfgKinematics.cfgEtaNptV0->first, cfgKinematics.cfgEtaNptV0->second); + } + + struct V0Selection { + bool selected = false; + bool isK0 = false; + bool isL = false; + bool isAL = false; + }; + template bool selectionV0Daughter(TTrack const& track, int pid) { @@ -1913,19 +2074,41 @@ struct FlowGenericFramework { return false; } - // Eta cuts on daughter particles to remove self-correlations with correlated observables - if (track.eta() < cfgEtaV0Daughters->first || track.eta() > cfgEtaV0Daughters->second) + return true; + } + + template + bool selectionV0DaughterEta(TTrack const& track, FractionSetup setup) + { + const auto [etaMin, etaMax] = getFractionEtaRange(setup); + if (track.eta() < etaMin || track.eta() > etaMax) + return false; + if (cfgFill.cfgFillQA) { + if (setup == FractionV02) + registryQA.fill(HIST("trackQA/after/etaV02"), track.eta()); + if (setup == FractionV0) + registryQA.fill(HIST("trackQA/after/etaV0"), track.eta()); + } + return true; + } + + template + bool selectionLambdaDaughterEta(TTrack const& postrack, TTrack const& negtrack, const V0Selection& lambdaSelection, FractionSetup setup) + { + if (lambdaSelection.isL && (!selectionV0DaughterEta(postrack, setup) || !selectionV0DaughterEta(negtrack, setup))) + return false; + if (lambdaSelection.isAL && (!selectionV0DaughterEta(postrack, setup) || !selectionV0DaughterEta(negtrack, setup))) return false; - if (cfgFill.cfgFillQA) - registryQA.fill(HIST("trackQA/after/etaV0Daughters"), track.eta()); return true; } template - bool selectK0(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality) + V0Selection selectK0(TCollision const& collision, TV0 const& v0, TTracks const&) { using V0TrackTable = std::decay_t; + V0Selection selection; + double massK0s = v0.mK0Short(); auto postrack = v0.template posTrack_as(); @@ -1933,76 +2116,58 @@ struct FlowGenericFramework { registryQA.fill(HIST("K0/hK0Count"), FillCandidate); if (postrack.pt() < resoCutVals[PosTrackPt][K0] || negtrack.pt() < resoCutVals[NegTrackPt][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillDaughterPt); if (massK0s < resoCutVals[MassMin][K0] && massK0s > resoCutVals[MassMax][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillMassCut); // Rapidity correction if (v0.yK0Short() > resoCutVals[Rapidity][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillRapidityCut); // DCA cuts for K0short if (std::abs(v0.dcapostopv()) < resoCutVals[DCAPosToPVMin][K0] || std::abs(v0.dcanegtopv()) < resoCutVals[DCANegToPVMin][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillDCAtoPV); if (resoSwitchVals[UseDCAxDaughters][K0] && std::abs(v0.dcaV0daughters()) > resoCutVals[DCAxDaughters][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillDCAxDaughters); // v0 radius cuts if (resoSwitchVals[UseV0Radius][K0] && (v0.v0radius() < resoCutVals[RadiusMin][K0] || v0.v0radius() > resoCutVals[RadiusMax][K0])) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillV0Radius); // cosine pointing angle cuts if (v0.v0cosPA() < resoCutVals[CosPA][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillCosPA); // Proper lifetime if (resoSwitchVals[UseProperLifetime][K0] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[LifeTime][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillProperLifetime); // ArmenterosPodolanskiCut if (resoSwitchVals[UseArmPodCut][K0] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[ArmPodMin][K0]) - return false; + return selection; registryQA.fill(HIST("K0/hK0Count"), FillArmPodCut); if (resoSwitchVals[UseCompetingMassRejection][K0]) { if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < resoCutVals[MassRejection][K0]) - return false; + return selection; if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < resoCutVals[MassRejection][K0]) - return false; + return selection; } registryQA.fill(HIST("K0/hK0Count"), FillCompetingMass); if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Pions)) - return false; - registryQA.fill(HIST("K0/hK0Count"), FillDaughterTrackSelection); + return selection; - if (cfgFill.cfgFillQA) { - registryQA.fill(HIST("K0/hK0Mass_sparse"), massK0s, v0.pt(), centrality); - registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); - registryQA.fill(HIST("K0/hK0Eta"), v0.eta()); - registryQA.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); - registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); - registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); - registryQA.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); - } - - if (doprocessMCReco) { - if (cfgFill.cfgFillQA) { - registry.fill(HIST("trackQA/after/pt_centrality_K0"), v0.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); - } - } - - return true; + selection.selected = true; + selection.isK0 = true; + return selection; } template - bool selectLambda(TCollision const& collision, TV0 const& v0, TTracks const&, const double& centrality) + V0Selection selectLambda(TCollision const& collision, TV0 const& v0, TTracks const&) { using V0TrackTable = std::decay_t; - bool isL = false; // Is lambda candidate - bool isAL = false; // Is anti-lambda candidate + V0Selection selection; double mlambda = v0.mLambda(); double mantilambda = v0.mAntiLambda(); @@ -2013,99 +2178,68 @@ struct FlowGenericFramework { registryQA.fill(HIST("Lambda/hLambdaCount"), FillCandidate); if (postrack.pt() < resoCutVals[PosTrackPt][Lambda] || negtrack.pt() < resoCutVals[NegTrackPt][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterPt); if (mlambda > resoCutVals[MassMin][Lambda] && mlambda < resoCutVals[MassMax][Lambda]) - isL = true; + selection.isL = true; if (mantilambda > resoCutVals[MassMin][Lambda] && mantilambda < resoCutVals[MassMax][Lambda]) - isAL = true; + selection.isAL = true; - if (!isL && !isAL) { - return false; + if (!selection.isL && !selection.isAL) { + return selection; } registryQA.fill(HIST("Lambda/hLambdaCount"), FillMassCut); // Rapidity correction if (v0.yLambda() > resoCutVals[Rapidity][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillRapidityCut); // DCA cuts for lambda and antilambda - if (isL) { + if (selection.isL) { if (std::abs(v0.dcapostopv()) < resoCutVals[DCAPosToPVMin][Lambda] || std::abs(v0.dcanegtopv()) < resoCutVals[DCANegToPVMin][Lambda]) - return false; + return selection; } - if (isAL) { + if (selection.isAL) { if (std::abs(v0.dcapostopv()) < resoCutVals[DCANegToPVMin][Lambda] || std::abs(v0.dcanegtopv()) < resoCutVals[DCAPosToPVMin][Lambda]) - return false; + return selection; } registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAtoPV); if (resoSwitchVals[UseDCAxDaughters][Lambda] && std::abs(v0.dcaV0daughters()) > resoCutVals[DCAxDaughters][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillDCAxDaughters); // v0 radius cuts if (resoSwitchVals[UseV0Radius][Lambda] && (v0.v0radius() < resoCutVals[RadiusMin][Lambda] || v0.v0radius() > resoCutVals[RadiusMax][Lambda])) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillV0Radius); // cosine pointing angle cuts if (v0.v0cosPA() < resoCutVals[CosPA][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillCosPA); // Proper lifetime if (resoSwitchVals[UseProperLifetime][Lambda] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LifeTime][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillProperLifetime); // ArmenterosPodolanskiCut if (resoSwitchVals[UseArmPodCut][Lambda] && (v0.qtarm() / std::abs(v0.alpha())) < resoCutVals[ArmPodMin][Lambda]) - return false; + return selection; registryQA.fill(HIST("Lambda/hLambdaCount"), FillArmPodCut); if (resoSwitchVals[UseCompetingMassRejection][Lambda]) { if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[MassRejection][Lambda]) - return false; + return selection; } registryQA.fill(HIST("Lambda/hLambdaCount"), FillCompetingMass); - if (isL) { + if (selection.isL) { if (!selectionV0Daughter(postrack, Protons) || !selectionV0Daughter(negtrack, Pions)) - return false; + return selection; } - if (isAL) { + if (selection.isAL) { if (!selectionV0Daughter(postrack, Pions) || !selectionV0Daughter(negtrack, Protons)) - return false; + return selection; } - registryQA.fill(HIST("Lambda/hLambdaCount"), FillDaughterTrackSelection); + selection.selected = true; - if (isL && cfgFill.cfgFillQA) { - registryQA.fill(HIST("Lambda/hLambdaMass_sparse"), mlambda, v0.pt(), centrality); - registryQA.fill(HIST("Lambda/hLambdaPhi"), v0.phi()); - registryQA.fill(HIST("Lambda/hLambdaEta"), v0.eta()); - registryQA.fill(HIST("Lambda/PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); - registryQA.fill(HIST("Lambda/PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); - registryQA.fill(HIST("Lambda/PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); - registryQA.fill(HIST("Lambda/PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); - - if (doprocessMCReco) { - registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), negtrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), postrack.pt(), centrality); - } - } - if (isAL && cfgFill.cfgFillQA) { - registryQA.fill(HIST("Lambda/hAntiLambdaMass_sparse"), mantilambda, v0.pt(), centrality); - registryQA.fill(HIST("Lambda/hAntiLambdaPhi"), v0.phi()); - registryQA.fill(HIST("Lambda/hAntiLambdaEta"), v0.eta()); - registryQA.fill(HIST("Lambda/PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); - registryQA.fill(HIST("Lambda/PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); - registryQA.fill(HIST("Lambda/PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); - registryQA.fill(HIST("Lambda/PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); - - if (doprocessMCReco) { - registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), postrack.pt(), centrality); - registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), negtrack.pt(), centrality); - } - } - - return true; + return selection; } template @@ -2117,7 +2251,7 @@ struct FlowGenericFramework { return; // Fill the nominal sums - if (track.eta() > cfgEtaPtPt->first && track.eta() < cfgEtaPtPt->second) + if (track.eta() > cfgKinematics.cfgEtaPtPt->first && track.eta() < cfgKinematics.cfgEtaPtPt->second) fFCpt->fill(weff, track.pt()); // Fill the subevent sums @@ -2215,14 +2349,73 @@ struct FlowGenericFramework { registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_ref"), track.pt()); registryQA.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_poi"), track.pt()); - if (track.eta() > cfgEtaNch->first && track.eta() < cfgEtaNch->second) + if (track.eta() > cfgKinematics.cfgEtaNch->first && track.eta() < cfgKinematics.cfgEtaNch->second) registryQA.fill(HIST("trackQA/after/etaNch"), track.eta()); - if (track.eta() > cfgEtaPtPt->first && track.eta() < cfgEtaPtPt->second && cfgFill.cfgFillQA) + if (track.eta() > cfgKinematics.cfgEtaPtPt->first && track.eta() < cfgKinematics.cfgEtaPtPt->second && cfgFill.cfgFillQA) registryQA.fill(HIST("trackQA/after/etaPtPt"), track.eta()); } } } + template + inline void fillV0QA(const V0Selection& selection, TV0 const& v0, TTrack postrack, TTrack negtrack, const float& centrality, const float& weff) + { + if (selection.isK0) { + registryQA.fill(HIST("K0/hK0Mass_sparse"), v0.mK0Short(), v0.pt(), centrality); + registryQA.fill(HIST("K0/hK0Phi"), v0.phi()); + registryQA.fill(HIST("K0/hK0Eta"), v0.eta()); + registryQA.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); + registryQA.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); + registryQA.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registryQA.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); + + registryQA.fill(HIST("K0/hK0s"), 0.5, 1); + if (cfgEfficiency.cfgUsePIDEfficiencies) + registryQA.fill(HIST("K0/hK0s_corrected"), 0.5, weff); + + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_K0"), v0.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_K0_pion"), negtrack.pt(), centrality); + } + } + if (selection.isL) { + registryQA.fill(HIST("Lambda/hLambdaMass_sparse"), v0.mLambda(), v0.pt(), centrality); + registryQA.fill(HIST("Lambda/hLambdaPhi"), v0.phi()); + registryQA.fill(HIST("Lambda/hLambdaEta"), v0.eta()); + registryQA.fill(HIST("Lambda/PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); + registryQA.fill(HIST("Lambda/PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); + registryQA.fill(HIST("Lambda/PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registryQA.fill(HIST("Lambda/PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); + + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), negtrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), postrack.pt(), centrality); + } + } + if (selection.isAL) { + registryQA.fill(HIST("Lambda/hAntiLambdaMass_sparse"), v0.mAntiLambda(), v0.pt(), centrality); + registryQA.fill(HIST("Lambda/hAntiLambdaPhi"), v0.phi()); + registryQA.fill(HIST("Lambda/hAntiLambdaEta"), v0.eta()); + registryQA.fill(HIST("Lambda/PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); + registryQA.fill(HIST("Lambda/PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); + registryQA.fill(HIST("Lambda/PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registryQA.fill(HIST("Lambda/PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); + + if (doprocessMCReco) { + registry.fill(HIST("trackQA/after/pt_centrality_Lambda"), v0.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_pion"), postrack.pt(), centrality); + registry.fill(HIST("trackQA/after/pt_centrality_Lambda_proton"), negtrack.pt(), centrality); + } + } + if (selection.isL || selection.isAL) { + registryQA.fill(HIST("Lambda/hLambdas"), 0.5, 1); + if (cfgEfficiency.cfgUsePIDEfficiencies) + registryQA.fill(HIST("Lambda/hLambdas_corrected"), 0.5, weff); + } + } + template float getCentrality(TCollision collision) { @@ -2260,7 +2453,7 @@ struct FlowGenericFramework { } o2::framework::expressions::Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ; - o2::framework::expressions::Filter trackFilter = (aod::track::eta > cfgEta->first) && (aod::track::eta < cfgEta->second) && (aod::track::pt > cfgPtmin) && (aod::track::pt < cfgPtmax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; + o2::framework::expressions::Filter trackFilter = (aod::track::eta > cfgKinematics.cfgEta->first) && (aod::track::eta < cfgKinematics.cfgEta->second) && (aod::track::pt > cfgPtmin) && (aod::track::pt < cfgPtmax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; using GFWCollisions = soa::Filtered>; // using GFWTracks = soa::Filtered>; From 846bb89db85f60d783c7b322186307bfd315798e Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:30:05 +0800 Subject: [PATCH 416/449] [PWGCF] Add ITSncls min cut for V0 and casc (#16529) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 43 +++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index b0136c59acc..2d7930493a3 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -168,7 +168,8 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "Maximal DCAz for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.1f, "Maximal DCAxy for tracks") // track quality selections for daughter track - O2_DEFINE_CONFIGURABLE(cfgITSNCls, int, 3, "check minimum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgMaxITSNCls, int, 5, "check maximum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgMinITSNCls, int, 0, "check minimum number of ITS clusters") O2_DEFINE_CONFIGURABLE(cfgChITSNCls, int, 5, "check minimum number of ITS clusters") O2_DEFINE_CONFIGURABLE(cfgTPCNCls, int, 50, "check minimum number of TPC hits") O2_DEFINE_CONFIGURABLE(cfgTPCCrossedRows, int, 70, "check minimum number of TPC crossed rows") @@ -1260,9 +1261,13 @@ struct FlowGfwOmegaXi { if (!isK0s && !isLambda && !isALambda) continue; // track quality check - if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (v0posdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) continue; - if (v0negdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (v0negdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) + continue; + if (v0posdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) + continue; + if (v0negdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) continue; if (v0posdau.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) continue; @@ -1556,11 +1561,17 @@ struct FlowGfwOmegaXi { if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascBuilderOpts.cfgcasc_mlambdawindow.value) continue; // track quality check - if (bachelor.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (bachelor.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) + continue; + if (posdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) + continue; + if (negdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) + continue; + if (bachelor.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) continue; - if (posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (posdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) continue; - if (negdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (negdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) continue; if (bachelor.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) continue; @@ -1999,11 +2010,17 @@ struct FlowGfwOmegaXi { } } // track quality check - if (bachelor.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (bachelor.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) continue; - if (posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (posdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) continue; - if (negdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (negdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) + continue; + if (bachelor.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) + continue; + if (posdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) + continue; + if (negdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) continue; if (bachelor.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) continue; @@ -2184,9 +2201,13 @@ struct FlowGfwOmegaXi { } } // // track quality check - if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (v0posdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) + continue; + if (v0negdau.itsNCls() >= trkQualityOpts.cfgMaxITSNCls.value) + continue; + if (v0posdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) continue; - if (v0negdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (v0negdau.itsNCls() <= trkQualityOpts.cfgMinITSNCls.value) continue; if (v0posdau.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) continue; From 6d8295fb89727df4cabda82965851bd5159d8e63 Mon Sep 17 00:00:00 2001 From: Roberta Ferioli <142217183+Roberta-Ferioli@users.noreply.github.com> Date: Thu, 4 Jun 2026 10:34:02 +0200 Subject: [PATCH 417/449] [PWGCF] Fix bugs on hist manager and close triplet rejection (#16517) --- PWGCF/Femto/Core/cascadeHistManager.h | 2 -- PWGCF/Femto/Core/closeTripletRejection.h | 6 +++--- PWGCF/Femto/Core/tripletBuilder.h | 6 ------ PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx | 7 ++----- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/PWGCF/Femto/Core/cascadeHistManager.h b/PWGCF/Femto/Core/cascadeHistManager.h index 5180f60856e..749f2f16631 100644 --- a/PWGCF/Femto/Core/cascadeHistManager.h +++ b/PWGCF/Femto/Core/cascadeHistManager.h @@ -290,7 +290,6 @@ class CascadeHistManager { mHistogramRegistry = registry; mPdgCode = std::abs(ConfCascadeSelection.pdgCodeAbs.value); - int bachelorPdgCodeAbs = 0; int posDauPdgCodeAbs = 0; int negDauPdgCodeAbs = 0; @@ -328,7 +327,6 @@ class CascadeHistManager } else { LOG(fatal) << "PDG code for Cascade has to be either Xi or Omega"; } - mBachelorManager.template init(registry, BachelorSpecs, absCharge, signBachelor, bachelorPdgCodeAbs); mPosDauManager.template init(registry, PosDauSpecs, absCharge, signPlus, posDauPdgCodeAbs); mNegDauManager.template init(registry, NegDauSpecs, absCharge, signMinus, negDauPdgCodeAbs); diff --git a/PWGCF/Femto/Core/closeTripletRejection.h b/PWGCF/Femto/Core/closeTripletRejection.h index 0e05c865a6f..c75bc2cea37 100644 --- a/PWGCF/Femto/Core/closeTripletRejection.h +++ b/PWGCF/Femto/Core/closeTripletRejection.h @@ -57,9 +57,9 @@ constexpr char PrefixTrack1V0DaughterMe[] = "CPR_Track1V0Dau/ME/"; constexpr char PrefixTrack2V0DaughterMe[] = "CPR_Track2V0Dau/ME/"; constexpr char PrefixTrack1CascadeBachelorSe[] = "CPR_Track1CascadeBachelor/SE/"; -constexpr char PrefixTrack2CascadeBachelorSe[] = "CPR_TrackCascadeBachelor/SE/"; -constexpr char PrefixTrack1CascadeBachelorMe[] = "CPR_TrackCascadeBachelor/ME/"; -constexpr char PrefixTrack2CascadeBachelorMe[] = "CPR_TrackCascadeBachelor/ME/"; +constexpr char PrefixTrack2CascadeBachelorSe[] = "CPR_Track2CascadeBachelor/SE/"; +constexpr char PrefixTrack1CascadeBachelorMe[] = "CPR_Track1CascadeBachelor/ME/"; +constexpr char PrefixTrack2CascadeBachelorMe[] = "CPR_Track2CascadeBachelor/ME/"; template (registry, colHistSpec, confCollisionBinning); mTripletHistManagerSe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); mTripletHistManagerMe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); mTc.template init(confTripletCuts); - if (mTrack1Track2AreSameSpecies) { // Track1 & Track2 & are the same particle species and track 3 is something else mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); mCascadeHistManager.template init(registry, cascadeHistSpec, confCascadeSelection, bachelorHistSpec, posDauHistSpec, negDauHistSpec); - mTrackCleaner.init(confTrackCleaner); mCascadeCleaner.init(confCascadeCleaner); - mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); mCtrSe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); - mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); mCtrMe.init(registry, ctrHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter, confCtr, confCprBachelor, confCprV0Daughter, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); @@ -742,7 +737,6 @@ class TripletTrackTrackCascadeBuilder // setup mixing mMixingPolicy = static_cast(confMixing.policy.value); mMixingDepth = confMixing.depth.value; - // setup rng if necessary if (confMixing.seed.value >= 0) { uint64_t randomSeed = 0; diff --git a/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx b/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx index d37e4741cf2..ae9f0ca2783 100644 --- a/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx +++ b/PWGCF/Femto/Tasks/femtoTripletTrackTrackCascade.cxx @@ -46,7 +46,6 @@ using namespace o2::analysis::femto; struct FemtoTripletTrackTrackCascade { - // setup tables using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; @@ -65,7 +64,6 @@ struct FemtoTripletTrackTrackCascade { using FemtoOmegasWithLabel = o2::soa::Join; o2::framework::SliceCache cache; - // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); @@ -196,7 +194,6 @@ struct FemtoTripletTrackTrackCascade { if (processXi && processOmega) { LOG(fatal) << "Both xi-track and omega-track processing is enabled. Breaking..."; } - // setup columnpolicy for binning // default values are used during instantiation, so we need to explicity update them here mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; @@ -223,7 +220,7 @@ struct FemtoTripletTrackTrackCascade { colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); - omegaHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confOmegaBinning); + bachelorHistSpec = trackhistmanager::makeTrackHistSpecMap(confBachelorBinning); posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); tripletTrackTrackCascadeHistSpec = triplethistmanager::makeTripletHistSpecMap(confTripletBinning); @@ -278,7 +275,7 @@ struct FemtoTripletTrackTrackCascade { } PROCESS_SWITCH(FemtoTripletTrackTrackCascade, processXiMixedEventMc, "Enable processing mixed event processing for tracks and xis with mc information", false); - void processOmegaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoOmegas const& /*omegas*/) + void processOmegaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoOmegas const& /*omega*/) { tripletTrackTrackOmegaBuilder.processSameEvent(col, tracks, trackPartition1, trackPartition2, omegaPartition, cache); } From 11efab07a9bb12bd712cf3c40af142ec9d21be05 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Thu, 4 Jun 2026 12:17:27 +0200 Subject: [PATCH 418/449] [PWGCF] Add MC gen process functions (#16531) --- .../TableProducer/longrangeMaker.cxx | 8 +- .../Tasks/longrangecorrDerived.cxx | 92 +++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 4dd36146ce2..03a5d861653 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -880,7 +880,7 @@ struct LongrangeMaker { continue; } // Fill midrapidity tracks - if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) + if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMax) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks if (cfgfittrksel.cfgFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0aEtaMax) @@ -888,7 +888,7 @@ struct LongrangeMaker { if (cfgfittrksel.cfgFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax) + if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax && particle.pt() > cfgmfttrksel.cfgMftPtCutMin && particle.pt() < cfgmfttrksel.cfgMftPtCutMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } @@ -909,7 +909,7 @@ struct LongrangeMaker { continue; } // Fill midrapidity tracks - if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMult) + if (std::abs(particle.eta()) < cfgtrksel.cfgEtaCut && particle.pt() > cfgtrksel.cfgPtCutMin && particle.pt() < cfgtrksel.cfgPtCutMax) lrmidmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), particle.flags()); // Fill FT0 tracks if (cfgfittrksel.cfgFt0aEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0aEtaMax) @@ -917,7 +917,7 @@ struct LongrangeMaker { if (cfgfittrksel.cfgFt0cEtaMin < particle.eta() && particle.eta() < cfgfittrksel.cfgFt0cEtaMax) lrft0cmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); // Fill MFT tracks - if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax) + if (cfgmfttrksel.cfgMftEtaMin < particle.eta() && particle.eta() < cfgmfttrksel.cfgMftEtaMax && particle.pt() > cfgmfttrksel.cfgMftPtCutMin && particle.pt() < cfgmfttrksel.cfgMftPtCutMax) lrmftmctracks(lrmccollision.lastIndex(), particle.pt(), particle.eta(), particle.phi()); } } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 79b3b67238c..36e1e416722 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -502,6 +502,38 @@ struct LongrangecorrDerived { } // pair loop } // process MC mixed + template + void processMcGenSame(McCollsTable::iterator const& mccollision, TTriggers const& triggers, TAssocs const& assocs) + { + if (std::abs(mccollision.posZ()) >= cfgSel.cfgVtxCut) { + return; + } + fillCollQA(mccollision); + auto multiplicity = mccollision.multiplicity(); + fillCorrHist(same, triggers, assocs, false, mccollision.posZ(), multiplicity, 1.0); + } // process MC gen same + + template + void processMcGenMixed(McCollsTable const& mccollisions, TrackTypes&&... tracks) + { + auto getMultiplicity = [this](auto& collision) { + (void)this; + return collision.multiplicity(); + }; + using MixedBinning = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getMultiplicity)>; + MixedBinning binningOnVtxAndMult{{getMultiplicity}, {cfgAxis.axisVtxZME, cfgAxis.axisMultME}, true}; + auto tracksTuple = std::make_tuple(std::forward(tracks)...); + using TupleAtrack = std::tuple_element<0, decltype(tracksTuple)>::type; + using TupleBtrack = std::tuple_element - 1, decltype(tracksTuple)>::type; + Pair pairs{binningOnVtxAndMult, cfgSel.cfgNmixedevent, -1, mccollisions, tracksTuple, &cache}; + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [col1, tracks1, col2, tracks2] = *it; + float eventweight = 1.0f / it.currentWindowNeighbours(); + auto multiplicity = getMultiplicity(col1); + fillCorrHist(mixed, tracks1, tracks2, true, col1.posZ(), multiplicity, eventweight); + } // pair loop + } // process MC gen mixed + void processTpcft0aSE(CollsTable::iterator const& col, TrksTable const& tracks, Ft0aTrksTable const& ft0as) { processSame(col, tracks, ft0as); @@ -700,6 +732,56 @@ struct LongrangecorrDerived { processMcMixed(mccollisions, collisions, ft0as, ft0cs); } + void processMcGenTpcft0aSE(McCollsTable::iterator const& mccollision, McTrksTable const& tracks, McFt0aTrksTable const& ft0as) + { + processMcGenSame(mccollision, tracks, ft0as); + } + + void processMcGenTpcft0cSE(McCollsTable::iterator const& mccollision, McTrksTable const& tracks, McFt0cTrksTable const& ft0cs) + { + processMcGenSame(mccollision, tracks, ft0cs); + } + + void processMcGenTpcmftSE(McCollsTable::iterator const& mccollision, McTrksTable const& tracks, McMftTrksTable const& mfts) + { + processMcGenSame(mccollision, tracks, mfts); + } + + void processMcGenMftft0aSE(McCollsTable::iterator const& mccollision, McMftTrksTable const& mfts, McFt0aTrksTable const& ft0as) + { + processMcGenSame(mccollision, mfts, ft0as); + } + + void processMcGenFt0aft0cSE(McCollsTable::iterator const& mccollision, McFt0aTrksTable const& ft0as, McFt0cTrksTable const& ft0cs) + { + processMcGenSame(mccollision, ft0as, ft0cs); + } + + void processMcGenTpcft0aME(McCollsTable const& mccollisions, McTrksTable const& tracks, McFt0aTrksTable const& ft0as) + { + processMcGenMixed(mccollisions, tracks, ft0as); + } + + void processMcGenTpcft0cME(McCollsTable const& mccollisions, McTrksTable const& tracks, McFt0cTrksTable const& ft0cs) + { + processMcGenMixed(mccollisions, tracks, ft0cs); + } + + void processMcGenTpcmftME(McCollsTable const& mccollisions, McTrksTable const& tracks, McMftTrksTable const& mfts) + { + processMcGenMixed(mccollisions, tracks, mfts); + } + + void processMcGenMftft0aME(McCollsTable const& mccollisions, McMftTrksTable const& mfts, McFt0aTrksTable const& ft0as) + { + processMcGenMixed(mccollisions, mfts, ft0as); + } + + void processMcGenFt0aft0cME(McCollsTable const& mccollisions, McFt0aTrksTable const& ft0as, McFt0cTrksTable const& ft0cs) + { + processMcGenMixed(mccollisions, ft0as, ft0cs); + } + PROCESS_SWITCH(LongrangecorrDerived, processTpcft0aSE, "same event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processTpcft0aME, "mixed event TPC vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processTpcft0cSE, "same event TPC vs FT0C", false); @@ -736,6 +818,16 @@ struct LongrangecorrDerived { PROCESS_SWITCH(LongrangecorrDerived, processMcMftft0aME, "mixed MC event MFT vs FT0A", false); PROCESS_SWITCH(LongrangecorrDerived, processMcFt0aft0cSE, "same MC event FT0A vs FT0C", false); PROCESS_SWITCH(LongrangecorrDerived, processMcFt0aft0cME, "mixed MC event FT0A vs FT0C", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcft0aSE, "same MC gen event TPC vs FT0A", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcft0aME, "mixed MC gen event TPC vs FT0A", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcft0cSE, "same MC gen event TPC vs FT0C", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcft0cME, "mixed MC gen event TPC vs FT0C", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcmftSE, "same MC gen event TPC vs MFT", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenTpcmftME, "mixed MC gen event TPC vs MFT", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenMftft0aSE, "same MC gen event MFT vs FT0A", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenMftft0aME, "mixed MC gen event MFT vs FT0A", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenFt0aft0cSE, "same MC gen event FT0A vs FT0C", false); + PROCESS_SWITCH(LongrangecorrDerived, processMcGenFt0aft0cME, "mixed MC gen event FT0A vs FT0C", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From d7af5fca46fca6a12eb2f913cc111084eb2ec658 Mon Sep 17 00:00:00 2001 From: Andrea Giovanni Riffero Date: Thu, 4 Jun 2026 16:05:42 +0200 Subject: [PATCH 419/449] [PWGUD] Update ptSpectraInclusiveUpc.cxx (#16534) --- PWGUD/Tasks/ptSpectraInclusiveUpc.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx b/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx index 8ddaff46569..f4523ae3135 100644 --- a/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx +++ b/PWGUD/Tasks/ptSpectraInclusiveUpc.cxx @@ -56,13 +56,13 @@ struct PtSpectraInclusiveUpc { Configurable nBinsDCAxy{"nBinsDCAxy", 100, "N bins in DCA_{xy} histos"}; Configurable applyKineCutsInGen{"applyKineCutsInGen", false, "Apply kinematic cuts in the generated level"}; - Preslice perCollision = aod::track::collisionId; - Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; // define abbreviations - using CCs = soa::Join; + using CCs = soa::Join; using CC = CCs::iterator; - using TCs = soa::Join; - using TC = TCs::iterator; + using CCMCs = soa::Join; + using CCMC = CCMCs::iterator; + using TCs = soa::Join; + using TCMCs = soa::Join; const double etaMax = 0.9; const double yMax = 0.9; @@ -153,7 +153,7 @@ struct PtSpectraInclusiveUpc { } } - void processReco(CC const&, TCs const& tracks, aod::UDMcParticles const&) + void processReco(CCMC const&, TCMCs const& tracks, aod::UDMcParticles const&) { double dcaXyLimit = 0; From 824348f5dcdf9a58e89e82743c238779cb2e3e9e Mon Sep 17 00:00:00 2001 From: tutripat <73981392+tutripat@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:11:47 +0200 Subject: [PATCH 420/449] [PWGLF] Minor configurable changes (#16532) Co-authored-by: ALICE Action Bot --- .../PseudorapidityDensityMFT.cxx | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx index c765142dbac..ed76d333570 100644 --- a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx @@ -83,7 +83,6 @@ AxisSpec dcaXyAxis = {6000, -30, 30}; AxisSpec dcaZAxis = {6000, -30, 30}; AxisSpec dcaXAxis = {6000, -30, 30}; AxisSpec dcaYAxis = {6000, -30, 30}; // previous AxisSpec dcaYAxis = {2000, -10, 10}; - // AxisSpec dcaXyAxis = {600, -0.15f, 0.15f}; // AxisSpec dcaZAxis = {600, -0.15f, 0.15f}; // AxisSpec dcaXAxis = {600, -0.15f, 0.15f}; @@ -91,7 +90,6 @@ AxisSpec dcaYAxis = {6000, -30, 30}; // previous AxisSpec dcaYAxis = {2000, -10 // bin width 0.0005 cm: range [-30, 30] cm => 60/0.0005 = 120000 bins // Keep bin width = 0.0005 cm (5 um): range [-1, 1] cm => 2.0/0.0005 = 4000 bins // AxisSpec axisBinsDCA = {600, -0.15f, 0.15f, "#it{dca}_{xy} (cm)"}; - AxisSpec centAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; // Vertex position axes (cm) @@ -345,7 +343,8 @@ struct PseudorapidityDensityMFT { Configurable estimatorEta{"estimatorEta", 1.0, "eta range for INEL>0 sample definition"}; - + Configurable usePerCollisionSampleGt0Cut{"usePerCollisionSampleGt0Cut", true, "Require at least one central-barrel track in the per-collision sample"}; + Configurable useMidtracksAndPerCollisionSampleGt0Cut{"useMidtracksAndPerCollisionSampleGt0Cut", true, "Require both INEL>0 midtracks and at least one central-barrel track in the per-collision sample"}; Configurable useEvSel{"useEvSel", true, "use event selection"}; Configurable useNoSameBunchPileup{"useNoSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; Configurable useGoodItsLayersAll{"useGoodItsLayersAll", true, "all ITS layers are in a good state"}; @@ -1562,20 +1561,24 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_all"), nTrk, z); fillDataCut(DataCutBin::VzWindow); // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Vz)); + const bool hasPerCollisionSample = perCollisionSample.size() > 0; + const bool hasMidtracks = midtracks.size() > 0; if (midtracks.size() > 0) { // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Sel8VzInelGt0)); registry.fill(HIST("EventsNtrkZvtx_gt0"), nTrk, z); registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), nTrk, z); eventsInel.insert(collision.globalIndex()); } - if (perCollisionSample.size() > 0) { - // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::PerCollisionSampleGt0)); - fillDataCut(DataCutBin::PerCollisionSampleGt0); + if (usePerCollisionSampleGt0Cut && !hasPerCollisionSample) { + return; } - if (midtracks.size() > 0 && perCollisionSample.size() > 0) { - // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::MidtracksAndPerCollisionSampleGt0)); - fillDataCut(DataCutBin::InelGt0); + fillDataCut(DataCutBin::PerCollisionSampleGt0); + + if (useMidtracksAndPerCollisionSampleGt0Cut && !(hasMidtracks && hasPerCollisionSample)) { + return; } + // registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::MidtracksAndPerCollisionSampleGt0)); + fillDataCut(DataCutBin::InelGt0); const auto passEventSelection = [&](auto const& collision) { struct EvSelStep { @@ -1626,6 +1629,7 @@ struct PseudorapidityDensityMFT { const float ndf = getTrackNdf(track); const float chi2ndf = track.chi2() / ndf; float phi = track.phi(); + float ptCut = track.pt(); o2::math_utils::bringTo02Pi(phi); const float dcaXyCut = retrack.bestDCAXY(); @@ -1641,7 +1645,7 @@ struct PseudorapidityDensityMFT { ((phi <= PhiVetoLow) || ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || (phi >= PhiVetoHigh))) || - (useDCAxyCut && dcaXyCut > maxDCAxy); + (useDCAxyCut && dcaXyCut > maxDCAxy) || (usePtCut && ptCut > cfgnPt); if constexpr (std::is_same_v>) { const float dcaZCut = retrack.bestDCAZ(); From aa0d5104ca98d54be39c7a0279a973861f7a962a Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 4 Jun 2026 18:04:05 +0200 Subject: [PATCH 421/449] [PWGEM/Dilepton] fix dphi range in SCT (#16535) --- PWGEM/Dilepton/Utils/SemiCharmTag.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGEM/Dilepton/Utils/SemiCharmTag.h b/PWGEM/Dilepton/Utils/SemiCharmTag.h index 8f3610e1e23..c38df4337af 100644 --- a/PWGEM/Dilepton/Utils/SemiCharmTag.h +++ b/PWGEM/Dilepton/Utils/SemiCharmTag.h @@ -175,8 +175,8 @@ LHPair makePairLeptonTrack(TFitter& fitter, TCollision const& collision, TLepton pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); - pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron - pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI, 1U); // lepton - hadron pair.isOK = true; return pair; } @@ -302,8 +302,8 @@ LHPair makePairLeptonV0(TFitter& fitter, TCollision const& collision, TLepton co pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); - pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron - pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI, 1U); // lepton - hadron pair.isOK = true; return pair; @@ -434,8 +434,8 @@ LHPair makePairLeptonCascade(TFitter& fitter, TCollision const& collision, TLept pair.mass = v12.M(); pair.pt = v12.Pt(); pair.p = v12.P(); - pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron - pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI / 2, 1U); // lepton - hadron + pair.deta = v1.Eta() - v2.Eta(); // lepton - hadron + pair.dphi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(v1.Phi(), 0, 1U) - RecoDecay::constrainAngle(v2.Phi(), 0, 1U), -M_PI, 1U); // lepton - hadron pair.isOK = true; return pair; From df09e93cc2e6f53a4e9970bfafaa61750b6455f7 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:23:58 +0200 Subject: [PATCH 422/449] [PWGLF] Refactoring and bug fixes (#16518) Co-authored-by: ALICE Action Bot --- .../Nuspex/coalescenceTreeProducer.cxx | 716 +++++------------- 1 file changed, 208 insertions(+), 508 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx index 4b478ad4d89..339fd71a655 100644 --- a/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx +++ b/PWGLF/TableProducer/Nuspex/coalescenceTreeProducer.cxx @@ -10,8 +10,7 @@ // or submit itself to any jurisdiction. // /// \file coalescenceTreeProducer.cxx -/// \brief Tree producer for deuteron, triton, helium-3, and hypertriton -/// coalescence studies. +/// \brief Tree producer for deuteron, triton, helium-3, and hypertriton coalescence studies. /// /// The task loops over generated MC particles and builds bound-state /// candidates according to the selected species. For each candidate, @@ -55,125 +54,75 @@ #include #include +using namespace std; using namespace o2; +using namespace o2::soa; +using namespace o2::aod; using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::constants::math; + +// Lightweight particle container +struct ReducedParticle { + int64_t idPart = 0; + int pdgPart = 0; + float xPart = 0.f; + float yPart = 0.f; + float zPart = 0.f; + float tPart = 0.f; + float pxPart = 0.f; + float pyPart = 0.f; + float pzPart = 0.f; +}; struct CoalescenceTreeProducer { - // Supported bound-state species - enum BoundStateSpecies { - kDeuteron = 0, - kTriton = 1, - kHelium3 = 2, - kHypertriton = 3 - }; - + // Histogram registry HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // Analysis parameters - Configurable zVtx{"zVtx", 10.f, "Maximum |z vertex| in cm"}; + // Configurable analysis parameters + Configurable zVtxMax{"zVtxMax", 10.f, "Maximum |z vertex| in cm"}; Configurable etaMax{"etaMax", 1.5f, "Maximum |eta| for generated particles"}; Configurable pRhoMax{"pRhoMax", 1.0f, "Maximum Jacobi p_rho in GeV/c"}; Configurable pLambdaMax{"pLambdaMax", 1.0f, "Maximum Jacobi p_lambda in GeV/c"}; - Configurable boundStateSpecies{"boundStateSpecies", kHypertriton, "Species selector: 0 = deuteron, 1 = triton, 2 = helium3, 3 = hypertriton"}; - - Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + // Output tree storing bound-state candidates OutputObj treeBoundState{"treeBoundState", OutputObjHandlingPolicy::AnalysisObject}; - int64_t eventID = 0; // Event ID - int64_t idB1 = 0, idB2 = 0, idB3 = 0; // MC particle IDs + // Variables to be stored in the tree + Long64_t eventID = 0; // Event identifier + Long64_t nMatterCandidatesPerEvent = 0; // Number of matter candidates per event + Long64_t nAntimatterCandidatesPerEvent = 0; // Number of antimatter candidates per event + Long64_t idB1 = 0, idB2 = 0, idB3 = 0; // Constituent identifiers + int pdgB1 = 0, pdgB2 = 0, pdgB3 = 0; // Constituent PDG codes - int pdgB1 = 0, pdgB2 = 0, pdgB3 = 0; - int chargeB1 = 0, chargeB2 = 0, chargeB3 = 0; - - // Space-time coordinates and momentum components + // Constituent space-time coordinates and momentum components float xB1 = 0.f, yB1 = 0.f, zB1 = 0.f, tB1 = 0.f, pxB1 = 0.f, pyB1 = 0.f, pzB1 = 0.f; float xB2 = 0.f, yB2 = 0.f, zB2 = 0.f, tB2 = 0.f, pxB2 = 0.f, pyB2 = 0.f, pzB2 = 0.f; float xB3 = 0.f, yB3 = 0.f, zB3 = 0.f, tB3 = 0.f, pxB3 = 0.f, pyB3 = 0.f, pzB3 = 0.f; - struct Particle { - int64_t id = 0; - int pdg = 0; - int charge = 0; - - float x = 0.f; - float y = 0.f; - float z = 0.f; - float t = 0.f; - - float px = 0.f; - float py = 0.f; - float pz = 0.f; - - float mass = 0.f; - - Particle() = default; - - template - explicit Particle(T const& p) - : id(p.globalIndex()), - pdg(p.pdgCode()), - charge(chargeFromPdg(pdg)), - x(p.vx()), - y(p.vy()), - z(p.vz()), - t(p.vt()), - px(p.px()), - py(p.py()), - pz(p.pz()), - mass(static_cast(massFromPdg(pdg))) - { - } - - static int chargeFromPdg(int pdg) - { - if (pdg == PDG_t::kProton) { - return 1; - } - if (pdg == PDG_t::kProtonBar) { - return -1; - } - return 0; - } - - static double massFromPdg(int pdg) - { - switch (std::abs(pdg)) { - case PDG_t::kProton: - return o2::constants::physics::MassProton; - case PDG_t::kNeutron: - return o2::constants::physics::MassNeutron; - case PDG_t::kLambda0: - return o2::constants::physics::MassLambda0; - default: - return -1.; - } - } - }; - - void init(InitContext&) + // Initialize output objects and histograms + void init(InitContext const&) { + // Event selection counter registry.add("eventCounter", "event Counter", HistType::kTH1F, {{5, 0, 5, "counter"}}); registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(1, "Before z-vertex cut"); registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(2, "After z-vertex cut"); - registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(3, "After non-empty lists"); + registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(3, "After non-empty constituent lists"); + registry.get(HIST("eventCounter"))->GetXaxis()->SetBinLabel(4, "After non-empty candidate lists"); + + // Output tree for bound-state candidates + treeBoundState.setObject(new TTree("BoundStateTree", "Tree for coalescence")); - // Tree for pairs/triplets. - // For deuterons only the first two baryons are stored. - // For three-body states, the third-baryon branches are also created. - treeBoundState.setObject(new TTree("BoundStateTree", "Tree for coalescence studies")); + // Event information treeBoundState->Branch("eventID", &eventID, "eventID/L"); + treeBoundState->Branch("nMatterCandidatesPerEvent", &nMatterCandidatesPerEvent, "nMatterCandidatesPerEvent/L"); + treeBoundState->Branch("nAntimatterCandidatesPerEvent", &nAntimatterCandidatesPerEvent, "nAntimatterCandidatesPerEvent/L"); + // Constituent 1: ID, PDG code, space-time coordinates, and momentum components treeBoundState->Branch("idB1", &idB1, "idB1/L"); - treeBoundState->Branch("idB2", &idB2, "idB2/L"); - treeBoundState->Branch("pdgB1", &pdgB1, "pdgB1/I"); - treeBoundState->Branch("pdgB2", &pdgB2, "pdgB2/I"); - - treeBoundState->Branch("chargeB1", &chargeB1, "chargeB1/I"); - treeBoundState->Branch("chargeB2", &chargeB2, "chargeB2/I"); - treeBoundState->Branch("xB1", &xB1, "xB1/F"); treeBoundState->Branch("yB1", &yB1, "yB1/F"); treeBoundState->Branch("zB1", &zB1, "zB1/F"); @@ -182,6 +131,9 @@ struct CoalescenceTreeProducer { treeBoundState->Branch("pyB1", &pyB1, "pyB1/F"); treeBoundState->Branch("pzB1", &pzB1, "pzB1/F"); + // Constituent 2: ID, PDG code, space-time coordinates, and momentum components + treeBoundState->Branch("idB2", &idB2, "idB2/L"); + treeBoundState->Branch("pdgB2", &pdgB2, "pdgB2/I"); treeBoundState->Branch("xB2", &xB2, "xB2/F"); treeBoundState->Branch("yB2", &yB2, "yB2/F"); treeBoundState->Branch("zB2", &zB2, "zB2/F"); @@ -190,12 +142,10 @@ struct CoalescenceTreeProducer { treeBoundState->Branch("pyB2", &pyB2, "pyB2/F"); treeBoundState->Branch("pzB2", &pzB2, "pzB2/F"); - if (static_cast(boundStateSpecies) != kDeuteron) { + // Constituent 3: ID, PDG code, space-time coordinates, and momentum components (three-body bound states only) + if (doprocessHypertriton) { treeBoundState->Branch("idB3", &idB3, "idB3/L"); - treeBoundState->Branch("pdgB3", &pdgB3, "pdgB3/I"); - treeBoundState->Branch("chargeB3", &chargeB3, "chargeB3/I"); - treeBoundState->Branch("xB3", &xB3, "xB3/F"); treeBoundState->Branch("yB3", &yB3, "yB3/F"); treeBoundState->Branch("zB3", &zB3, "zB3/F"); @@ -206,477 +156,227 @@ struct CoalescenceTreeProducer { } } - ROOT::Math::PxPyPzMVector makeFourVector(Particle const& p) - { - return ROOT::Math::PxPyPzMVector{p.px, p.py, p.pz, p.mass}; - } - - void storePair(Particle const& b1, Particle const& b2) - { - idB1 = b1.id; - idB2 = b2.id; - - pdgB1 = b1.pdg; - pdgB2 = b2.pdg; - - chargeB1 = b1.charge; - chargeB2 = b2.charge; - - xB1 = b1.x; - yB1 = b1.y; - zB1 = b1.z; - tB1 = b1.t; - pxB1 = b1.px; - pyB1 = b1.py; - pzB1 = b1.pz; - - xB2 = b2.x; - yB2 = b2.y; - zB2 = b2.z; - tB2 = b2.t; - pxB2 = b2.px; - pyB2 = b2.py; - pzB2 = b2.pz; - - treeBoundState->Fill(); - } - - void storeTriplet(Particle const& b1, Particle const& b2, Particle const& b3) + // Assign mass based on PDG code + static double massFromPdg(int pdg) { - idB1 = b1.id; - idB2 = b2.id; - idB3 = b3.id; - - pdgB1 = b1.pdg; - pdgB2 = b2.pdg; - pdgB3 = b3.pdg; - - chargeB1 = b1.charge; - chargeB2 = b2.charge; - chargeB3 = b3.charge; - - xB1 = b1.x; - yB1 = b1.y; - zB1 = b1.z; - tB1 = b1.t; - pxB1 = b1.px; - pyB1 = b1.py; - pzB1 = b1.pz; - - xB2 = b2.x; - yB2 = b2.y; - zB2 = b2.z; - tB2 = b2.t; - pxB2 = b2.px; - pyB2 = b2.py; - pzB2 = b2.pz; - - xB3 = b3.x; - yB3 = b3.y; - zB3 = b3.z; - tB3 = b3.t; - pxB3 = b3.px; - pyB3 = b3.py; - pzB3 = b3.pz; - - treeBoundState->Fill(); + switch (std::abs(pdg)) { + case PDG_t::kProton: + return o2::constants::physics::MassProton; + case PDG_t::kNeutron: + return o2::constants::physics::MassNeutron; + case PDG_t::kLambda0: + return o2::constants::physics::MassLambda0; + default: + return 0.0; + } } - bool passTwoBodySkim(Particle const& b1, Particle const& b2) + // Apply a momentum-space skim using Jacobi momenta in the candidate rest frame + template + bool passThreeBodySkim(const ReducedPart& b1, const ReducedPart& b2, const ReducedPart& b3) { - auto p4B1 = makeFourVector(b1); - auto p4B2 = makeFourVector(b2); - - auto candidate = p4B1 + p4B2; - - // BoostToCM() returns the boost vector needed to go from the lab frame - // to the candidate center-of-mass frame. - auto betaCandidate = candidate.BoostToCM(); - ROOT::Math::Boost boostToRest(betaCandidate); - - auto p4B1Star = boostToRest(p4B1); - auto p4B2Star = boostToRest(p4B2); - - /* - // Space-time propagation block. - // Not needed for the present skim because the selection is based only on - // the relative momentum pRho in the candidate rest frame. - // - // This block can be re-enabled later if one wants to apply coordinate-space - // or full phase-space coalescence selections, e.g. cuts on relative distance - // after propagation to a common time. - - ROOT::Math::XYZTVector x4B1{b1.x, b1.y, b1.z, b1.t}; - ROOT::Math::XYZTVector x4B2{b2.x, b2.y, b2.z, b2.t}; - - auto x4B1Star = boostToRest(x4B1); - auto x4B2Star = boostToRest(x4B2); - - const double tMax = std::max(x4B1Star.T(), x4B2Star.T()); - - ROOT::Math::XYZVector rB1{x4B1Star.X(), x4B1Star.Y(), x4B1Star.Z()}; - ROOT::Math::XYZVector rB2{x4B2Star.X(), x4B2Star.Y(), x4B2Star.Z()}; - - ROOT::Math::XYZVector vB1 = p4B1Star.Vect() / p4B1Star.E(); - ROOT::Math::XYZVector vB2 = p4B2Star.Vect() / p4B2Star.E(); - - rB1 += vB1 * (tMax - x4B1Star.T()); - rB2 += vB2 * (tMax - x4B2Star.T()); - */ - - const ROOT::Math::XYZVector pB1Star = p4B1Star.Vect(); - const ROOT::Math::XYZVector pB2Star = p4B2Star.Vect(); - - const double m12 = b1.mass + b2.mass; - - ROOT::Math::XYZVector pRho = (b2.mass * pB1Star - b1.mass * pB2Star) / m12; - - if (pRho.R() > pRhoMax) { + // Constituent masses from PDG codes + double m1 = massFromPdg(b1.pdgPart); + double m2 = massFromPdg(b2.pdgPart); + double m3 = massFromPdg(b3.pdgPart); + if (m1 <= 0.0 || m2 <= 0.0 || m3 <= 0.0) { return false; } - return true; - } - bool passThreeBodySkim(Particle const& b1, Particle const& b2, Particle const& b3) - { - auto p4B1 = makeFourVector(b1); - auto p4B2 = makeFourVector(b2); - auto p4B3 = makeFourVector(b3); + // Constituent four-momenta in the laboratory frame + auto p4B1 = ROOT::Math::PxPyPzMVector{b1.pxPart, b1.pyPart, b1.pzPart, m1}; + auto p4B2 = ROOT::Math::PxPyPzMVector{b2.pxPart, b2.pyPart, b2.pzPart, m2}; + auto p4B3 = ROOT::Math::PxPyPzMVector{b3.pxPart, b3.pyPart, b3.pzPart, m3}; + // Candidate four-momentum auto candidate = p4B1 + p4B2 + p4B3; - // BoostToCM() returns the boost vector needed to go from the lab frame - // to the candidate center-of-mass frame. + // Boost to the candidate rest frame auto betaCandidate = candidate.BoostToCM(); ROOT::Math::Boost boostToRest(betaCandidate); + // Constituent momenta in the candidate rest frame auto p4B1Star = boostToRest(p4B1); auto p4B2Star = boostToRest(p4B2); auto p4B3Star = boostToRest(p4B3); - - /* - // Space-time propagation block. - // Not needed for the present skim because the selection is based only on - // the Jacobi relative momenta pRho and pLambda in the candidate rest frame. - // - // This block can be re-enabled later if one wants to apply coordinate-space - // or full phase-space coalescence selections, e.g. cuts on relative distances - // after propagation to a common time. - - ROOT::Math::XYZTVector x4B1{b1.x, b1.y, b1.z, b1.t}; - ROOT::Math::XYZTVector x4B2{b2.x, b2.y, b2.z, b2.t}; - ROOT::Math::XYZTVector x4B3{b3.x, b3.y, b3.z, b3.t}; - - auto x4B1Star = boostToRest(x4B1); - auto x4B2Star = boostToRest(x4B2); - auto x4B3Star = boostToRest(x4B3); - - const double tMax = std::max({x4B1Star.T(), x4B2Star.T(), x4B3Star.T()}); - - ROOT::Math::XYZVector rB1{x4B1Star.X(), x4B1Star.Y(), x4B1Star.Z()}; - ROOT::Math::XYZVector rB2{x4B2Star.X(), x4B2Star.Y(), x4B2Star.Z()}; - ROOT::Math::XYZVector rB3{x4B3Star.X(), x4B3Star.Y(), x4B3Star.Z()}; - - ROOT::Math::XYZVector vB1 = p4B1Star.Vect() / p4B1Star.E(); - ROOT::Math::XYZVector vB2 = p4B2Star.Vect() / p4B2Star.E(); - ROOT::Math::XYZVector vB3 = p4B3Star.Vect() / p4B3Star.E(); - - rB1 += vB1 * (tMax - x4B1Star.T()); - rB2 += vB2 * (tMax - x4B2Star.T()); - rB3 += vB3 * (tMax - x4B3Star.T()); - */ - const ROOT::Math::XYZVector pB1Star = p4B1Star.Vect(); const ROOT::Math::XYZVector pB2Star = p4B2Star.Vect(); const ROOT::Math::XYZVector pB3Star = p4B3Star.Vect(); - const double m12 = b1.mass + b2.mass; - const double mTot = b1.mass + b2.mass + b3.mass; + // Reduced masses entering the Jacobi coordinates + const double m12 = m1 + m2; + const double mTot = m1 + m2 + m3; - ROOT::Math::XYZVector pRho = (b2.mass * pB1Star - b1.mass * pB2Star) / m12; - ROOT::Math::XYZVector pLambda = (b3.mass * (pB1Star + pB2Star) - m12 * pB3Star) / mTot; + // Jacobi momenta in the candidate rest frame + ROOT::Math::XYZVector pRho = (m2 * pB1Star - m1 * pB2Star) / m12; + ROOT::Math::XYZVector pLambda = (m3 * (pB1Star + pB2Star) - m12 * pB3Star) / mTot; - if (pRho.R() > pRhoMax) { - return false; - } - - if (pLambda.R() > pLambdaMax) { + // Reject candidates outside the momentum-space acceptance + if (pRho.R() > pRhoMax || pLambda.R() > pLambdaMax) { return false; } return true; } - void buildPairs(std::vector const& b1Candidates, - std::vector const& b2Candidates) - { - if (b1Candidates.empty() || b2Candidates.empty()) { - return; - } - - for (const auto& b1 : b1Candidates) { - for (const auto& b2 : b2Candidates) { - if (!passTwoBodySkim(b1, b2)) { - continue; - } + // Group MC particles by their associated MC collision + Preslice mcParticlesPerMcCollision = o2::aod::mcparticle::mcCollisionId; - storePair(b1, b2); - } - } - } - - void buildTriplets(std::vector const& b1Candidates, - std::vector const& b2Candidates, - std::vector const& b3Candidates, - bool identicalB1B2 = false, - bool identicalB2B3 = false) + // Process Hypertriton + void processHypertriton(aod::McCollisions const& collisions, aod::McParticles const& mcParticles) { - if (b1Candidates.empty() || b2Candidates.empty() || b3Candidates.empty()) { - return; - } - - if (identicalB1B2) { - for (size_t iB1 = 0; iB1 < b1Candidates.size(); ++iB1) { - for (size_t iB2 = iB1 + 1; iB2 < b2Candidates.size(); ++iB2) { - for (const auto& b3 : b3Candidates) { - const auto& b1 = b1Candidates[iB1]; - const auto& b2 = b2Candidates[iB2]; - - if (!passThreeBodySkim(b1, b2, b3)) { - continue; - } - - storeTriplet(b1, b2, b3); - } - } - } - return; - } + // Loop over MC collisions + for (const auto& collision : collisions) { - if (identicalB2B3) { - for (const auto& b1 : b1Candidates) { - for (size_t iB2 = 0; iB2 < b2Candidates.size(); ++iB2) { - for (size_t iB3 = iB2 + 1; iB3 < b3Candidates.size(); ++iB3) { - const auto& b2 = b2Candidates[iB2]; - const auto& b3 = b3Candidates[iB3]; - - if (!passThreeBodySkim(b1, b2, b3)) { - continue; - } + // Event counter before selections + registry.fill(HIST("eventCounter"), 0.5); - storeTriplet(b1, b2, b3); - } - } - } - return; - } + // Apply z-vertex selection + if (std::fabs(collision.posZ()) > zVtxMax) + continue; - for (const auto& b1 : b1Candidates) { - for (const auto& b2 : b2Candidates) { - for (const auto& b3 : b3Candidates) { - if (!passThreeBodySkim(b1, b2, b3)) { - continue; - } + // Event counter after z-vertex cut + registry.fill(HIST("eventCounter"), 1.5); - storeTriplet(b1, b2, b3); - } - } - } - } + // To be implemented: maybe add INEL>0 selection - template - void selectGeneratedParticles(McParticles const& mcParticlesThisMcColl, - std::vector& protons, - std::vector& antiProtons, - std::vector& neutrons, - std::vector& antiNeutrons, - std::vector& lambdas, - std::vector& antiLambdas) - { - for (const auto& particle : mcParticlesThisMcColl) { - if (!particle.isPhysicalPrimary()) { - continue; - } + // Get particles in this MC collision + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); - if (std::fabs(particle.eta()) > etaMax) { - continue; - } + // Event ID + eventID = collision.globalIndex(); - const int pdg = particle.pdgCode(); - - if (pdg == PDG_t::kProton) { - protons.emplace_back(particle); - } else if (pdg == PDG_t::kProtonBar) { - antiProtons.emplace_back(particle); - } else if (pdg == PDG_t::kNeutron) { - neutrons.emplace_back(particle); - } else if (pdg == PDG_t::kNeutronBar) { - antiNeutrons.emplace_back(particle); - } else if (pdg == PDG_t::kLambda0) { - lambdas.emplace_back(particle); - } else if (pdg == PDG_t::kLambda0Bar) { - antiLambdas.emplace_back(particle); - } - } - } + // Containers for candidate constituents + std::vector protons; + std::vector neutrons; + std::vector lambdas; - void fillDeuteron(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) - { - // Deuteron: p + n - buildPairs(protons, neutrons); + // Loop over MC particles + for (const auto& particle : mcParticlesThisMcColl) { - // anti-deuteron: anti-p + anti-n - buildPairs(antiProtons, antiNeutrons); - } + // Select physical primary particles only + if (!particle.isPhysicalPrimary()) + continue; - void fillHelium3(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) - { - // 3He: p + p + n - buildTriplets(protons, protons, neutrons, true, false); + // Select particles with |eta|< eta_max + if (std::fabs(particle.eta()) > etaMax) + continue; - // anti-3He: anti-p + anti-p + anti-n - buildTriplets(antiProtons, antiProtons, antiNeutrons, true, false); - } + // Store protons + if (std::abs(particle.pdgCode()) == PDG_t::kProton) { + protons.push_back({particle.globalIndex(), particle.pdgCode(), particle.vx(), particle.vy(), particle.vz(), particle.vt(), particle.px(), particle.py(), particle.pz()}); + } - void fillTriton(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) - { - // Triton: p + n + n - buildTriplets(protons, neutrons, neutrons, false, true); + // Store neutrons + if (std::abs(particle.pdgCode()) == PDG_t::kNeutron) { + neutrons.push_back({particle.globalIndex(), particle.pdgCode(), particle.vx(), particle.vy(), particle.vz(), particle.vt(), particle.px(), particle.py(), particle.pz()}); + } - // anti-triton: anti-p + anti-n + anti-n - buildTriplets(antiProtons, antiNeutrons, antiNeutrons, false, true); - } + // Store lambdas + if (std::abs(particle.pdgCode()) == PDG_t::kLambda0) { + lambdas.push_back({particle.globalIndex(), particle.pdgCode(), particle.vx(), particle.vy(), particle.vz(), particle.vt(), particle.px(), particle.py(), particle.pz()}); + } + } // end of loop over MC particles - void fillHypertriton(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons, - std::vector const& lambdas, - std::vector const& antiLambdas) - { - // Hypertriton: p + n + Lambda - buildTriplets(protons, neutrons, lambdas); + // Reject events that do not contain at least one proton, one neutron, and one lambda + if (protons.empty() || neutrons.empty() || lambdas.empty()) + continue; - // anti-hypertriton: anti-p + anti-n + anti-Lambda - buildTriplets(antiProtons, antiNeutrons, antiLambdas); - } + // Event counter: events containing all three constituent species + registry.fill(HIST("eventCounter"), 2.5); - bool hasDeuteronCandidates(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) const - { - return (!protons.empty() && !neutrons.empty()) || - (!antiProtons.empty() && !antiNeutrons.empty()); - } + // Count matter and antimatter candidates in the event + Long64_t nCandidatesMatter(0); + Long64_t nCandidatesAntiMatter(0); + for (const auto& proton : protons) { + for (const auto& neutron : neutrons) { + for (const auto& lambda : lambdas) { - bool hasHelium3Candidates(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) const - { - constexpr std::size_t minimumSizeContainer = 2; - return (protons.size() >= minimumSizeContainer && !neutrons.empty()) || - (antiProtons.size() >= minimumSizeContainer && !antiNeutrons.empty()); - } + const bool isMatter = proton.pdgPart > 0 && neutron.pdgPart > 0 && lambda.pdgPart > 0; + const bool isAntimatter = proton.pdgPart < 0 && neutron.pdgPart < 0 && lambda.pdgPart < 0; - bool hasTritonCandidates(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons) const - { - constexpr std::size_t minimumSizeContainer = 2; - return (!protons.empty() && neutrons.size() >= minimumSizeContainer) || - (!antiProtons.empty() && antiNeutrons.size() >= minimumSizeContainer); - } + // Skip mixed-sign combinations + if (!isMatter && !isAntimatter) + continue; + const bool passSkim = passThreeBodySkim(proton, neutron, lambda); - bool hasHypertritonCandidates(std::vector const& protons, - std::vector const& antiProtons, - std::vector const& neutrons, - std::vector const& antiNeutrons, - std::vector const& lambdas, - std::vector const& antiLambdas) const - { - return (!protons.empty() && !neutrons.empty() && !lambdas.empty()) || - (!antiProtons.empty() && !antiNeutrons.empty() && !antiLambdas.empty()); - } + if (isMatter && passSkim) + nCandidatesMatter++; + if (isAntimatter && passSkim) + nCandidatesAntiMatter++; + } + } + } - void processCoalescence(aod::McCollision const& collision, aod::McParticles const& mcParticles) - { - registry.fill(HIST("eventCounter"), 0.5); + // Reject events with no accepted candidates + if (nCandidatesMatter == 0 && nCandidatesAntiMatter == 0) + continue; - if (std::fabs(collision.posZ()) > zVtx) { - return; - } + // Event counter: number of events with at least one candidate + registry.fill(HIST("eventCounter"), 3.5); - registry.fill(HIST("eventCounter"), 1.5); + // Store number of candidates per event + nMatterCandidatesPerEvent = nCandidatesMatter; + nAntimatterCandidatesPerEvent = nCandidatesAntiMatter; - eventID = collision.globalIndex(); + // Loop over accepted triplets and fill the tree + for (const auto& proton : protons) { + for (const auto& neutron : neutrons) { + for (const auto& lambda : lambdas) { - std::vector protons; - std::vector antiProtons; - std::vector neutrons; - std::vector antiNeutrons; - std::vector lambdas; - std::vector antiLambdas; + const bool isMatter = proton.pdgPart > 0 && neutron.pdgPart > 0 && lambda.pdgPart > 0; + const bool isAntimatter = proton.pdgPart < 0 && neutron.pdgPart < 0 && lambda.pdgPart < 0; - const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + // Skip mixed-sign combinations + if (!isMatter && !isAntimatter) + continue; - selectGeneratedParticles(mcParticlesThisMcColl, - protons, - antiProtons, - neutrons, - antiNeutrons, - lambdas, - antiLambdas); + // Apply momentum-space selection + const bool passSkim = passThreeBodySkim(proton, neutron, lambda); + if (!passSkim) + continue; - switch (boundStateSpecies) { - case kDeuteron: - if (!hasDeuteronCandidates(protons, antiProtons, neutrons, antiNeutrons)) { - return; - } - registry.fill(HIST("eventCounter"), 2.5); - fillDeuteron(protons, antiProtons, neutrons, antiNeutrons); - break; - case kHelium3: - if (!hasHelium3Candidates(protons, antiProtons, neutrons, antiNeutrons)) { - return; - } - registry.fill(HIST("eventCounter"), 2.5); - fillHelium3(protons, antiProtons, neutrons, antiNeutrons); - break; - case kTriton: - if (!hasTritonCandidates(protons, antiProtons, neutrons, antiNeutrons)) { - return; - } - registry.fill(HIST("eventCounter"), 2.5); - fillTriton(protons, antiProtons, neutrons, antiNeutrons); - break; - case kHypertriton: - if (!hasHypertritonCandidates(protons, antiProtons, neutrons, antiNeutrons, lambdas, antiLambdas)) { - return; + // Fill tree + idB1 = proton.idPart; + pdgB1 = proton.pdgPart; + xB1 = proton.xPart; + yB1 = proton.yPart; + zB1 = proton.zPart; + tB1 = proton.tPart; + pxB1 = proton.pxPart; + pyB1 = proton.pyPart; + pzB1 = proton.pzPart; + + idB2 = neutron.idPart; + pdgB2 = neutron.pdgPart; + xB2 = neutron.xPart; + yB2 = neutron.yPart; + zB2 = neutron.zPart; + tB2 = neutron.tPart; + pxB2 = neutron.pxPart; + pyB2 = neutron.pyPart; + pzB2 = neutron.pzPart; + + idB3 = lambda.idPart; + pdgB3 = lambda.pdgPart; + xB3 = lambda.xPart; + yB3 = lambda.yPart; + zB3 = lambda.zPart; + tB3 = lambda.tPart; + pxB3 = lambda.pxPart; + pyB3 = lambda.pyPart; + pzB3 = lambda.pzPart; + + treeBoundState->Fill(); + } } - registry.fill(HIST("eventCounter"), 2.5); - fillHypertriton(protons, antiProtons, neutrons, antiNeutrons, lambdas, antiLambdas); - break; - default: - LOGF(fatal, "Unknown boundStateSpecies=%d. Use 0 = deuteron, 1 = triton, 2 = helium3, 3 = hypertriton", static_cast(boundStateSpecies)); - } + } + } // end of loop over mc collisions } - PROCESS_SWITCH(CoalescenceTreeProducer, processCoalescence, "process coalescence", true); + PROCESS_SWITCH(CoalescenceTreeProducer, processHypertriton, "process hypertriton", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 27131fa185c39380d027deb24f31285f6bdf7018 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Thu, 4 Jun 2026 21:25:13 +0200 Subject: [PATCH 423/449] [PWGLF] MC matching for kinkBuilder + SP process function for L1405 (#16484) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFLambda1405Table.h | 16 + PWGLF/TableProducer/Common/kinkBuilder.cxx | 702 ++++++++++--- PWGLF/Tasks/Resonances/lambda1405analysis.cxx | 936 ++++++++++++++---- PWGLF/Utils/svPoolCreator.h | 35 +- 4 files changed, 1323 insertions(+), 366 deletions(-) diff --git a/PWGLF/DataModel/LFLambda1405Table.h b/PWGLF/DataModel/LFLambda1405Table.h index be61dc083bc..31721f634e3 100644 --- a/PWGLF/DataModel/LFLambda1405Table.h +++ b/PWGLF/DataModel/LFLambda1405Table.h @@ -29,6 +29,7 @@ namespace lambda1405 DECLARE_SOA_COLUMN(Px, px, float); //! Px of the candidate DECLARE_SOA_COLUMN(Py, py, float); //! Py of the candidate DECLARE_SOA_COLUMN(Pz, pz, float); //! Pz of the candidate +DECLARE_SOA_COLUMN(Pt, pt, float); //! Pt of the candidate DECLARE_SOA_COLUMN(Mass, mass, float); //! Invariant mass of the candidate DECLARE_SOA_COLUMN(MassXi1530, massXi1530, float); //! Invariant mass of the Xi(1530) candidate DECLARE_SOA_COLUMN(SigmaMinusMass, sigmaMinusMass, float); //! Invariant mass of the Sigma- candidate @@ -47,6 +48,10 @@ DECLARE_SOA_COLUMN(DCAKinkDauToPV, dcaKinkDauToPV, float); //! DCA of the kink DECLARE_SOA_COLUMN(NSigmaTPCPiDau, nSigmaTPCPiDau, float); //! Number of sigmas for the lambda1405 pion daughter in TPC DECLARE_SOA_COLUMN(NSigmaTOFPiDau, nSigmaTOFPiDau, float); //! Number of sigmas for the lambda1405 pion daughter in TOF +// Flow columns +DECLARE_SOA_COLUMN(ScalarProd, scalarProd, float); //! Scalar product of the candidate +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Centrality of the candidate + // MC Columns DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! pT of the candidate in MC DECLARE_SOA_COLUMN(MassMC, massMC, float); //! Invariant mass of the candidate in MC @@ -67,6 +72,17 @@ DECLARE_SOA_TABLE(Lambda1405Cands, "AOD", "LAMBDA1405", lambda1405::DCAKinkDauToPV, lambda1405::NSigmaTPCPiDau, lambda1405::NSigmaTOFPiDau); +DECLARE_SOA_TABLE(Lambda1405Flow, "AOD", "LAMBDA1405FLOW", + o2::soa::Index<>, + lambda1405::Pt, + lambda1405::Mass, lambda1405::SigmaMinusMass, lambda1405::SigmaPlusMass, + lambda1405::AlphaAPSigma, lambda1405::QtAPSigma, + lambda1405::NSigmaTPCPiKink, lambda1405::NSigmaTOFPiKink, + lambda1405::NSigmaTPCPrKink, lambda1405::NSigmaTOFPrKink, + lambda1405::DCAKinkDauToPV, + lambda1405::NSigmaTPCPiDau, lambda1405::NSigmaTOFPiDau, + lambda1405::ScalarProd, lambda1405::Centrality); + DECLARE_SOA_TABLE(Lambda1405CandsMC, "AOD", "MCLAMBDA1405", o2::soa::Index<>, lambda1405::Px, lambda1405::Py, lambda1405::Pz, diff --git a/PWGLF/TableProducer/Common/kinkBuilder.cxx b/PWGLF/TableProducer/Common/kinkBuilder.cxx index cd2f4c89cf1..4ae1e77b7c0 100644 --- a/PWGLF/TableProducer/Common/kinkBuilder.cxx +++ b/PWGLF/TableProducer/Common/kinkBuilder.cxx @@ -16,7 +16,9 @@ #include "PWGLF/DataModel/LFKinkDecayTables.h" #include "PWGLF/Utils/svPoolCreator.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include #include @@ -40,6 +42,7 @@ #include #include +#include #include #include @@ -50,11 +53,22 @@ #include using namespace o2; +using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; using std::array; using VBracket = o2::math_utils::Bracket; using TracksFull = soa::Join; +using TracksFullMc = soa::Join; +using CollisionsCent = soa::Join; +using McRecoCollisions = soa::Join; +using McRecoCollisionsCent = soa::Join; + +enum KinkDecayType { SigmaMinusToPiMinusNeutron = 0, + SigmaPlusToPiPlusNeutron, + SigmaPlusToProtonPi0, + NMatchedDecays }; namespace { @@ -62,12 +76,29 @@ constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; static const std::vector particleNames{"Daughter"}; +constexpr int DepthMcMatchMax = 1; // Max depth for MC matching std::shared_ptr h2ClsMapPtMoth; std::shared_ptr h2ClsMapPtDaug; std::shared_ptr h2DeDxDaugSel; std::shared_ptr h2KinkAnglePt; std::shared_ptr h2MothMassPt; +std::shared_ptr hSelMotherQA; +std::shared_ptr hSelDaugQA; +std::shared_ptr hSelKinkedTrackQA; +std::shared_ptr hMothDaughSignsInit; +std::shared_ptr hMothDaughSignsFinal; +std::shared_ptr h2ItsClsMothBeforeSel; +std::shared_ptr h2ItsClsDaugBeforeSel; +std::shared_ptr hZDiff; +std::shared_ptr hPhiDiff; +std::shared_ptr hDCAMothToPV; +std::shared_ptr hDCADaugToPV; +std::shared_ptr hMothDecRad2; +std::shared_ptr hGenCandidates; +std::shared_ptr hRecCandidates; +std::array, NMatchedDecays> hGenPtKinkAngle; +std::array, NMatchedDecays> hRecPtKinkAngle; } // namespace struct kinkCandidate { @@ -126,6 +157,11 @@ struct kinkBuilder { o2::vertexing::DCAFitterN<2> fitter; o2::base::MatLayerCylSet* lut = nullptr; + int nItsInnerBarrelLayers = 3; + int nItsOuterBarrelLayers = 4; + int nItsTotalLayers = 7; + int nCoords = 7; + int itsChi2NClMax = 36; // constants float radToDeg = o2::constants::math::Rad2Deg; @@ -137,18 +173,32 @@ struct kinkBuilder { Configurable customVertexerTimeMargin{"customVertexerTimeMargin", 800, "Time margin for custom vertexer (ns)"}; Configurable skipAmbiTracks{"skipAmbiTracks", false, "Skip ambiguous tracks"}; Configurable unlikeSignBkg{"unlikeSignBkg", false, "Use unlike sign background"}; + Configurable skipBkgCands{"skipBkgCands", true, "Skip bkg candidates in MC process"}; + + // Centrality selection + Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; + Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; // CCDB options Configurable ccdbPath{"ccdbPath", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; - // PDG codes - // histogram axes ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for rigidity #it{p}^{TPC}/#it{z}"}; ConfigurableAxis dedxBins{"dedxBins", {1000, 0.f, 1000.f}, "Binning for dE/dx"}; ConfigurableAxis nSigmaBins{"nSigmaBins", {200, -5.f, 5.f}, "Binning for n sigma"}; + ConfigurableAxis zDiffBins{"zDiffBins", {300, 0.f, 30.f}, "Binning for z difference"}; + ConfigurableAxis phiDiffBins{"phiDiffBins", {360, 0.f, 360.f}, "Binning for phi difference"}; + ConfigurableAxis dcaMothToPVBins{"dcaMothToPVBins", {120, 0.f, 60.f}, "Binning for DCA of mother to PV"}; + ConfigurableAxis dcaDaugToPVBins{"dcaDaugToPVBins", {200, 0.f, 20.f}, "Binning for DCA of daughter to PV"}; + ConfigurableAxis mothDecRad2Bins{"mothDecRad2Bins", {100, 0, 100}, "Binning for mother decay radius squared"}; + + // Filter collisions with centrality information (for the process with centrality selection) + using CollisionsCentSel = soa::Filtered; + using McRecoCollisionsCentSel = soa::Filtered; + + Filter filterCentrality = aod::cent::centFT0C >= centralityMin && aod::cent::centFT0C <= centralityMax; // std vector of candidates std::vector kinkCandidates; @@ -161,6 +211,7 @@ struct kinkBuilder { // mother and daughter tracks' properties (absolute charge and mass) int charge = 1; + std::vector mothMatchPdgCodes{}; float mothMass = o2::constants::physics::MassSigmaMinus; float chargedDauMass = o2::constants::physics::MassPiMinus; float neutDauMass = o2::constants::physics::MassNeutron; @@ -169,6 +220,7 @@ struct kinkBuilder { { if (hypoMoth == kSigmaMinus) { charge = 1; + mothMatchPdgCodes = {PDG_t::kSigmaMinus, PDG_t::kSigmaPlus}; mothMass = o2::constants::physics::MassSigmaMinus; chargedDauMass = o2::constants::physics::MassPiMinus; neutDauMass = o2::constants::physics::MassNeutron; @@ -209,6 +261,7 @@ struct kinkBuilder { const AxisSpec itsClusterMapAxis(128, 0, 127, "ITS cluster map"); const AxisSpec rigidityAxis{rigidityBins, "#it{p}^{TPC}/#it{z}"}; const AxisSpec ptAxis{rigidityBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec absPtAxis{1000, 0, 10, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec kinkAngleAxis{100, 0, 180, "#theta_{kink} (deg)"}; const AxisSpec dedxAxis{dedxBins, "d#it{E}/d#it{x}"}; @@ -221,213 +274,358 @@ struct kinkBuilder { massAxis = AxisSpec{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; } - h2DeDxDaugSel = qaRegistry.add("h2DeDxDaugSel", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dedxAxis}); - h2KinkAnglePt = qaRegistry.add("h2KinkAnglePt", "; p_{T} (GeV/#it{c}); #theta_{kink} (deg)", HistType::kTH2F, {ptAxis, kinkAngleAxis}); - h2MothMassPt = qaRegistry.add("h2MothMassPt", "; p_{T} (GeV/#it{c}); m (GeV/#it{c}^{2})", HistType::kTH2F, {ptAxis, massAxis}); - h2ClsMapPtMoth = qaRegistry.add("h2ClsMapPtMoth", "; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); - h2ClsMapPtDaug = qaRegistry.add("h2ClsMapPtDaug", "; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); + h2DeDxDaugSel = qaRegistry.add("h2DeDxDaugSel", "h2DeDxDaugSel; p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dedxAxis}); + h2KinkAnglePt = qaRegistry.add("h2KinkAnglePt", "h2KinkAnglePt; p_{T} (GeV/#it{c}); #theta_{kink} (deg)", HistType::kTH2F, {ptAxis, kinkAngleAxis}); + h2MothMassPt = qaRegistry.add("h2MothMassPt", "h2MothMassPt; p_{T} (GeV/#it{c}); m (GeV/#it{c}^{2})", HistType::kTH2F, {ptAxis, massAxis}); + h2ClsMapPtMoth = qaRegistry.add("h2ClsMapPtMoth", "h2ClsMapPtMoth; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); + h2ClsMapPtDaug = qaRegistry.add("h2ClsMapPtDaug", "h2ClsMapPtDaug; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); + h2ItsClsMothBeforeSel = qaRegistry.add("h2ItsClsMothBeforeSel", "h2ItsClsMothBeforeSel; Tot Cls; IB clusters", HistType::kTH2F, {{8, -0.5, 7.5}, {4, -0.5, 3.5}}); + h2ItsClsDaugBeforeSel = qaRegistry.add("h2ItsClsDaugBeforeSel", "h2ItsClsDaugBeforeSel; Tot Cls; IB clusters", HistType::kTH2F, {{8, -0.5, 7.5}, {4, -0.5, 3.5}}); + + // QA + hSelMotherQA = qaRegistry.add("hSelMotherQA", "hSelMotherQA;;Q_{Mother}", {HistType::kTH2F, {{9, -0.5, 8.5}, {2, -0.5, 1.5}}}); + hSelMotherQA->GetYaxis()->SetBinLabel(1, "-"); + hSelMotherQA->GetYaxis()->SetBinLabel(2, "+"); + hSelMotherQA->GetXaxis()->SetBinLabel(1, "All"); + hSelMotherQA->GetXaxis()->SetBinLabel(2, "Has Collision"); + hSelMotherQA->GetXaxis()->SetBinLabel(3, "Has ITS"); + hSelMotherQA->GetXaxis()->SetBinLabel(4, "Has NO TPC"); + hSelMotherQA->GetXaxis()->SetBinLabel(5, "Has NO TOF"); + hSelMotherQA->GetXaxis()->SetBinLabel(6, "ITS cls sel"); + hSelMotherQA->GetXaxis()->SetBinLabel(7, "ITS IB cls sel"); + hSelMotherQA->GetXaxis()->SetBinLabel(8, "ITS chi2 N cls sel"); + hSelMotherQA->GetXaxis()->SetBinLabel(9, "Pt sel"); + + // QA + hSelDaugQA = qaRegistry.add("hSelDaugQA", "hSelDaugQA;;Q_{Daug}", {HistType::kTH2F, {{8, -0.5, 7.5}, {2, -0.5, 1.5}}}); + hSelDaugQA->GetYaxis()->SetBinLabel(1, "-"); + hSelDaugQA->GetYaxis()->SetBinLabel(2, "+"); + hSelDaugQA->GetXaxis()->SetBinLabel(1, "All"); + hSelDaugQA->GetXaxis()->SetBinLabel(2, "Has ITS"); + hSelDaugQA->GetXaxis()->SetBinLabel(3, "Has TPC"); + hSelDaugQA->GetXaxis()->SetBinLabel(4, "Has TOF"); + hSelDaugQA->GetXaxis()->SetBinLabel(5, "ITS tot cls sel"); + hSelDaugQA->GetXaxis()->SetBinLabel(6, "ITS IB cls sel"); + hSelDaugQA->GetXaxis()->SetBinLabel(7, "TPC Crossed rows vs findable sel"); + hSelDaugQA->GetXaxis()->SetBinLabel(8, "TPC cls sel"); + + hSelKinkedTrackQA = qaRegistry.add("hSelKinkedTrackQA", "hSelKinkedTrackQA;;(Q_{Mother}, Q_{Daughter})", {HistType::kTH2F, {{11, -0.5, 10.5}, {4, -0.5, 3.5}}}); + hSelKinkedTrackQA->GetYaxis()->SetBinLabel(1, "(+,+)"); + hSelKinkedTrackQA->GetYaxis()->SetBinLabel(2, "(-,-)"); + hSelKinkedTrackQA->GetYaxis()->SetBinLabel(3, "(+,-)"); + hSelKinkedTrackQA->GetYaxis()->SetBinLabel(4, "(-,+)"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(1, "All"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(2, "MaxDCAMothToPV"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(3, "MaxZDiff"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(4, "MaxPhiDiff"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(5, "MinDCADaugToPV"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(6, "UpdateMothTrackUsePV"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(7, "DCAFitter"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(8, "PropagateTracksToVertex"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(9, "MothDecRad2InsideL4"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(10, "MothDaugLastLayers"); + hSelKinkedTrackQA->GetXaxis()->SetBinLabel(11, "MothLastLayerRadiusCheck"); + hMothDaughSignsInit = qaRegistry.add("hMothDaughSignsInit", "hMothDaughSignsInit; Sign Mother; Sign Daughter", {HistType::kTH2F, {{3, -1.5, 1.5}, {3, -1.5, 1.5}}}); + hMothDaughSignsFinal = qaRegistry.add("hMothDaughSignsFinal", "hMothDaughSignsFinal; Sign Mother; Sign Daughter", {HistType::kTH2F, {{3, -1.5, 1.5}, {3, -1.5, 1.5}}}); + hZDiff = qaRegistry.add("hZDiff", "hZDiff; #Delta z (#mu m);(Q_{Mother}, Q_{Daughter})", HistType::kTH2F, {zDiffBins, {4, -0.5, 3.5}}); + hZDiff->GetYaxis()->SetBinLabel(1, "(+,+)"); + hZDiff->GetYaxis()->SetBinLabel(2, "(-,-)"); + hZDiff->GetYaxis()->SetBinLabel(3, "(+,-)"); + hZDiff->GetYaxis()->SetBinLabel(4, "(-,+)"); + hPhiDiff = qaRegistry.add("hPhiDiff", "hPhiDiff; #Delta #phi (rad);(Q_{Mother}, Q_{Daughter})", HistType::kTH2F, {phiDiffBins, {4, -0.5, 3.5}}); + hPhiDiff->GetYaxis()->SetBinLabel(1, "(+,+)"); + hPhiDiff->GetYaxis()->SetBinLabel(2, "(-,-)"); + hPhiDiff->GetYaxis()->SetBinLabel(3, "(+,-)"); + hPhiDiff->GetYaxis()->SetBinLabel(4, "(-,+)"); + hDCAMothToPV = qaRegistry.add("hDCAMothToPV", "hDCAMothToPV; DCA moth to PV;(Q_{Mother}, Q_{Daughter})", HistType::kTH2F, {dcaMothToPVBins, {4, -0.5, 3.5}}); + hDCAMothToPV->GetYaxis()->SetBinLabel(1, "(+,+)"); + hDCAMothToPV->GetYaxis()->SetBinLabel(2, "(-,-)"); + hDCAMothToPV->GetYaxis()->SetBinLabel(3, "(+,-)"); + hDCAMothToPV->GetYaxis()->SetBinLabel(4, "(-,+)"); + hDCADaugToPV = qaRegistry.add("hDCADaugToPV", "hDCADaugToPV; DCA daug to PV;(Q_{Mother}, Q_{Daughter})", HistType::kTH2F, {dcaDaugToPVBins, {4, -0.5, 3.5}}); + hDCADaugToPV->GetYaxis()->SetBinLabel(1, "(+,+)"); + hDCADaugToPV->GetYaxis()->SetBinLabel(2, "(-,-)"); + hDCADaugToPV->GetYaxis()->SetBinLabel(3, "(+,-)"); + hDCADaugToPV->GetYaxis()->SetBinLabel(4, "(-,+)"); + hMothDecRad2 = qaRegistry.add("hMothDecRad2", "hMothDecRad2; Mother Dec. Radius Squared (cm^{2});(Q_{Mother}, Q_{Daughter})", HistType::kTH2F, {mothDecRad2Bins, {4, -0.5, 3.5}}); + hMothDecRad2->GetYaxis()->SetBinLabel(1, "(+,+)"); + hMothDecRad2->GetYaxis()->SetBinLabel(2, "(-,-)"); + hMothDecRad2->GetYaxis()->SetBinLabel(3, "(+,-)"); + hMothDecRad2->GetYaxis()->SetBinLabel(4, "(-,+)"); + + mBBparamsDaug[0] = cfgBetheBlochParams->get("Daughter", Form("p%i", 0)); + mBBparamsDaug[1] = cfgBetheBlochParams->get("Daughter", Form("p%i", 1)); + mBBparamsDaug[2] = cfgBetheBlochParams->get("Daughter", Form("p%i", 2)); + mBBparamsDaug[3] = cfgBetheBlochParams->get("Daughter", Form("p%i", 3)); + mBBparamsDaug[4] = cfgBetheBlochParams->get("Daughter", Form("p%i", 4)); + mBBparamsDaug[5] = cfgBetheBlochParams->get("Daughter", "resolution"); - for (int i = 0; i < 5; i++) { - mBBparamsDaug[i] = cfgBetheBlochParams->get("Daughter", Form("p%i", i)); + if (doprocessMc || doprocessMcWCent) { + if (skipBkgCands) { + hRecCandidates = qaRegistry.add("hRecCandidates", "hRecCandidates;Counts;", {HistType::kTH2F, {{NMatchedDecays, -0.5, static_cast(NMatchedDecays) - 0.5}, absPtAxis}}); + hRecCandidates->GetXaxis()->SetBinLabel(1, "#Sigma^{-} #rightarrow n#pi^{-}"); + hRecCandidates->GetXaxis()->SetBinLabel(2, "#Sigma^{+} #rightarrow n#pi^{+}"); + hRecCandidates->GetXaxis()->SetBinLabel(3, "#Sigma^{+} #rightarrow p#pi^{0}"); + } + hGenCandidates = qaRegistry.add("hGenCandidates", "hGenCandidates;Counts;", {HistType::kTH2F, {{NMatchedDecays, -0.5, static_cast(NMatchedDecays) - 0.5}, absPtAxis}}); + hGenCandidates->GetXaxis()->SetBinLabel(1, "#Sigma^{-} #rightarrow n#pi^{-}"); + hGenCandidates->GetXaxis()->SetBinLabel(2, "#Sigma^{+} #rightarrow n#pi^{+}"); + hGenCandidates->GetXaxis()->SetBinLabel(3, "#Sigma^{+} #rightarrow p#pi^{0}"); + hRecPtKinkAngle[SigmaMinusToPiMinusNeutron] = qaRegistry.add("hRecPtKinkAngleSigmaMinusToPiMinusNeutron", "Rec Pt vs KinkAngle #Sigma^{-} #rightarrow #pi^{-}n;Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); + hRecPtKinkAngle[SigmaPlusToPiPlusNeutron] = qaRegistry.add("hRecPtKinkAngleSigmaPlusToPiPlusNeutron", "Rec Pt vs KinkAngle #Sigma^{+} #rightarrow #pi^{+}n;Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); + hRecPtKinkAngle[SigmaPlusToProtonPi0] = qaRegistry.add("hRecPtKinkAngleSigmaPlusToProtonPi0", "Rec Pt vs KinkAngle #Sigma^{+} #rightarrow p#pi^{0};Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); + hGenPtKinkAngle[SigmaMinusToPiMinusNeutron] = qaRegistry.add("hGenPtKinkAngleSigmaMinusToPiMinusNeutron", "Gen Pt vs KinkAngle #Sigma^{-} #rightarrow #pi^{-}n;Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); + hGenPtKinkAngle[SigmaPlusToPiPlusNeutron] = qaRegistry.add("hGenPtKinkAngleSigmaPlusToPiPlusNeutron", "Gen Pt vs KinkAngle #Sigma^{+} #rightarrow #pi^{+}n;Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); + hGenPtKinkAngle[SigmaPlusToProtonPi0] = qaRegistry.add("hGenPtKinkAngleSigmaPlusToProtonPi0", "Gen Pt vs KinkAngle #Sigma^{+} #rightarrow p#pi^{0};Counts;", {HistType::kTH2F, {absPtAxis, kinkAngleAxis}}); } - mBBparamsDaug[5] = cfgBetheBlochParams->get("Daughter", "resolution"); } template bool selectMothTrack(const T& candidate) { - if (candidate.has_collision() && candidate.hasITS() && !candidate.hasTPC() && !candidate.hasTOF() && candidate.itsNCls() < 6 && - candidate.itsNClsInnerBarrel() == 3 && candidate.itsChi2NCl() < 36 && candidate.pt() > minPtMoth) { - return true; - } - return false; - } + bool isPositive = candidate.sign() > 0; + hSelMotherQA->Fill(0.f, isPositive); - template - bool selectDaugTrack(const T& candidate) - { - if (!candidate.hasTPC() || !candidate.hasITS()) { + if (!candidate.has_collision()) return false; - } + hSelMotherQA->Fill(1.f, isPositive); - if (askTOFforDaug && !candidate.hasTOF()) { + if (!candidate.hasITS()) return false; - } + hSelMotherQA->Fill(2.f, isPositive); - bool isGoodTPCCand = false; - if (candidate.itsNClsInnerBarrel() == 0 && candidate.itsNCls() < 4 && - candidate.tpcNClsCrossedRows() > 0.8 * candidate.tpcNClsFindable() && candidate.tpcNClsFound() > nTPCClusMinDaug) { - isGoodTPCCand = true; - } + if (candidate.hasTPC()) + return false; + hSelMotherQA->Fill(3.f, isPositive); - if (!isGoodTPCCand) { + if (candidate.hasTOF()) return false; - } + hSelMotherQA->Fill(4.f, isPositive); + + h2ItsClsMothBeforeSel->Fill(candidate.itsNCls(), candidate.itsNClsInnerBarrel()); + if (candidate.itsNCls() >= nItsTotalLayers - 1) + return false; + hSelMotherQA->Fill(5.f, isPositive); + + if (candidate.itsNClsInnerBarrel() != nItsInnerBarrelLayers) + return false; + hSelMotherQA->Fill(6.f, isPositive); + + if (candidate.itsChi2NCl() >= itsChi2NClMax) + return false; + hSelMotherQA->Fill(7.f, isPositive); + + if (candidate.pt() <= minPtMoth) + return false; + hSelMotherQA->Fill(8.f, isPositive); return true; } - template - void fillCandidateData(const Tcolls& collisions, const Ttracks& tracks, aod::AmbiguousTracks const& ambiguousTracks, aod::BCs const& bcs) + template + bool selectDaugTrack(const T& candidate) { - svCreator.clearPools(); - svCreator.fillBC2Coll(collisions, bcs); + bool isPositive = candidate.sign() > 0; + hSelDaugQA->Fill(0.f, isPositive); - for (const auto& track : tracks) { - if (std::abs(track.eta()) > etaMax) - continue; + if (!candidate.hasITS()) + return false; + hSelDaugQA->Fill(1.f, isPositive); - bool isDaug = selectDaugTrack(track); - bool isMoth = selectMothTrack(track); + if (!candidate.hasTPC()) + return false; + hSelDaugQA->Fill(2.f, isPositive); - if (!isDaug && !isMoth) - continue; + if (askTOFforDaug && !candidate.hasTOF()) + return false; + hSelDaugQA->Fill(3.f, isPositive); - int pdgHypo = isMoth ? 1 : 0; - svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); - } - auto& kinkPool = svCreator.getSVCandPool(collisions, !unlikeSignBkg); + h2ItsClsDaugBeforeSel->Fill(candidate.itsNCls(), candidate.itsNClsInnerBarrel()); + if (candidate.itsNClsInnerBarrel() != 0) + return false; + hSelDaugQA->Fill(4.f, isPositive); - for (const auto& svCand : kinkPool) { - kinkCandidate kinkCand; + if (candidate.itsNCls() >= nItsOuterBarrelLayers) + return false; + hSelDaugQA->Fill(5.f, isPositive); - auto trackMoth = tracks.rawIteratorAt(svCand.tr0Idx); - auto trackDaug = tracks.rawIteratorAt(svCand.tr1Idx); + if (candidate.tpcNClsCrossedRows() <= 0.8 * candidate.tpcNClsFindable()) + return false; + hSelDaugQA->Fill(6.f, isPositive); - auto const& collision = trackMoth.template collision_as(); - auto const& bc = collision.template bc_as(); - initCCDB(bc); + if (candidate.tpcNClsFound() <= nTPCClusMinDaug) + return false; + hSelDaugQA->Fill(7.f, isPositive); - o2::dataformats::VertexBase primaryVertex; - primaryVertex.setPos({collision.posX(), collision.posY(), collision.posZ()}); - primaryVertex.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - kinkCand.primVtx = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; + return true; + } - o2::track::TrackParCov trackParCovMoth = getTrackParCov(trackMoth); - o2::track::TrackParCov trackParCovMothPV{trackParCovMoth}; - o2::base::Propagator::Instance()->PropagateToXBxByBz(trackParCovMoth, LayerRadii[trackMoth.itsNCls() - 1]); + template + void buildKinkCand(const TSVCand& svCand, const TTracks& tracks, bool& isAccepted, const TColls&) + { + isAccepted = false; + kinkCandidate kinkCand; - std::array dcaInfoMoth; - o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovMothPV, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); + auto trackMoth = tracks.rawIteratorAt(svCand.tr0Idx); + auto trackDaug = tracks.rawIteratorAt(svCand.tr1Idx); - if (std::abs(dcaInfoMoth[0]) > maxDCAMothToPV) { - continue; - } + // Fill Selections QA histo + int chargeCombSvCand = 2 * unlikeSignBkg + (trackMoth.sign() == -1 ? 1 : 0); + hSelKinkedTrackQA->Fill(0.f, chargeCombSvCand); // all candidates bin + hMothDaughSignsInit->Fill(trackMoth.sign(), trackDaug.sign()); - o2::track::TrackParCov trackParCovDaug = getTrackParCov(trackDaug); + auto const& collision = trackMoth.template collision_as(); + auto const& bc = collision.template bc_as(); + initCCDB(bc); - // check if the kink daughter is close to the mother - if (std::abs(trackParCovMoth.getZ() - trackParCovDaug.getZ()) > maxZDiff) { - continue; - } + o2::dataformats::VertexBase primaryVertex; + primaryVertex.setPos({collision.posX(), collision.posY(), collision.posZ()}); + primaryVertex.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + kinkCand.primVtx = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; - if ((std::abs(trackParCovMoth.getPhi() - trackParCovDaug.getPhi()) * radToDeg) > maxPhiDiff) { - continue; - } + o2::track::TrackParCov trackParCovMoth = getTrackParCov(trackMoth); + o2::track::TrackParCov trackParCovMothPV{trackParCovMoth}; + o2::base::Propagator::Instance()->PropagateToXBxByBz(trackParCovMoth, LayerRadii[trackMoth.itsNCls() - 1]); - // propagate to PV - std::array dcaInfoDaug; - o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovDaug, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoDaug); - if (std::abs(dcaInfoDaug[0]) < minDCADaugToPV) { - continue; - } + std::array dcaInfoMoth; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovMothPV, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); - if (updateMothTrackUsePV) { - // update the mother track parameters using the primary vertex - trackParCovMoth = trackParCovMothPV; - if (!trackParCovMoth.update(primaryVertex)) { - continue; - } - } + hDCAMothToPV->Fill(std::abs(dcaInfoMoth[0]), chargeCombSvCand); + if (std::abs(dcaInfoMoth[0]) > maxDCAMothToPV) { + return; + } + hSelKinkedTrackQA->Fill(1.f, chargeCombSvCand); // MaxDCAMothToPV cut bin - int nCand = 0; - try { - nCand = fitter.process(trackParCovMoth, trackParCovDaug); - } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; - continue; - } - if (nCand == 0) { - continue; - } + o2::track::TrackParCov trackParCovDaug = getTrackParCov(trackDaug); - if (!fitter.propagateTracksToVertex()) { - continue; - } + // check if the kink daughter is close to the mother + hZDiff->Fill(std::abs(trackParCovMoth.getZ() - trackParCovDaug.getZ()), chargeCombSvCand); + if (std::abs(trackParCovMoth.getZ() - trackParCovDaug.getZ()) > maxZDiff) { + return; + } + hSelKinkedTrackQA->Fill(2.f, chargeCombSvCand); // MaxZDiff cut bin - auto propMothTrack = fitter.getTrack(0); - auto propDaugTrack = fitter.getTrack(1); - kinkCand.decVtx = fitter.getPCACandidatePos(); + hPhiDiff->Fill(std::abs(trackParCovMoth.getPhi() - trackParCovDaug.getPhi()) * radToDeg, chargeCombSvCand); + if ((std::abs(trackParCovMoth.getPhi() - trackParCovDaug.getPhi()) * radToDeg) > maxPhiDiff) { + return; + } + hSelKinkedTrackQA->Fill(3.f, chargeCombSvCand); // MaxPhiDiff cut bin - // cut on decay radius to 17 cm - float decRad2 = kinkCand.decVtx[0] * kinkCand.decVtx[0] + kinkCand.decVtx[1] * kinkCand.decVtx[1]; - if (doSVRadiusCut && decRad2 < LayerRadii[3] * LayerRadii[3]) { - continue; - } + // propagate to PV + std::array dcaInfoDaug; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovDaug, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoDaug); + hDCADaugToPV->Fill(std::abs(dcaInfoDaug[0]), chargeCombSvCand); + if (std::abs(dcaInfoDaug[0]) < minDCADaugToPV) { + return; + } + hSelKinkedTrackQA->Fill(4.f, chargeCombSvCand); // MinDCADaugToPV cut bin - // get last layer hitted by the mother and the first layer hitted by the daughter - int lastLayerMoth = 0, firstLayerDaug = 0; - for (int i = 0; i < 7; i++) { - if (trackMoth.itsClusterMap() & (1 << i)) { - lastLayerMoth = i; - } + if (updateMothTrackUsePV) { + // update the mother track parameters using the primary vertex + trackParCovMoth = trackParCovMothPV; + if (!trackParCovMoth.update(primaryVertex)) { + return; } + } + hSelKinkedTrackQA->Fill(5.f, chargeCombSvCand); // UpdateMothTrackUsePV cut bin - for (int i = 0; i < 7; i++) { - if (trackDaug.itsClusterMap() & (1 << i)) { - firstLayerDaug = i; - break; - } - } + int nCand = 0; + try { + nCand = fitter.process(trackParCovMoth, trackParCovDaug); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return; + } + if (nCand == 0) { + return; + } + hSelKinkedTrackQA->Fill(6.f, chargeCombSvCand); // DCAFitter cut bin - if (doSVRadiusCut && lastLayerMoth >= firstLayerDaug) { - continue; - } + if (!fitter.propagateTracksToVertex()) { + return; + } + hSelKinkedTrackQA->Fill(7.f, chargeCombSvCand); // PropagateTracksToVertex cut bin - if (doSVRadiusCut && decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { - continue; - } + auto propMothTrack = fitter.getTrack(0); + auto propDaugTrack = fitter.getTrack(1); + kinkCand.decVtx = fitter.getPCACandidatePos(); - for (int i = 0; i < 3; i++) { - kinkCand.decVtx[i] -= kinkCand.primVtx[i]; - } + // cut on decay radius to 17 cm + float decRad2 = kinkCand.decVtx[0] * kinkCand.decVtx[0] + kinkCand.decVtx[1] * kinkCand.decVtx[1]; + hMothDecRad2->Fill(decRad2, chargeCombSvCand); + int idxFirstOuterBarrelLayer = nItsInnerBarrelLayers; + if (doSVRadiusCut && decRad2 < LayerRadii[idxFirstOuterBarrelLayer] * LayerRadii[idxFirstOuterBarrelLayer]) { + return; + } + hSelKinkedTrackQA->Fill(8.f, chargeCombSvCand); // MothDecRad2InsideL4 cut bin - propMothTrack.getPxPyPzGlo(kinkCand.momMoth); - propDaugTrack.getPxPyPzGlo(kinkCand.momDaug); - for (int i = 0; i < 3; i++) { - kinkCand.momMoth[i] *= charge; - kinkCand.momDaug[i] *= charge; + // get last layer hitted by the mother and the first layer hitted by the daughter + int lastLayerMoth = 0, firstLayerDaug = 0; + for (int i = 0; i < nItsTotalLayers; i++) { + if (trackMoth.itsClusterMap() & (1 << i)) { + lastLayerMoth = i; } - float pMoth = propMothTrack.getP() * charge; - float pDaug = propDaugTrack.getP() * charge; - float spKink = kinkCand.momMoth[0] * kinkCand.momDaug[0] + kinkCand.momMoth[1] * kinkCand.momDaug[1] + kinkCand.momMoth[2] * kinkCand.momDaug[2]; - kinkCand.kinkAngle = std::acos(spKink / (pMoth * pDaug)); - - std::array neutDauMom{0.f, 0.f, 0.f}; - for (int i = 0; i < 3; i++) { - neutDauMom[i] = kinkCand.momMoth[i] - kinkCand.momDaug[i]; + } + + for (int i = 0; i < nItsTotalLayers; i++) { + if (trackDaug.itsClusterMap() & (1 << i)) { + firstLayerDaug = i; + break; } + } + + if (doSVRadiusCut && lastLayerMoth >= firstLayerDaug) { + return; + } + hSelKinkedTrackQA->Fill(9.f, chargeCombSvCand); // MothDaugLastLayers cut bin - float chargedDauE = std::sqrt(pDaug * pDaug + chargedDauMass * chargedDauMass); - float neutE = std::sqrt(neutDauMom[0] * neutDauMom[0] + neutDauMom[1] * neutDauMom[1] + neutDauMom[2] * neutDauMom[2] + neutDauMass * neutDauMass); - float invMass = std::sqrt((chargedDauE + neutE) * (chargedDauE + neutE) - (pMoth * pMoth)); - - h2DeDxDaugSel->Fill(trackDaug.tpcInnerParam() * trackDaug.sign(), trackDaug.tpcSignal()); - h2KinkAnglePt->Fill(trackMoth.pt() * charge * trackMoth.sign(), kinkCand.kinkAngle * radToDeg); - h2MothMassPt->Fill(trackMoth.pt() * charge * trackMoth.sign(), invMass); - h2ClsMapPtMoth->Fill(trackMoth.pt() * charge * trackMoth.sign(), trackMoth.itsClusterMap()); - h2ClsMapPtDaug->Fill(trackDaug.pt() * charge * trackDaug.sign(), trackDaug.itsClusterMap()); - - kinkCand.collisionID = collision.globalIndex(); - kinkCand.mothTrackID = trackMoth.globalIndex(); - kinkCand.daugTrackID = trackDaug.globalIndex(); - - kinkCand.dcaXYmoth = dcaInfoMoth[0]; - kinkCand.mothSign = trackMoth.sign(); - kinkCand.dcaXYdaug = dcaInfoDaug[0]; - kinkCand.dcaKinkTopo = std::sqrt(fitter.getChi2AtPCACandidate()); - kinkCandidates.push_back(kinkCand); + if (doSVRadiusCut && decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { + return; + } + hSelKinkedTrackQA->Fill(10.f, chargeCombSvCand); // MothLastLayerRadiusCheck cut bin + + for (int i = 0; i < nCoords; i++) { + kinkCand.decVtx[i] -= kinkCand.primVtx[i]; + } + + propMothTrack.getPxPyPzGlo(kinkCand.momMoth); + propDaugTrack.getPxPyPzGlo(kinkCand.momDaug); + for (int i = 0; i < nCoords; i++) { + kinkCand.momMoth[i] *= charge; + kinkCand.momDaug[i] *= charge; + } + float pMoth = propMothTrack.getP() * charge; + float pDaug = propDaugTrack.getP() * charge; + float spKink = kinkCand.momMoth[0] * kinkCand.momDaug[0] + kinkCand.momMoth[1] * kinkCand.momDaug[1] + kinkCand.momMoth[2] * kinkCand.momDaug[2]; + kinkCand.kinkAngle = std::acos(spKink / (pMoth * pDaug)); + + std::array neutDauMom{0.f, 0.f, 0.f}; + for (int i = 0; i < nCoords; i++) { + neutDauMom[i] = kinkCand.momMoth[i] - kinkCand.momDaug[i]; } + + float chargedDauE = std::sqrt(pDaug * pDaug + chargedDauMass * chargedDauMass); + float neutE = std::sqrt(neutDauMom[0] * neutDauMom[0] + neutDauMom[1] * neutDauMom[1] + neutDauMom[2] * neutDauMom[2] + neutDauMass * neutDauMass); + float invMass = std::sqrt((chargedDauE + neutE) * (chargedDauE + neutE) - (pMoth * pMoth)); + + h2DeDxDaugSel->Fill(trackDaug.tpcInnerParam() * trackDaug.sign(), trackDaug.tpcSignal()); + h2KinkAnglePt->Fill(trackMoth.pt() * charge * trackMoth.sign(), kinkCand.kinkAngle * radToDeg); + h2MothMassPt->Fill(trackMoth.pt() * charge * trackMoth.sign(), invMass); + h2ClsMapPtMoth->Fill(trackMoth.pt() * charge * trackMoth.sign(), trackMoth.itsClusterMap()); + h2ClsMapPtDaug->Fill(trackDaug.pt() * charge * trackDaug.sign(), trackDaug.itsClusterMap()); + hMothDaughSignsFinal->Fill(trackMoth.sign(), trackDaug.sign()); + + kinkCand.collisionID = collision.globalIndex(); + kinkCand.mothTrackID = trackMoth.globalIndex(); + kinkCand.daugTrackID = trackDaug.globalIndex(); + + kinkCand.dcaXYmoth = dcaInfoMoth[0]; + kinkCand.mothSign = trackMoth.sign(); + kinkCand.dcaXYdaug = dcaInfoDaug[0]; + kinkCand.dcaKinkTopo = std::sqrt(fitter.getChi2AtPCACandidate()); + kinkCandidates.push_back(kinkCand); + isAccepted = true; + return; } void initCCDB(aod::BCs::iterator const& bc) @@ -451,11 +649,153 @@ struct kinkBuilder { LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; } - void process(aod::Collisions const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCs const& bcs) + template + void buildSvPool(const TColls& collisions, const TTracks& tracks, const TAmbiTracks& ambiguousTracks, const aod::BCs& bcs) + { + svCreator.clearPools(); + svCreator.fillBC2Coll(collisions, bcs); + + for (const auto& track : tracks) { + if (std::abs(track.eta()) > etaMax) { + continue; + } + + bool isDaug = selectDaugTrack(track); + bool isMoth = selectMothTrack(track); + if (!isDaug && !isMoth) { + continue; + } + int pdgHypo = isMoth ? 1 : 0; + svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); + } + } + + template + void fillOutputsData(const TColls& collisions, const TTracks& tracks, const aod::AmbiguousTracks& ambiTracks, const aod::BCs& bcs) + { + kinkCandidates.clear(); + + buildSvPool(collisions, tracks, ambiTracks, bcs); + auto& kinkPool = svCreator.getSVCandPool(collisions, !unlikeSignBkg); + bool isAccepted = false; + for (const auto& svCand : kinkPool) { + buildKinkCand(svCand, tracks, isAccepted, collisions); + } + + // sort kinkCandidates by collisionID to allow joining with collision table + std::sort(kinkCandidates.begin(), kinkCandidates.end(), [](const kinkCandidate& a, const kinkCandidate& b) { return a.collisionID < b.collisionID; }); + + for (const auto& kinkCand : kinkCandidates) { + if (fillDebugTable) { + outputDataTableUB(kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], + kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], + kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], + kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + } else { + outputDataTable(kinkCand.collisionID, kinkCand.mothTrackID, kinkCand.daugTrackID, + kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], + kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], + kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], + kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + } + } + } + + void processData(aod::Collisions const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCs const& bcs) + { + fillOutputsData(collisions, tracks, ambiTracks, bcs); + } + PROCESS_SWITCH(kinkBuilder, processData, "Data processing", true); + + void processDataWCentSel(CollisionsCentSel const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCs const& bcs) { + fillOutputsData(collisions, tracks, ambiTracks, bcs); + } + PROCESS_SWITCH(kinkBuilder, processDataWCentSel, "Data processing with centrality selection", false); + + template + int matchKinkDecay(const TMother& motherPart, const aod::McParticles& mcParticles) + { + int pdgMother = motherPart.pdgCode(); + int8_t sign = 0; + int pdgCodeNeutralDaug{-1}, pdgCodeChargedDaug{-1}; + std::array finState = {-1, -1}; + switch (std::abs(pdgMother)) { + case PDG_t::kSigmaMinus: { + // Swap the sign of the neutral decay products in case of anti-particles + pdgCodeNeutralDaug = (pdgMother > 0) ? +PDG_t::kNeutron : -PDG_t::kNeutron; + pdgCodeChargedDaug = (pdgMother > 0) ? +PDG_t::kPiMinus : +PDG_t::kPiPlus; + finState = {pdgCodeChargedDaug, pdgCodeNeutralDaug}; // Both decay channels have the same neutral daughter + if (RecoDecay::isMatchedMCGen(mcParticles, motherPart, pdgMother, finState, true, &sign, DepthMcMatchMax)) { + return SigmaMinusToPiMinusNeutron; + } + break; + } + case PDG_t::kSigmaPlus: { + // Swap the sign of the neutral decay products in case of anti-particles + pdgCodeNeutralDaug = (pdgMother > 0) ? +PDG_t::kNeutron : -PDG_t::kNeutron; + pdgCodeChargedDaug = (pdgMother > 0) ? +PDG_t::kPiPlus : +PDG_t::kPiMinus; + finState = {pdgCodeChargedDaug, pdgCodeNeutralDaug}; + if (RecoDecay::isMatchedMCGen(mcParticles, motherPart, pdgMother, finState, true, &sign, DepthMcMatchMax)) { + return SigmaPlusToPiPlusNeutron; + } + + // Swap the sign of the neutral decay products in case of anti-particles + pdgCodeNeutralDaug = (pdgMother > 0) ? +PDG_t::kPi0 : -PDG_t::kPi0; + pdgCodeChargedDaug = (pdgMother > 0) ? +PDG_t::kProton : -PDG_t::kProton; + finState = {pdgCodeChargedDaug, pdgCodeNeutralDaug}; + if (RecoDecay::isMatchedMCGen(mcParticles, motherPart, pdgMother, finState, true, &sign, DepthMcMatchMax)) { + return SigmaPlusToProtonPi0; + } + break; + } + default: + LOG(warning) << "No matching function implemented for the selected mother particle hypothesis. Returning -1."; + return -1; + } + + return -1; + } + template + void fillOutputsMc(const TColls& mcRecoCollisions, const TTracks& tracksMc, const aod::AmbiguousTracks& ambiTracksMc, const aod::BCs& bcs, const aod::McParticles& mcParticles) + { kinkCandidates.clear(); - fillCandidateData(collisions, tracks, ambiTracks, bcs); + + buildSvPool(mcRecoCollisions, tracksMc, ambiTracksMc, bcs); + auto& kinkPool = svCreator.getSVCandPool(mcRecoCollisions, !unlikeSignBkg); + for (const auto& svCand : kinkPool) { + // Perform matching of the kink candidate + auto trackMoth = tracksMc.rawIteratorAt(svCand.tr0Idx); + auto genMothPart = trackMoth.template mcParticle_as(); + auto trackDaug = tracksMc.rawIteratorAt(svCand.tr1Idx); + auto genDaugPart = trackDaug.template mcParticle_as(); + int decayChannel{-1}; + if (skipBkgCands) { + + // Check mother PDG first + if (std::find(mothMatchPdgCodes.begin(), mothMatchPdgCodes.end(), std::abs(genMothPart.pdgCode())) == mothMatchPdgCodes.end()) { + continue; + } + + // Check that the daughter was generated from the selected mother + int genDaugMothIdx = RecoDecay::getMother(mcParticles, genDaugPart, genMothPart.pdgCode(), true); + if (genDaugMothIdx != trackMoth.mcParticleId()) { + continue; // Skip candidates where the daughter is not coming from the selected mother + } + decayChannel = matchKinkDecay(genMothPart, mcParticles); + if (decayChannel < 0) { + continue; // Skip candidates that do not match the decay channels of interest + } + hRecCandidates->Fill(decayChannel, trackMoth.pt()); // Decay channel match bin + } + bool isAccepted = false; + buildKinkCand(svCand, tracksMc, isAccepted, mcRecoCollisions); + // If candidate passed all selections and was built, fill histogram + if (isAccepted && skipBkgCands) { + hRecPtKinkAngle[decayChannel]->Fill(trackMoth.pt(), std::abs(trackMoth.phi() - trackDaug.phi()) * radToDeg); + } + } // sort kinkCandidates by collisionID to allow joining with collision table std::sort(kinkCandidates.begin(), kinkCandidates.end(), [](const kinkCandidate& a, const kinkCandidate& b) { return a.collisionID < b.collisionID; }); @@ -474,7 +814,47 @@ struct kinkBuilder { kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); } } + + // Generated kinks + for (const auto& mcPart : mcParticles) { + if (std::find(mothMatchPdgCodes.begin(), mothMatchPdgCodes.end(), std::abs(mcPart.pdgCode())) == mothMatchPdgCodes.end()) { + continue; // Skip if mother particle does not match the PDG codes of interest + } + int decayChannel = matchKinkDecay(mcPart, mcParticles); // Dummy daughter PDG code since we are not checking it in this case + if (decayChannel < 0) { + continue; // Skip if no matching decay channel is found + } + hGenCandidates->Fill(decayChannel, mcPart.pt()); + std::vector arrDaughIdxs = {}; + RecoDecay::getDaughters(mcPart, &arrDaughIdxs, std::array{0}, DepthMcMatchMax); + for (auto iProng = 0u; iProng < arrDaughIdxs.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIdxs[iProng]); + if (std::abs(daughI.pdgCode()) == PDG_t::kPiPlus || std::abs(daughI.pdgCode()) == PDG_t::kProton) { + hGenPtKinkAngle[decayChannel]->Fill(mcPart.pt(), std::abs(mcPart.phi() - daughI.phi()) * radToDeg); + } + } + } + } + + void processMc(McRecoCollisions const& mcRecoCollisions, + aod::McParticles const& mcParticles, + TracksFullMc const& tracksMc, + aod::AmbiguousTracks const& ambiTracksMc, + aod::BCs const& bcs) + { + fillOutputsMc(mcRecoCollisions, tracksMc, ambiTracksMc, bcs, mcParticles); + } + PROCESS_SWITCH(kinkBuilder, processMc, "MC processing", false); + + void processMcWCent(McRecoCollisionsCentSel const& mcRecoCollisions, + aod::McParticles const& mcParticles, + TracksFullMc const& tracksMc, + aod::AmbiguousTracks const& ambiTracksMc, + aod::BCs const& bcs) + { + fillOutputsMc(mcRecoCollisions, tracksMc, ambiTracksMc, bcs, mcParticles); } + PROCESS_SWITCH(kinkBuilder, processMcWCent, "MC processing with centrality selection", false); }; WorkflowSpec diff --git a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx index 7c12c2b9042..fa84d56eab2 100644 --- a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx +++ b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx @@ -17,9 +17,11 @@ #include "PWGLF/DataModel/LFLambda1405Table.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/Qvectors.h" #include #include @@ -33,9 +35,13 @@ #include #include +#include + #include #include #include +#include +#include using namespace o2; using namespace o2::framework; @@ -43,19 +49,29 @@ using namespace o2::framework::expressions; using TracksFull = soa::Join; using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; +using CollisionsFullWCentQVecs = soa::Join; +using CollisionsFullMc = soa::Join; +using CollisionsFullMcWCent = soa::Join; + +enum L1405DecayType { kSigmaMinusPiToPiPiNeutron = 0, + kSigmaPlusPiToPiPiNeutron, + kSigmaPlusPiToPiPiProton, + kNL1405Decays }; struct lambda1405candidate { // Columns for Lambda(1405) candidate - float mass = -1; // Invariant mass of the Lambda(1405) candidate + float massL1405 = -1; // Invariant mass of the Lambda(1405) candidate float massXi1530 = -1; // Invariant mass of the Xi(1530) candidate float px = -1; // Px of the Lambda(1405) candidate float py = -1; // Py of the Lambda(1405) candidate float pz = -1; // Pz of the Lambda(1405) candidate - float pt() const { return std::sqrt(px * px + py * py); } // pT of the Lambda(1405 candidate + float pt() const { return std::sqrt(px * px + py * py); } // pT of the Lambda(1405) candidate + float phi = -1; // Phi of the Lambda(1405) candidate bool isSigmaPlus = false; // True if compatible with Sigma+ bool isSigmaMinus = false; // True if compatible with Sigma- + bool hasPiKink = false; // True if the Sigma candidate has a kink topology compatible with a pion + bool hasPrKink = false; // True if the Sigma candidate has a kink topology compatible with a proton float sigmaMinusMass = -1; // Invariant mass of the Sigma- candidate float sigmaPlusMass = -1; // Invariant mass of the Sigma+ candidate float xiMinusMass = -1; // Invariant mass of the Xi- candidate @@ -64,46 +80,94 @@ struct lambda1405candidate { float sigmaAlphaAP = -1; // Alpha of the Sigma float sigmaQtAP = -1; // qT of the Sigma float kinkPt = -1; // pT of the kink daughter - float kinkTPCNSigmaPi = -1; // Number of sigmas for the pion candidate from Sigma kink in TPC - float kinkTOFNSigmaPi = -1; // Number of sigmas for the pion candidate from Sigma kink in TOF - float kinkTPCNSigmaPr = -1; // Number of sigmas for the proton candidate from Sigma kink in TPC - float kinkTOFNSigmaPr = -1; // Number of sigmas for the proton candidate from Sigma kink in TOF - float dcaKinkDauToPV = -1; // DCA of the kink daughter to the primary vertex + float kinkPiNSigTpc = -1; // Number of sigmas for the pion candidate from Sigma kink in Tpc + float kinkPiNSigTof = -1; // Number of sigmas for the pion candidate from Sigma kink in Tof + float kinkPrNSigTpc = -1; // Number of sigmas for the proton candidate from Sigma kink in Tpc + float kinkPrNSigTof = -1; // Number of sigmas for the proton candidate from Sigma kink in Tof + float kinkDcaDauToPv = -1; // DCA of the kink daughter to the primary vertex float sigmaRadius = -1; // Radius of the Sigma decay vertex float piPt = -1; // pT of the pion daughter - float nSigmaTPCPi = -1; // Number of sigmas for the pion candidate - float nSigmaTOFPi = -1; // Number of sigmas for the pion candidate using TOF - int kinkDauID = 0; // ID of the pion from Sigma decay in MC - int sigmaID = 0; // ID of the Sigma candidate in MC - int piID = 0; // ID of the pion candidate in MC + float bachPiNSigTpc = -1; // Number of sigmas for the pion candidate + float bachPiNSigTof = -1; // Number of sigmas for the pion candidate using Tof + int kinkDauId = 0; // Id of the pion from Sigma decay in MC + int sigmaId = 0; // Id of the Sigma candidate in MC + int piId = 0; // Id of the pion candidate in MC + + float scalarProd = -1; // Scalar product for flow analysis }; struct lambda1405analysis { int lambda1405PdgCode = 102132; // PDG code for Lambda(1405) lambda1405candidate lambda1405Cand; // Lambda(1405) candidate structure Produces outputDataTable; // Output table for Lambda(1405) candidates + Produces outputDataFlowTable; // Output table for Lambda(1405) flow analysis Produces outputDataTableMC; // Output table for Lambda(1405) candidates in MC // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rLambda1405{"lambda1405", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSigmaMinus{"sigmaMinus", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSigmaPlus{"sigmaPlus", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSelections{"selections", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for event selection - Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable cutEtaDaught{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; - Configurable cutDCAtoPVSigma{"cutDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; - Configurable cutDCAtoPVPiFromSigma{"cutDCAtoPVPiFromSigma", 2., "Min DCA to primary vertex for pion from Sigma candidates (cm)"}; + Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutEtaDaughter{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; + Configurable cutDCAtoPvSigma{"cutDCAtoPvSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; + Configurable cutDCAtoPvPiFromSigma{"cutDCAtoPvPiFromSigma", 2., "Min DCA to primary vertex for pion from Sigma candidates (cm)"}; Configurable cutUpperMass{"cutUpperMass", 1.6f, "Upper mass cut for Lambda(1405) candidates (GeV/c^2)"}; Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; Configurable cutSigmaMass{"cutSigmaMass", 0.1, "Sigma mass window (MeV/c^2)"}; - Configurable cutNITSClusPi{"cutNITSClusPi", 5, "Minimum number of ITS clusters for pion candidate"}; - Configurable cutNTPCClusPi{"cutNTPCClusPi", 90, "Minimum number of TPC clusters for pion candidate"}; - Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "NSigmaTPCPion"}; - Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "NSigmaTOFPion"}; + Configurable cutNITSClusKink{"cutNITSClusKink", 3, "Minimum number of ITS clusters for pion candidate"}; + Configurable cutNTpcClusPi{"cutNTpcClusPi", 90, "Minimum number of Tpc clusters for pion candidate"}; + Configurable cutNSigTpc{"cutNSigTpc", 3, "NSigTpcPion"}; + Configurable cutNSigTof{"cutNSigTof", 3, "NSigTofPion"}; + Configurable cutSigmaQtAPMin{"cutSigmaQtAPMin", "0.17", "Functional form of minimum qT(alpha) selection"}; + Configurable cutSigmaQtAPMax{"cutSigmaQtAPMax", "0.2", "Functional form of minimum qT(alpha) selection"}; + Configurable cutMinBachPiPtVsL1405Pt{"cutMinBachPiPtVsL1405Pt", "0", "Functional form of minimum qT(alpha) selection"}; + Configurable cutMaxBachPiPtVsL1405Pt{"cutMaxBachPiPtVsL1405Pt", "10", "Functional form of minimum qT(alpha) selection"}; + Configurable cutMinSigmaPtVsL1405Pt{"cutMinSigmaPtVsL1405Pt", "0", "Functional form of minimum qT(alpha) selection"}; + Configurable cutMaxSigmaPtVsL1405Pt{"cutMaxSigmaPtVsL1405Pt", "10", "Functional form of minimum qT(alpha) selection"}; + + // Configurables for flow analysis + Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; + Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; + Configurable fillFlowTree{"fillFlowTree", false, "If true, fill the output tree with Lambda(1405) candidates"}; + + // Downsample for table filling + Configurable downSampleFactor{"downSampleFactor", 1., "Fraction of candidates to keep in TTree"}; + Configurable ptDownSampleMax{"ptDownSampleMax", 10., "Maximum pt for the application of the downsampling factor"}; Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Lambda(1405) candidates"}; - Configurable doLSBkg{"doLikeSignBkg", false, "Use like-sign background"}; - Configurable useTOF{"useTOF", false, "Use TOF for PID for pion candidates"}; + Configurable doLikeSignBkg{"doLikeSignBkg", false, "Use like-sign background"}; + Configurable useTof{"useTof", false, "Use Tof for PId for pion candidates"}; + + TF1 funcMinQtAlphaAP, funcMaxQtAlphaAP, funcMinBachPiPtVsL1405Pt, funcMaxBachPiPtVsL1405Pt, funcMinSigmaPtVsL1405Pt, funcMaxSigmaPtVsL1405Pt; + + using CollisionsCentSel = soa::Filtered; + using McRecoCollisionsCentSel = soa::Filtered; + + Filter filterCentrality = aod::cent::centFT0C >= centralityMin && aod::cent::centFT0C <= centralityMax; + + // Configurable axes + ConfigurableAxis axisCent{"axisCent", {10000, 0., 100.}, ""}; + ConfigurableAxis axisPtL1405{"axisPtL1405", {100, 0., 10.}, ""}; + ConfigurableAxis axisPCompsL1405{"axisPCompsL1405", {100, -10., 10.}, ""}; + ConfigurableAxis axisPtKinkDaug{"axisPtKinkDaug", {100, -5., 5.}, ""}; + ConfigurableAxis axisPtResolution{"axisPtResolution", {100, -0.5, 0.5}, ""}; + ConfigurableAxis axisMassL1405{"axisMassL1405", {100, 1.3, 1.8}, ""}; + ConfigurableAxis axisXi1530Mass{"axisXi1530Mass", {100, 1.4, 1.6}, ""}; + ConfigurableAxis axisMassResolution{"axisMassResolution", {100, -0.1, 0.1}, ""}; + ConfigurableAxis axisNSig{"axisNSig", {100, -5., 5.}, ""}; + ConfigurableAxis axisSigmaMass{"axisSigmaMass", {100, 1.1, 1.4}, ""}; + ConfigurableAxis axisXiMass{"axisXiMass", {100, 1.2, 1.5}, ""}; + ConfigurableAxis axisVertexZ{"axisVertexZ", {100, -15., 15.}, ""}; + ConfigurableAxis axisQtAP{"axisQtAP", {100, 0., 0.3}, ""}; + ConfigurableAxis axisAlphaAP{"axisAlphaAP", {200, -1., 1.}, ""}; + ConfigurableAxis axisSigmaRadius{"axisSigmaRadius", {100, 0., 100.}, ""}; + ConfigurableAxis axisDcaSigmaToPv{"axisDcaSigmaToPv", {120, 0., 0.05}, ""}; + ConfigurableAxis axisDcaKinkToPv{"axisDcaKinkToPv", {200, 0., 20.}, ""}; + ConfigurableAxis axisScalarProd{"axisScalarProd", {200, -4., 4.}, ""}; Preslice mKinkPerCol = aod::track::collisionId; Preslice mPerColTracks = aod::track::collisionId; @@ -111,41 +175,184 @@ struct lambda1405analysis { void init(InitContext const&) { // Axes - const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec ptPiAxis{100, -5, 5, "#it{p}_{T}^{#pi} (GeV/#it{c})"}; - const AxisSpec ptResolutionAxis{100, -0.5, 0.5, "#it{p}_{T}^{rec} - #it{p}_{T}^{gen} (GeV/#it{c})"}; - const AxisSpec massAxis{100, 1.3, 1.6, "m (GeV/#it{c}^{2})"}; - const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; - const AxisSpec nSigmaPiAxis{100, -5, 5, "n#sigma_{#pi}"}; - const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + const AxisSpec ptAxis{axisPtL1405, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec pCompAxisL1405{axisPCompsL1405, "#it{p}_{comp} (GeV/#it{c})"}; + const AxisSpec ptKinkDaugAxis{axisPtKinkDaug, "#it{p}_{T}^{#pi} (GeV/#it{c})"}; + const AxisSpec ptResolutionAxis{axisPtResolution, "#it{p}_{T}^{rec} - #it{p}_{T}^{gen} (GeV/#it{c})"}; + const AxisSpec lambda1405MassAxis{axisMassL1405, "m (GeV/#it{c}^{2})"}; + const AxisSpec xi1530MassAxis{axisXi1530Mass, "m (GeV/#it{c}^{2})"}; + const AxisSpec massResolutionAxis{axisMassResolution, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; + const AxisSpec nSigmaAxis{axisNSig, "n#sigma_{#pi}"}; + const AxisSpec sigmaMassAxis{axisSigmaMass, "m (GeV/#it{c}^{2})"}; + const AxisSpec xiMassAxis{axisXiMass, "m (GeV/#it{c}^{2})"}; + const AxisSpec vertexZAxis{axisVertexZ, "vrtx_{Z} [cm]"}; + const AxisSpec qtAxis{axisQtAP, "q_{T, AP}"}; + const AxisSpec alphaAxis{axisAlphaAP, "#alpha_{AP}"}; + const AxisSpec sigmaRadiusAxis{axisSigmaRadius, "#Sigma radius (cm)"}; + const AxisSpec centAxis{axisCent, "Centrality"}; + const AxisSpec dcaSigmaToPvBinsAxis{axisDcaSigmaToPv, "DCA of mother to Pv"}; + const AxisSpec dcaKinkToPvBinsAxis{axisDcaKinkToPv, "DCA of kink to Pv"}; + const AxisSpec scalarProdAxis{axisScalarProd, "SP"}; + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - // lambda1405 to sigmaminus - rLambda1405.add("h2PtMass_0", "h2PtMass_0", {HistType::kTH2F, {ptAxis, massAxis}}); - rLambda1405.add("h2PtMassSigmaBeforeCuts_0", "h2PtMassSigmaBeforeCuts_0", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rLambda1405.add("h2PtMassSigma_0", "h2PtMassSigma_0", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rLambda1405.add("h2SigmaMassVsMass_0", "h2SigmaMassVsMass_0", {HistType::kTH2F, {massAxis, sigmaMassAxis}}); - rLambda1405.add("h2PtPiNSigma_0", "h2PtPiNSigma_0", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); - rLambda1405.add("h2PtPiNSigmaTOF_0", "h2PtPiNSigmaTOF_0", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); - // lambda1405 to sigmaplus - rLambda1405.add("h2PtMass_1", "h2PtMass_1", {HistType::kTH2F, {ptAxis, massAxis}}); - rLambda1405.add("h2PtMassSigmaBeforeCuts_1", "h2PtMassSigmaBeforeCuts_1", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rLambda1405.add("h2PtMassSigma_1", "h2PtMassSigma_1", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rLambda1405.add("h2SigmaMassVsMass_1", "h2SigmaMassVsMass_1", {HistType::kTH2F, {massAxis, sigmaMassAxis}}); - rLambda1405.add("h2PtPiNSigma_1", "h2PtPiNSigma_1", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); - rLambda1405.add("h2PtPiNSigmaTOF_1", "h2PtPiNSigmaTOF_1", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); - - if (doprocessMC) { + // Sigma- candidate properties + rSigmaMinus.add("hSigmaMinusMass", "hSigmaMinusMass", {HistType::kTH1D, {sigmaMassAxis}}); + rSigmaMinus.add("hSigmaPlusMass", "hSigmaPlusMass", {HistType::kTH1D, {sigmaMassAxis}}); + rSigmaMinus.add("hSigmaMinusPt", "hSigmaMinusPt", {HistType::kTH1D, {ptAxis}}); + rSigmaMinus.add("hMassXiMinusSigmaMinus", "hMassXiMinusSigmaMinus", {HistType::kTH1D, {xiMassAxis}}); + rSigmaMinus.add("h2PtMassSigmaMinusBeforeCuts", "h2PtMassSigmaMinusBeforeCuts", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2PtPiKinkNSigBeforeCutsSigmaMinus", "h2PtPiKinkNSigBeforeCutsSigmaMinus", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rSigmaMinus.add("h2dPtMassSigmaMinus", "h2dPtMassSigmaMinus", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2SigmaMinusMassVsLambdaMass", "h2SigmaMinusMassVsLambdaMass", {HistType::kTH2F, {lambda1405MassAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2KinkPiPtNSigTofSigmaMinus", "h2KinkPiPtNSigTofSigmaMinus", {HistType::kTH2F, {ptKinkDaugAxis, nSigmaAxis}}); + rSigmaMinus.add("h2KinkPrPtNSigTofSigmaMinus", "h2KinkPrPtNSigTofSigmaMinus", {HistType::kTH2F, {ptKinkDaugAxis, nSigmaAxis}}); + rSigmaMinus.add("hSigmaMinusArmPod", "hSigmaMinusArmPod", {HistType::kTH2D, {alphaAxis, qtAxis}}); + rSigmaMinus.add("hSigmaMinusRadius", "hSigmaMinusRadius", {HistType::kTH1D, {sigmaRadiusAxis}}); + rSigmaMinus.add("hSigmaMinusDcaToPv", "hSigmaMinusDcaToPv", {HistType::kTH1D, {dcaSigmaToPvBinsAxis}}); + rSigmaMinus.add("hSigmaMinusKinkPt", "hSigmaMinusKinkPt", {HistType::kTH1D, {ptKinkDaugAxis}}); + rSigmaMinus.add("hSigmaMinusKinkTpcNSigPi", "hSigmaMinusKinkTpcNSigPi", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaMinus.add("hSigmaMinusKinkTofNSigPi", "hSigmaMinusKinkTofNSigPi", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaMinus.add("hSigmaMinusDcaKinkDauToPv", "hSigmaMinusDcaKinkDauToPv", {HistType::kTH1D, {dcaKinkToPvBinsAxis}}); + + // Sigma+ candidate properties + rSigmaPlus.add("hSigmaMinusMass", "hSigmaMinusMass", {HistType::kTH1D, {sigmaMassAxis}}); + rSigmaPlus.add("hSigmaPlusMass", "hSigmaPlusMass", {HistType::kTH1D, {sigmaMassAxis}}); + rSigmaPlus.add("hSigmaPlusPt", "hSigmaPlusPt", {HistType::kTH1D, {ptAxis}}); + rSigmaPlus.add("h2PtMassSigmaPlusBeforeCuts", "h2PtMassSigmaPlusBeforeCuts", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaPlus.add("h2PtPiKinkNSigBeforeCutsSigmaPlus", "h2PtPiKinkNSigBeforeCutsSigmaPlus", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rSigmaPlus.add("h2PtPrKinkNSigBeforeCutsSigmaPlus", "h2PtPrKinkNSigBeforeCutsSigmaPlus", {HistType::kTH2F, {ptAxis, nSigmaAxis}}); + rSigmaPlus.add("h2dPtMassSigmaPlus", "h2dPtMassSigmaPlus", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaPlus.add("h2SigmaPlusMassVsLambdaMass", "h2SigmaPlusMassVsLambdaMass", {HistType::kTH2F, {lambda1405MassAxis, sigmaMassAxis}}); + rSigmaPlus.add("h2KinkPrPtNSigTofSigmaPlus", "h2KinkPrPtNSigTofSigmaPlus", {HistType::kTH2F, {ptKinkDaugAxis, nSigmaAxis}}); + rSigmaPlus.add("hSigmaPlusArmPod", "hSigmaPlusArmPod", {HistType::kTH2D, {alphaAxis, qtAxis}}); + rSigmaPlus.add("hSigmaPlusRadius", "hSigmaPlusRadius", {HistType::kTH1D, {sigmaRadiusAxis}}); + rSigmaPlus.add("hSigmaPlusDcaToPv", "hSigmaPlusDcaToPv", {HistType::kTH1D, {dcaSigmaToPvBinsAxis}}); + rSigmaPlus.add("hSigmaPlusKinkPt", "hSigmaPlusKinkPt", {HistType::kTH1D, {ptKinkDaugAxis}}); + rSigmaPlus.add("hSigmaPlusKinkTpcNSigPi", "hSigmaPlusKinkTpcNSigPi", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaPlus.add("hSigmaPlusKinkTofNSigPi", "hSigmaPlusKinkTofNSigPi", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaPlus.add("hSigmaPlusKinkTpcNSigPr", "hSigmaPlusKinkTpcNSigPr", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaPlus.add("hSigmaPlusKinkTofNSigPr", "hSigmaPlusKinkTofNSigPr", {HistType::kTH1D, {nSigmaAxis}}); + rSigmaPlus.add("hSigmaPlusDcaKinkDauToPv", "hSigmaPlusDcaKinkDauToPv", {HistType::kTH1D, {dcaKinkToPvBinsAxis}}); + rSigmaPlus.add("hMassXiMinusSigmaPlus", "hMassXiMinusSigmaPlus", {HistType::kTH1D, {xiMassAxis}}); + + // Mass QA + rLambda1405.add("hMassL1405", "hMassL1405", {HistType::kTH1D, {lambda1405MassAxis}}); + rLambda1405.add("hMassXi1530", "hMassXi1530", {HistType::kTH1D, {xi1530MassAxis}}); + // Kinematic distributions + rLambda1405.add("hPx", "hPx;#it{p}_x;Counts", {HistType::kTH1D, {pCompAxisL1405}}); + rLambda1405.add("hPy", "hPy;#it{p}_y;Counts", {HistType::kTH1D, {pCompAxisL1405}}); + rLambda1405.add("hPz", "hPz;#it{p}_z;Counts", {HistType::kTH1D, {pCompAxisL1405}}); + rLambda1405.add("hPt", "hPt", {HistType::kTH1D, {ptAxis}}); + rLambda1405.add("hPhi", "hPhi", {HistType::kTH1D, {{128, -o2::constants::math::PI, o2::constants::math::PI}}}); + // Pion daughter properties + rLambda1405.add("hBachPiPt", "hBachPiPt", {HistType::kTH1D, {ptKinkDaugAxis}}); + rLambda1405.add("hBachPiNSigTpc", "hBachPiNSigTpc", {HistType::kTH1D, {nSigmaAxis}}); + rLambda1405.add("hBachPiNSigTof", "hBachPtNSigTof", {HistType::kTH1D, {nSigmaAxis}}); + rLambda1405.add("h2BachPiPtNSigTof", "h2BachPiPtNSigTof", {HistType::kTH2F, {ptKinkDaugAxis, nSigmaAxis}}); + rLambda1405.add("h2BachPiPtNSigTpc", "h2BachPiPtNSigTpc", {HistType::kTH2F, {ptKinkDaugAxis, nSigmaAxis}}); + + // Selection QA + rSelections.add("hSelectionsL1405", "hSelectionsL1405", {HistType::kTH1D, {{7, -0.f, 6.5f}}}); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(2, "Passed Sigma sel"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(3, "Passed Bach PID sel"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(4, "Upper mass sel"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(5, "Correl. #Sigma #it{p}_{T} sel"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(6, "Correl. bach. #pi #it{p}_{T} sel"); + rSelections.get(HIST("hSelectionsL1405"))->GetXaxis()->SetBinLabel(7, "Accepted"); + rSelections.add("hSelectionsSigmaPlus", "hSelectionsSigmaPlus", {HistType::kTH1D, {{7, -0.f, 6.5f}}}); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(2, "Passed kink sel"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(3, "Passed mass sel"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(4, "Passed cutDCAtoPvSigma"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(5, "Passed cutDCAtoPvPiFromSigma"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(6, "Passed cutSigmaRadius"); + rSelections.get(HIST("hSelectionsSigmaPlus"))->GetXaxis()->SetBinLabel(7, "Passed cutSigmaQtAP"); + rSelections.add("hSelectionsSigmaMinus", "hSelectionsSigmaMinus", {HistType::kTH1D, {{7, -0.f, 6.5f}}}); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(2, "Passed kink sel"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(3, "Passed mass sel"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(4, "Passed cutDCAtoPvSigma"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(5, "Passed cutDCAtoPvPiFromSigma"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(6, "Passed cutSigmaRadius"); + rSelections.get(HIST("hSelectionsSigmaMinus"))->GetXaxis()->SetBinLabel(7, "Passed cutSigmaQtAP"); + rSelections.add("hSelectionsBachPi", "hSelectionsBachPi", {HistType::kTH1D, {{6, -0.f, 5.5f}}}); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(2, "Sign sel"); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(3, "Nsigma Tpc sel"); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(4, "Tpc clusters sel"); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(5, "#eta sel"); + rSelections.get(HIST("hSelectionsBachPi"))->GetXaxis()->SetBinLabel(6, "PID sel"); + rSelections.add("hSelectionsKinkPi", "hSelectionsKinkPi", {HistType::kTH1D, {{7, -0.f, 6.5f}}}); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(2, "Tpc N#sigma PID sel"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(3, "Tpc N clusters sel"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(4, "#eta sel"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(5, "ITS clusters sel"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(6, "has Tof sel"); + rSelections.get(HIST("hSelectionsKinkPi"))->GetXaxis()->SetBinLabel(7, "N#sigma Tof sel"); + rSelections.add("hSelectionsKinkPr", "hSelectionsKinkPr", {HistType::kTH1D, {{7, -0.f, 6.5f}}}); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(1, "All"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(2, "Tpc N#sigma PID sel"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(3, "Tpc N clusters sel"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(4, "#eta sel"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(5, "ITS clusters sel"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(6, "has Tof sel"); + rSelections.get(HIST("hSelectionsKinkPr"))->GetXaxis()->SetBinLabel(7, "N#sigma Tof sel"); + + if (doprocessDataWCentQVecs) { + rLambda1405.add("hScalarProd", "hScalarProd", {HistType::kTH1D, {scalarProdAxis}}); + std::vector axesFlow = {lambda1405MassAxis, ptAxis, centAxis, scalarProdAxis}; + rLambda1405.add("hSparseFlowL1405", "THn for SP", HistType::kTHnSparseF, axesFlow); + } + + if (doprocessMc || doprocessMcWCentSel) { // Add MC histograms if needed, to sigmaminus - rLambda1405.add("h2MassResolution_0", "h2MassResolution_0", {HistType::kTH2F, {massAxis, massResolutionAxis}}); - rLambda1405.add("h2PtResolution_0", "h2PtResolution_0", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); - rLambda1405.add("h2PtMassMC_0", "h2PtMassMC_0", {HistType::kTH2F, {ptAxis, massAxis}}); + rLambda1405.add("hRecoL1405", "hRecoL1405;;Counts", {HistType::kTH2F, {{6, -0.5, 5.5}, ptAxis}}); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(1, "Reconstructed #Sigma (1405)"); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(2, "Has MC particle"); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(3, "Has #Sigma daug"); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(4, "Has bach #pi"); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(5, "Has mothers"); + rLambda1405.get(HIST("hRecoL1405"))->GetXaxis()->SetBinLabel(6, "Has same mother"); + rLambda1405.add("hGenL1405", "hGenL1405;;Counts", {HistType::kTH2F, {{3, -0.5, 2.5}, ptAxis}}); + rLambda1405.get(HIST("hGenL1405"))->GetXaxis()->SetBinLabel(1, "#Lambda(1405) #rightarrow #Sigma^{-} #pi^{+} #rightarrow n #pi^{-} #pi^{+}"); + rLambda1405.get(HIST("hGenL1405"))->GetXaxis()->SetBinLabel(2, "#Lambda(1405) #rightarrow #Sigma^{+} #pi^{-} #rightarrow n #pi^{+} #pi^{-}"); + rLambda1405.get(HIST("hGenL1405"))->GetXaxis()->SetBinLabel(3, "#Lambda(1405) #rightarrow #Sigma^{+} #pi^{-} #rightarrow p #pi^{0} #pi^{-}"); + rLambda1405.add("h2GenSigmaMinusArmPod", "h2GenSigmaMinusArmPod", {HistType::kTH2F, {alphaAxis, qtAxis}}); + rLambda1405.add("h2GenSigmaPlusArmPod", "h2GenSigmaPlusArmPod", {HistType::kTH2F, {alphaAxis, qtAxis}}); + rLambda1405.add("h2GenPtVsBachPtSigmaMinusPiToPiPiNeutron", "h2GenPtVsBachPtSigmaMinusPiToPiPiNeutron;#Lambda(1405) #it{p}_{T} (GeV/c); Bach #pi #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenPtVsBachPtSigmaPlusPiToPiPiN", "h2GenPtVsBachPtSigmaPlusPiToPiPiN;#Lambda(1405) #it{p}_{T} (GeV/c); Bach #pi #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenPtVsBachPtSigmaPlusPiToPiPiP", "h2GenPtVsBachPtSigmaPlusPiToPiPiP;#Lambda(1405) #it{p}_{T} (GeV/c); Bach #pi #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenPtVsSigmaPtSigmaMinusPiToPiPiNeutron", "h2GenPtVsBachPtSigmaMinusPiToPiPiNeutron;#Lambda(1405) #it{p}_{T} (GeV/c); #Sigma #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenPtVsSigmaPtSigmaPlusPiToPiPiN", "h2GenPtVsBachPtSigmaPlusPiToPiPiN;#Lambda(1405) #it{p}_{T} (GeV/c); #Sigma #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenPtVsSigmaPtSigmaPlusPiToPiPiP", "h2GenPtVsBachPtSigmaPlusPiToPiPiP;#Lambda(1405) #it{p}_{T} (GeV/c); #Sigma #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenSigmaPtVsKinkPtSigmaMinusPiToPiPiNeutron", "h2GenSigmaPtVsKinkPtSigmaMinusPiToPiPiNeutron;#Sigma #it{p}_{T} (GeV/c); Kink #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenSigmaPtVsKinkPtSigmaPlusPiToPiPiN", "h2GenSigmaPtVsKinkPtSigmaPlusPiTo Pi PiNeutron;#Sigma #it{p}_{T} (GeV/c); Kink #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2GenSigmaPtVsKinkPtSigmaPlusPiToPiPiP", "h2GenSigmaPtVsKinkPtSigmaPlusPiToPiPiP;#Sigma #it{p}_{T} (GeV/c); Kink #it{p}_{T} (GeV/c)", {HistType::kTH2F, {ptAxis, ptAxis}}); + rLambda1405.add("h2MassResolutionFromSigmaMinus", "h2MassResolutionFromSigmaMinus", {HistType::kTH2F, {lambda1405MassAxis, massResolutionAxis}}); + rLambda1405.add("h2PtResolutionFromSigmaMinus", "h2PtResolutionFromSigmaMinus", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); // Add MC histograms if needed, to sigmaplus - rLambda1405.add("h2MassResolution_1", "h2MassResolution_1", {HistType::kTH2F, {massAxis, massResolutionAxis}}); - rLambda1405.add("h2PtResolution_1", "h2PtResolution_1", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); - rLambda1405.add("h2PtMassMC_1", "h2PtMassMC_1", {HistType::kTH2F, {ptAxis, massAxis}}); + rLambda1405.add("h2MassResolutionFromSigmaPlus", "h2MassResolutionFromSigmaPlus", {HistType::kTH2F, {lambda1405MassAxis, massResolutionAxis}}); + rLambda1405.add("h2PtResolutionFromSigmaPlus", "h2PtResolutionFromSigmaPlus", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); + // rLambda1405.add("h2PtMassMCWithSigmaDaug", "h2PtMassMCWithSigmaDaug", {HistType::kTH2F, {ptAxis, lambda1405MassAxis}}); + // rLambda1405.add("h2PtMassMCNoSigmaDaug", "h2PtMassMCNoSigmaDaug", {HistType::kTH2F, {ptAxis, lambda1405MassAxis}}); } + + // Functional selections + funcMinQtAlphaAP = TF1("funcMinQtAlphaAP", Form("%s", cutSigmaQtAPMin.value.data()), -1, 1); + LOGF(info, "funcMinQtAlphaAP: %s", Form("%s", cutSigmaQtAPMin.value.data())); + funcMinQtAlphaAP = TF1("funcMaxQtAlphaAP", Form("%s", cutSigmaQtAPMax.value.data()), -1, 1); + LOGF(info, "funcMaxQtAlphaAP: %s", Form("%s", cutSigmaQtAPMax.value.data())); + funcMinQtAlphaAP = TF1("funcMinBachPiPtVsL1405Pt", Form("%s", cutMinBachPiPtVsL1405Pt.value.data()), 0., 100); + LOGF(info, "funcMinBachPiPtVsL1405Pt: %s", Form("%s", cutMinBachPiPtVsL1405Pt.value.data())); + funcMinQtAlphaAP = TF1("funcMaxBachPiPtVsL1405Pt", Form("%s", cutMaxBachPiPtVsL1405Pt.value.data()), 0., 100); + LOGF(info, "funcMaxBachPiPtVsL1405Pt: %s", Form("%s", cutMaxBachPiPtVsL1405Pt.value.data())); + funcMinQtAlphaAP = TF1("funcMinSigmaPtVsL1405Pt", Form("%s", cutMinSigmaPtVsL1405Pt.value.data()), 0., 100); + LOGF(info, "funcMinSigmaPtVsL1405Pt: %s", Form("%s", cutMinSigmaPtVsL1405Pt.value.data())); + funcMinQtAlphaAP = TF1("funcMaxSigmaPtVsL1405Pt", Form("%s", cutMaxSigmaPtVsL1405Pt.value.data()), 0., 100); + LOGF(info, "funcMaxSigmaPtVsL1405Pt: %s", Form("%s", cutMaxSigmaPtVsL1405Pt.value.data())); } float alphaAP(const std::array& momMother, const std::array& momKink) @@ -164,139 +371,337 @@ struct lambda1405analysis { return std::sqrt(p2A - dp * dp / p2V0); } - template - bool selectPiTrack(const Ttrack& candidate, bool piFromSigma) + template + bool selectPiBach(const TTrack& candidate) + { + if (std::abs(candidate.tpcNSigmaPi()) > cutNSigTpc) { + return false; + } + rSelections.fill(HIST("hSelectionsBachPi"), 2); // Nsigma Tpc + + if (candidate.tpcNClsFound() < cutNTpcClusPi) { + return false; + } + rSelections.fill(HIST("hSelectionsBachPi"), 3); // Tpc clusters + + if (std::abs(candidate.eta()) > cutEtaDaughter) { + return false; + } + rSelections.fill(HIST("hSelectionsBachPi"), 4); // Eta selection + + return true; + } + + template + bool selectPiKink(const TTrack& candidate) { - if (std::abs(candidate.tpcNSigmaPi()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPi || std::abs(candidate.eta()) > cutEtaDaught) { + rSelections.fill(HIST("hSelectionsKinkPi"), 0); // All pion kink candidates + + if (std::abs(candidate.tpcNSigmaPi()) > cutNSigTpc) { return false; } - if (piFromSigma) { - return true; + rSelections.fill(HIST("hSelectionsKinkPi"), 1); // Nsigma Tpc + + if (candidate.tpcNClsFound() < cutNTpcClusPi) { + return false; + } + rSelections.fill(HIST("hSelectionsKinkPi"), 2); // Tpc clusters + + if (std::abs(candidate.eta()) > cutEtaDaughter) { + return false; } + rSelections.fill(HIST("hSelectionsKinkPi"), 3); // Eta selection - if (candidate.itsNCls() < cutNITSClusPi) { + if (candidate.itsNCls() < cutNITSClusKink) { return false; } + rSelections.fill(HIST("hSelectionsKinkPi"), 4); // ITS clusters - if (useTOF && !candidate.hasTOF()) { + if (useTof && !candidate.hasTOF()) { return false; } + rSelections.fill(HIST("hSelectionsKinkPi"), 5); // has Tof - if (useTOF && std::abs(candidate.tofNSigmaPi()) > cutNSigmaTOF) { + if (useTof && std::abs(candidate.tofNSigmaPi()) > cutNSigTof) { return false; } + rSelections.fill(HIST("hSelectionsKinkPi"), 6); // Nsigma Tof return true; // Track is selected } - template - bool selectProTrack(const Ttrack& candidate, bool prFromSigma) + template + bool selectPrKink(const TTrack& candidate) { - if (std::abs(candidate.tpcNSigmaPr()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPi || std::abs(candidate.eta()) > cutEtaDaught) { + rSelections.fill(HIST("hSelectionsKinkPr"), 0); // All proton kink candidates + + if (std::abs(candidate.tpcNSigmaPr()) > cutNSigTpc) { return false; } - if (prFromSigma) { - return true; + rSelections.fill(HIST("hSelectionsKinkPr"), 1); // Nsigma Tpc + + if (candidate.tpcNClsFound() < cutNTpcClusPi) { + return false; } - if (candidate.itsNCls() < cutNITSClusPi) { + rSelections.fill(HIST("hSelectionsKinkPr"), 2); // Tpc clusters + + if (std::abs(candidate.eta()) > cutEtaDaughter) { return false; } - if (useTOF && !candidate.hasTOF()) { + rSelections.fill(HIST("hSelectionsKinkPr"), 3); // eta selection + + if (candidate.itsNCls() < cutNITSClusKink) { return false; } - if (useTOF && std::abs(candidate.tofNSigmaPr()) > cutNSigmaTOF) { + rSelections.fill(HIST("hSelectionsKinkPr"), 4); // ITS clusters + + if (useTof && !candidate.hasTOF()) { return false; } + rSelections.fill(HIST("hSelectionsKinkPr"), 5); // has Tof + + if (useTof && std::abs(candidate.tofNSigmaPr()) > cutNSigTof) { + return false; + } + rSelections.fill(HIST("hSelectionsKinkPr"), 6); // Nsigma Tof + return true; // Track is selected } - bool selectCandidate(aod::KinkCands::iterator const& sigmaCand, TracksFull const& tracks) + template + void fillHistosSigma(const lambda1405candidate& lambda1405Cand, const TCand& sigmaCand, const TTrack& kinkDauTrack) + { + + if (sigmaCand.mothSign() > 0) { + rSigmaPlus.fill(HIST("hSigmaPlusMass"), sigmaCand.mSigmaPlus()); + rSigmaPlus.fill(HIST("h2dPtMassSigmaPlus"), sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); + rSigmaPlus.fill(HIST("hMassXiMinusSigmaPlus"), sigmaCand.mXiMinus()); + rSigmaPlus.fill(HIST("hSigmaPlusArmPod"), lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP); + rSigmaPlus.fill(HIST("hSigmaPlusPt"), sigmaCand.ptMoth()); + rSigmaPlus.fill(HIST("hSigmaPlusRadius"), lambda1405Cand.sigmaRadius); + rSigmaPlus.fill(HIST("hSigmaPlusDcaToPv"), sigmaCand.dcaMothPv()); + rSigmaPlus.fill(HIST("hSigmaPlusDcaKinkDauToPv"), sigmaCand.dcaDaugPv()); + // Fill QA histos for kink daughter + rSigmaPlus.fill(HIST("hSigmaPlusKinkPt"), kinkDauTrack.pt()); + rSigmaPlus.fill(HIST("hSigmaPlusKinkTpcNSigPi"), kinkDauTrack.tpcNSigmaPi()); + rSigmaPlus.fill(HIST("hSigmaPlusKinkTofNSigPi"), kinkDauTrack.tofNSigmaPi()); + rSigmaPlus.fill(HIST("hSigmaPlusKinkTpcNSigPr"), kinkDauTrack.tpcNSigmaPr()); + rSigmaPlus.fill(HIST("hSigmaPlusKinkTofNSigPr"), kinkDauTrack.tofNSigmaPr()); + } else { + rSigmaMinus.fill(HIST("hSigmaMinusMass"), sigmaCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2dPtMassSigmaMinus"), sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("hMassXiMinusSigmaMinus"), sigmaCand.mXiMinus()); + rSigmaMinus.fill(HIST("hSigmaMinusArmPod"), lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP); + rSigmaMinus.fill(HIST("hSigmaMinusPt"), sigmaCand.ptMoth()); + rSigmaMinus.fill(HIST("hSigmaMinusRadius"), lambda1405Cand.sigmaRadius); + rSigmaMinus.fill(HIST("hSigmaMinusDcaToPv"), sigmaCand.dcaMothPv()); + rSigmaMinus.fill(HIST("hSigmaMinusDcaKinkDauToPv"), sigmaCand.dcaDaugPv()); + // Fill QA histos for kink daughter + rSigmaMinus.fill(HIST("hSigmaMinusKinkPt"), kinkDauTrack.pt()); + rSigmaMinus.fill(HIST("hSigmaMinusKinkTpcNSigPi"), kinkDauTrack.tpcNSigmaPi()); + rSigmaMinus.fill(HIST("hSigmaMinusKinkTofNSigPi"), kinkDauTrack.tofNSigmaPi()); + } + } + + template + void fillHistosLambda1405(const lambda1405candidate& cand, const TTrack& piTrack) { + + // Fill QA histos for Lambda(1405) candidate + rLambda1405.fill(HIST("hMassL1405"), cand.massL1405); + rLambda1405.fill(HIST("hMassXi1530"), cand.massXi1530); + rLambda1405.fill(HIST("hPx"), cand.px); + rLambda1405.fill(HIST("hPy"), cand.py); + rLambda1405.fill(HIST("hPz"), cand.pz); + rLambda1405.fill(HIST("hPt"), cand.pt()); + rLambda1405.fill(HIST("hPhi"), cand.phi); + + // Bachelor Pi + rLambda1405.fill(HIST("hBachPiPt"), piTrack.pt() * (cand.isSigmaPlus ? -1 : 1)); // Invert pt for Sigma+ to have the correct charge correlation + rLambda1405.fill(HIST("hBachPiNSigTpc"), piTrack.tpcNSigmaPi()); + rLambda1405.fill(HIST("h2BachPiPtNSigTpc"), piTrack.pt(), piTrack.tpcNSigmaPi()); + rLambda1405.fill(HIST("hBachPiNSigTof"), piTrack.tofNSigmaPi()); + rLambda1405.fill(HIST("h2BachPiPtNSigTof"), piTrack.pt(), piTrack.tofNSigmaPi()); + } + + void constructCollCandidates(aod::KinkCands::iterator const& sigmaCand, TracksFull const& tracks, std::vector& selectedCandidates) + { + rSelections.fill(HIST("hSelectionsL1405"), 0); // All candidates + + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 0); // All Sigma- candidates + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 0); // All Sigma+ candidates + } + auto kinkDauTrack = sigmaCand.trackDaug_as(); - bool isPiKink = selectPiTrack(kinkDauTrack, true); - bool isProKink = selectProTrack(kinkDauTrack, true); - if (!isPiKink && !isProKink) { - return false; + bool isPiKink = selectPiKink(kinkDauTrack); + bool isPrKink = selectPrKink(kinkDauTrack); + if (!isPiKink && !isPrKink) { + return; } + lambda1405Cand.hasPiKink = isPiKink; + lambda1405Cand.hasPrKink = isPrKink; - if (isPiKink) { - rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts_0"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); - rLambda1405.fill(HIST("h2PtPiNSigma_0"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPi()); + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 1); // Passed kink sel + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 1); // Passed kink sel } - if (isProKink) { - rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts_1"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); - rLambda1405.fill(HIST("h2PtPiNSigma_1"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPr()); + + // Sigma- or AntiSigma+ candidates + if (isPiKink && sigmaCand.mothSign() < 0) { + rSigmaMinus.fill(HIST("h2PtMassSigmaMinusBeforeCuts"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2PtPiKinkNSigBeforeCutsSigmaMinus"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPi()); + } + if (isPiKink && sigmaCand.mothSign() > 0) { + rSigmaPlus.fill(HIST("h2PtMassSigmaPlusBeforeCuts"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); + rSigmaPlus.fill(HIST("h2PtPiKinkNSigBeforeCutsSigmaPlus"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPi()); + } + // Only Sigma+ can have a proton as kink daughter + if (isPrKink) { + rSigmaPlus.fill(HIST("h2PtMassSigmaPlusBeforeCuts"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); + rSigmaPlus.fill(HIST("h2PtPrKinkNSigBeforeCutsSigmaPlus"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPr()); } - lambda1405Cand.isSigmaPlus = isProKink && (sigmaCand.mSigmaPlus() > o2::constants::physics::MassSigmaPlus - cutSigmaMass && sigmaCand.mSigmaPlus() < o2::constants::physics::MassSigmaPlus + cutSigmaMass); + lambda1405Cand.isSigmaPlus = isPrKink && (sigmaCand.mSigmaPlus() > o2::constants::physics::MassSigmaPlus - cutSigmaMass && sigmaCand.mSigmaPlus() < o2::constants::physics::MassSigmaPlus + cutSigmaMass); lambda1405Cand.isSigmaMinus = isPiKink && (sigmaCand.mSigmaMinus() > o2::constants::physics::MassSigmaMinus - cutSigmaMass && sigmaCand.mSigmaMinus() < o2::constants::physics::MassSigmaMinus + cutSigmaMass); if (!lambda1405Cand.isSigmaPlus && !lambda1405Cand.isSigmaMinus) { - return false; + return; } + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 2); // Passed mass sel + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 2); // Passed mass sel + } + float sigmaRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma || std::abs(sigmaCand.dcaDaugPv()) < cutDCAtoPVPiFromSigma || sigmaRad < cutSigmaRadius) { - return false; + if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPvSigma) { + return; + } + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 3); // Passed cutDCAtoPvSigma + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 3); // Passed cutDCAtoPvSigma } + if (std::abs(sigmaCand.dcaDaugPv()) < cutDCAtoPvPiFromSigma) { + return; + } + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 4); // cutDCAtoPvPiFromSigma + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 4); // cutDCAtoPvPiFromSigma + } + + if (sigmaRad < cutSigmaRadius) { + return; + } + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 5); // Passed mass sel + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 5); // Passed mass sel + } + + auto kinkDauMom = std::array{sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + auto sigmaMom = std::array{sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + // Sigma properties + lambda1405Cand.sigmaId = sigmaCand.globalIndex(); + lambda1405Cand.sigmaMinusMass = sigmaCand.mSigmaMinus(); + lambda1405Cand.sigmaPlusMass = sigmaCand.mSigmaPlus(); + lambda1405Cand.xiMinusMass = sigmaCand.mXiMinus(); + lambda1405Cand.sigmaSign = sigmaCand.mothSign(); + lambda1405Cand.sigmaAlphaAP = alphaAP(sigmaMom, kinkDauMom); + lambda1405Cand.sigmaQtAP = qtAP(sigmaMom, kinkDauMom); + lambda1405Cand.sigmaPt = sigmaCand.ptMoth(); + lambda1405Cand.sigmaRadius = sigmaRad; + lambda1405Cand.kinkDcaDauToPv = sigmaCand.dcaDaugPv(); + + if (lambda1405Cand.sigmaQtAP < funcMinQtAlphaAP.Eval(lambda1405Cand.sigmaAlphaAP) || + lambda1405Cand.sigmaQtAP > funcMaxQtAlphaAP.Eval(lambda1405Cand.sigmaAlphaAP)) { + return; + } + if (sigmaCand.mothSign() < 0) { + rSelections.fill(HIST("hSelectionsSigmaMinus"), 6); // Passed mass sel + } else { + rSelections.fill(HIST("hSelectionsSigmaPlus"), 6); // Passed mass sel + } + + // Kink daughter properties + lambda1405Cand.kinkDauId = kinkDauTrack.globalIndex(); + lambda1405Cand.kinkPt = kinkDauTrack.pt(); + lambda1405Cand.kinkPiNSigTpc = kinkDauTrack.tpcNSigmaPi(); + lambda1405Cand.kinkPiNSigTof = kinkDauTrack.tofNSigmaPi(); + lambda1405Cand.kinkPrNSigTpc = kinkDauTrack.tpcNSigmaPr(); + lambda1405Cand.kinkPrNSigTof = kinkDauTrack.tofNSigmaPr(); + + fillHistosSigma(lambda1405Cand, sigmaCand, kinkDauTrack); + rSelections.fill(HIST("hSelectionsL1405"), 1); // Passed Sigma sel + for (const auto& piTrack : tracks) { - if (!doLSBkg) { - if (piTrack.sign() == sigmaCand.mothSign()) { - continue; - } - } else { - if (piTrack.sign() != sigmaCand.mothSign()) { - continue; - } + rSelections.fill(HIST("hSelectionsBachPi"), 0); // All bachelors + + bool isUnlikeSign = (piTrack.sign() != sigmaCand.mothSign()); + bool acceptPair = doLikeSignBkg ? !isUnlikeSign : isUnlikeSign; + if (!acceptPair) { + continue; } + rSelections.fill(HIST("hSelectionsBachPi"), 1); - if (!selectPiTrack(piTrack, false)) { + if (!selectPiBach(piTrack)) { continue; } + rSelections.fill(HIST("hSelectionsBachPi"), 5); // PID sel + rSelections.fill(HIST("hSelectionsL1405"), 2); // Bach Pi selection - auto kinkDauMom = std::array{sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; - auto sigmaMom = std::array{sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; auto piMom = std::array{piTrack.px(), piTrack.py(), piTrack.pz()}; - float invMass = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassSigmaMinus, o2::constants::physics::MassPiPlus}); - float invMassXiPi = RecoDecay::m(std::array{sigmaMom, kinkDauMom}, std::array{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}); + float invMass{-1.f}; + if (lambda1405Cand.isSigmaMinus) { + invMass = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassSigmaMinus, o2::constants::physics::MassPiPlus}); + } else if (lambda1405Cand.isSigmaPlus) { + invMass = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassSigmaPlus, o2::constants::physics::MassPiMinus}); + } if (invMass > cutUpperMass) { continue; } + rSelections.fill(HIST("hSelectionsL1405"), 3); // Upper mass selection - lambda1405Cand.kinkDauID = kinkDauTrack.globalIndex(); - lambda1405Cand.sigmaID = sigmaCand.globalIndex(); - lambda1405Cand.piID = piTrack.globalIndex(); + // Daughter Pi properties + lambda1405Cand.piId = piTrack.globalIndex(); + lambda1405Cand.piPt = piTrack.pt(); + lambda1405Cand.bachPiNSigTpc = piTrack.tpcNSigmaPi(); + if (useTof) { + lambda1405Cand.bachPiNSigTof = piTrack.tofNSigmaPi(); + } else { + lambda1405Cand.bachPiNSigTof = -999; // Not used if Tof is not enabled + } + // Lambda(1405) candidate properties + lambda1405Cand.massL1405 = invMass; + lambda1405Cand.massXi1530 = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}); lambda1405Cand.px = sigmaMom[0] + piMom[0]; lambda1405Cand.py = sigmaMom[1] + piMom[1]; lambda1405Cand.pz = sigmaMom[2] + piMom[2]; - lambda1405Cand.mass = invMass; - lambda1405Cand.massXi1530 = invMassXiPi; - - lambda1405Cand.sigmaMinusMass = sigmaCand.mSigmaMinus(); - lambda1405Cand.sigmaPlusMass = sigmaCand.mSigmaPlus(); - lambda1405Cand.xiMinusMass = sigmaCand.mXiMinus(); - lambda1405Cand.sigmaSign = sigmaCand.mothSign(); - lambda1405Cand.sigmaAlphaAP = alphaAP(sigmaMom, kinkDauMom); - lambda1405Cand.sigmaQtAP = qtAP(sigmaMom, kinkDauMom); - lambda1405Cand.sigmaPt = sigmaCand.ptMoth(); - lambda1405Cand.sigmaRadius = sigmaRad; - lambda1405Cand.kinkPt = kinkDauTrack.pt(); - lambda1405Cand.kinkTPCNSigmaPi = kinkDauTrack.tpcNSigmaPi(); - lambda1405Cand.kinkTOFNSigmaPi = kinkDauTrack.tofNSigmaPi(); - lambda1405Cand.kinkTPCNSigmaPr = kinkDauTrack.tpcNSigmaPr(); - lambda1405Cand.kinkTOFNSigmaPr = kinkDauTrack.tofNSigmaPr(); - lambda1405Cand.dcaKinkDauToPV = sigmaCand.dcaDaugPv(); + lambda1405Cand.phi = std::atan2(lambda1405Cand.py, lambda1405Cand.px); + lambda1405Cand.scalarProd = -1; - lambda1405Cand.piPt = piTrack.pt(); - lambda1405Cand.nSigmaTPCPi = piTrack.tpcNSigmaPi(); - if (useTOF) { - lambda1405Cand.nSigmaTOFPi = piTrack.tofNSigmaPi(); - } else { - lambda1405Cand.nSigmaTOFPi = -999; // Not used if TOF is not enabled + // Check correlations between transverse momenta of L1405, sigma and bachelor pi + if (std::hypot(sigmaCand.pxMoth(), sigmaCand.pyMoth()) < funcMinSigmaPtVsL1405Pt.Eval(lambda1405Cand.pt()) || + std::hypot(sigmaCand.pxMoth(), sigmaCand.pyMoth()) > funcMaxSigmaPtVsL1405Pt.Eval(lambda1405Cand.pt())) { + continue; } - return true; // Candidate is selected + rSelections.fill(HIST("hSelectionsL1405"), 4); // Accepted + + if (piTrack.pt() < funcMinBachPiPtVsL1405Pt.Eval(lambda1405Cand.pt()) || + piTrack.pt() > funcMaxBachPiPtVsL1405Pt.Eval(lambda1405Cand.pt())) { + continue; + } + rSelections.fill(HIST("hSelectionsL1405"), 5); // Accepted + + fillHistosLambda1405(lambda1405Cand, piTrack); + rSelections.fill(HIST("hSelectionsL1405"), 6); // Accepted + selectedCandidates.push_back(lambda1405Cand); } - return false; // No valid pion track found } template @@ -319,60 +724,199 @@ struct lambda1405analysis { return isKinkFromSigma; // Return true if the kink comes from the Sigma } - void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& kinkCands, TracksFull const& tracks) + template + void fillOutputData(const TCollision& collision, const TCand& sigmaCands, const TTrack& kinkDauTrack) { - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + if constexpr (requires { collision.centFT0C(); }) { + if (collision.centFT0C() < centralityMin || collision.centFT0C() > centralityMax) { + LOG(info) << "Skipping collision due to centrality cut"; + return; + } + } + if (std::abs(collision.posZ()) > cutZVertex || !collision.sel8()) { return; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - for (const auto& sigmaCand : kinkCands) { - if (selectCandidate(sigmaCand, tracks)) { + for (const auto& sigmaCand : sigmaCands) { + std::vector selectedCandidates; + constructCollCandidates(sigmaCand, kinkDauTrack, selectedCandidates); + for (auto& lambda1405Cand : selectedCandidates) { if (lambda1405Cand.isSigmaMinus) { - rLambda1405.fill(HIST("h2PtMass_0"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtMassSigma_0"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMinusMass); - rLambda1405.fill(HIST("h2SigmaMassVsMass_0"), lambda1405Cand.mass, lambda1405Cand.sigmaMinusMass); - rLambda1405.fill(HIST("h2PtPiNSigmaTOF_0"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.nSigmaTOFPi); + rSigmaMinus.fill(HIST("h2SigmaMinusMassVsLambdaMass"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMinusMass); + if (lambda1405Cand.hasPiKink) { + rSigmaMinus.fill(HIST("h2KinkPiPtNSigTofSigmaMinus"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.bachPiNSigTof); + } + if (lambda1405Cand.hasPrKink) { + rSigmaMinus.fill(HIST("h2KinkPrPtNSigTofSigmaMinus"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.bachPiNSigTof); + } } if (lambda1405Cand.isSigmaPlus) { - rLambda1405.fill(HIST("h2PtMass_1"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtMassSigma_1"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaPlusMass); - rLambda1405.fill(HIST("h2SigmaMassVsMass_1"), lambda1405Cand.mass, lambda1405Cand.sigmaPlusMass); - rLambda1405.fill(HIST("h2PtPiNSigmaTOF_1"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.nSigmaTOFPi); + rSigmaPlus.fill(HIST("h2SigmaPlusMassVsLambdaMass"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaPlusMass); + rSigmaPlus.fill(HIST("h2KinkPrPtNSigTofSigmaPlus"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.bachPiNSigTof); } if (fillOutputTree) { + float const ptCand = lambda1405Cand.pt(); + if (downSampleFactor < 1.) { + float const pseudoRndm = ptCand * 1000. - static_cast(ptCand * 1000); + if (ptCand < ptDownSampleMax && pseudoRndm >= downSampleFactor) { + continue; + } + } outputDataTable(lambda1405Cand.px, lambda1405Cand.py, lambda1405Cand.pz, - lambda1405Cand.mass, lambda1405Cand.massXi1530, + lambda1405Cand.massL1405, lambda1405Cand.massXi1530, lambda1405Cand.sigmaMinusMass, lambda1405Cand.sigmaPlusMass, lambda1405Cand.xiMinusMass, lambda1405Cand.sigmaPt, lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP, lambda1405Cand.sigmaRadius, lambda1405Cand.kinkPt, - lambda1405Cand.kinkTPCNSigmaPi, lambda1405Cand.kinkTOFNSigmaPi, - lambda1405Cand.kinkTPCNSigmaPr, lambda1405Cand.kinkTOFNSigmaPr, - lambda1405Cand.dcaKinkDauToPV, - lambda1405Cand.nSigmaTPCPi, lambda1405Cand.nSigmaTOFPi); + lambda1405Cand.kinkPiNSigTpc, lambda1405Cand.kinkPiNSigTof, + lambda1405Cand.kinkPrNSigTpc, lambda1405Cand.kinkPrNSigTof, + lambda1405Cand.kinkDcaDauToPv, + lambda1405Cand.bachPiNSigTpc, lambda1405Cand.bachPiNSigTof); + } + if constexpr (requires { collision.qvecFT0CRe(); }) { + float const xQVec = collision.qvecFT0CRe(); + float const yQVec = collision.qvecFT0CIm(); + float const cos2Phi = std::cos(2 * lambda1405Cand.phi); + float const sin2Phi = std::sin(2 * lambda1405Cand.phi); + lambda1405Cand.scalarProd = cos2Phi * xQVec + sin2Phi * yQVec; + float const ptCand = lambda1405Cand.pt(); + rLambda1405.fill(HIST("hSparseFlowL1405"), ptCand, lambda1405Cand.massL1405, collision.centFT0C(), lambda1405Cand.scalarProd); + LOG(info) << "Filled flow sparse for candidate with pt " << ptCand << ", mass " << lambda1405Cand.massL1405 << ", centrality " << collision.centFT0C() << " and scalar product " << lambda1405Cand.scalarProd; + if (fillFlowTree) { + if (downSampleFactor < 1.) { + float const pseudoRndm = ptCand * 1000. - static_cast(ptCand * 1000); + if (ptCand < ptDownSampleMax && pseudoRndm >= downSampleFactor) { + continue; + } + } + outputDataFlowTable(ptCand, lambda1405Cand.massL1405, + lambda1405Cand.sigmaMinusMass, lambda1405Cand.sigmaPlusMass, + lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP, + lambda1405Cand.kinkPiNSigTpc, lambda1405Cand.kinkPiNSigTof, + lambda1405Cand.kinkPrNSigTpc, lambda1405Cand.kinkPrNSigTof, + lambda1405Cand.kinkDcaDauToPv, + lambda1405Cand.bachPiNSigTpc, lambda1405Cand.bachPiNSigTof, + lambda1405Cand.scalarProd, collision.centFT0C()); + } } } } } + + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& kinkCands, TracksFull const& tracks) + { + fillOutputData(collision, kinkCands, tracks); + } PROCESS_SWITCH(lambda1405analysis, processData, "Data processing", true); - void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const& tracks) + void processDataWCentQVecs(CollisionsCentSel::iterator const& collision, aod::KinkCands const& kinkCands, TracksFull const& tracks) + { + fillOutputData(collision, kinkCands, tracks); + } + PROCESS_SWITCH(lambda1405analysis, processDataWCentQVecs, "Data processing with centrality and Q vectors info", false); + + template + int matchGenDecay(const TMother& motherPart, const aod::McParticles& mcParticles, std::array& daugsIdxs) + { + int pdgMother = motherPart.pdgCode(); + int8_t sign = 0; + + int MaxDepthFinState = 2; // Maximum depth to look for the decay chain + + std::vector arrL1405Daugs = {}; + std::array finalState; + int decayChannel = -1; + + // Match L(1405) --> n pi- pi+ final state + if (pdgMother > 0) { // Change sign of neutral decay products + finalState = {PDG_t::kNeutron, PDG_t::kPiMinus, PDG_t::kPiPlus}; + } else { + finalState = {-PDG_t::kNeutron, PDG_t::kPiMinus, PDG_t::kPiPlus}; + } + if (RecoDecay::isMatchedMCGen(mcParticles, motherPart, lambda1405PdgCode, finalState, true, &sign, MaxDepthFinState)) { + // Match the intermediate Sigma + RecoDecay::getDaughters(motherPart, &arrL1405Daugs, std::array{0}, 1); + for (auto iProng = 0u; iProng < arrL1405Daugs.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrL1405Daugs[iProng]); + if (std::abs(daughI.pdgCode()) == PDG_t::kSigmaPlus) { + decayChannel = kSigmaPlusPiToPiPiNeutron; + daugsIdxs[1] = arrL1405Daugs[iProng]; + } + if (std::abs(daughI.pdgCode()) == PDG_t::kSigmaMinus) { + decayChannel = kSigmaMinusPiToPiPiNeutron; + daugsIdxs[1] = arrL1405Daugs[iProng]; + } + if (std::abs(daughI.pdgCode()) == PDG_t::kPiPlus) { + daugsIdxs[0] = arrL1405Daugs[iProng]; + } + } + } + + // Match L(1405) --> p pi0 pi+ final state, only possible for Sigma+ + if (pdgMother > 0) { // Change sign of neutral decay products + finalState = {PDG_t::kProton, PDG_t::kPi0, PDG_t::kPiMinus}; + } else { + finalState = {PDG_t::kProton, -PDG_t::kPi0, PDG_t::kPiMinus}; + } + + if (RecoDecay::isMatchedMCGen(mcParticles, motherPart, lambda1405PdgCode, finalState, true, &sign, MaxDepthFinState)) { + // Match the intermediate Sigma + RecoDecay::getDaughters(motherPart, &arrL1405Daugs, std::array{0}, 1); + for (auto iProng = 0u; iProng < arrL1405Daugs.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrL1405Daugs[iProng]); + if (std::abs(daughI.pdgCode()) == PDG_t::kSigmaPlus) { + decayChannel = kSigmaPlusPiToPiPiProton; + daugsIdxs[1] = arrL1405Daugs[iProng]; + } + if (std::abs(daughI.pdgCode()) == PDG_t::kPiPlus) { + daugsIdxs[0] = arrL1405Daugs[iProng]; + } + } + } + + std::vector arrSigmaDaugs = {}; + auto sigmaDaug = mcParticles.rawIteratorAt(daugsIdxs[1]); + RecoDecay::getDaughters(sigmaDaug, &arrSigmaDaugs, std::array{0}, 1); + for (auto iProng = 0u; iProng < arrSigmaDaugs.size(); ++iProng) { + auto daughSigma = mcParticles.rawIteratorAt(arrSigmaDaugs[iProng]); + if (std::abs(daughSigma.pdgCode()) == PDG_t::kPiPlus || std::abs(daughSigma.pdgCode()) == PDG_t::kProton) { + daugsIdxs[2] = arrSigmaDaugs[iProng]; + } + } + + return decayChannel; + } + + template + void fillOutputMc(const TCollision& collisions, const aod::KinkCands& sigmaCands, const aod::McTrackLabels& trackLabelsMC, const TTrack& tracks, const aod::McParticles& particlesMC) { for (const auto& collision : collisions) { - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + if constexpr (requires { collision.centFT0C(); }) { + if (collision.centFT0C() < centralityMin || collision.centFT0C() > centralityMax) { + return; + } + } + if (std::abs(collision.posZ()) > cutZVertex) { // || !collision.sel8()) { continue; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - auto sigmaCandsPerCol = kinkCands.sliceBy(mKinkPerCol, collision.globalIndex()); + auto sigmaCandsPerCol = sigmaCands.sliceBy(mKinkPerCol, collision.globalIndex()); auto tracksPerCol = tracks.sliceBy(mPerColTracks, collision.globalIndex()); for (const auto& sigmaCand : sigmaCandsPerCol) { - if (selectCandidate(sigmaCand, tracksPerCol)) { + std::vector selectedCandidates; + constructCollCandidates(sigmaCand, tracksPerCol, selectedCandidates); + LOG(info) << "Selected " << selectedCandidates.size() << " Lambda(1405) candidates in this collision"; + for (const auto& lambda1405Cand : selectedCandidates) { + rLambda1405.fill(HIST("hRecoL1405"), 0., lambda1405Cand.pt()); // All reconstructed + // Do MC association - auto mcLabPiKink = trackLabelsMC.rawIteratorAt(lambda1405Cand.kinkDauID); - auto mcLabSigma = trackLabelsMC.rawIteratorAt(lambda1405Cand.sigmaID); - auto mcLabPi = trackLabelsMC.rawIteratorAt(lambda1405Cand.piID); - if (!mcLabSigma.has_mcParticle() || mcLabPiKink.has_mcParticle() || mcLabPi.has_mcParticle()) { + auto mcLabPiKink = trackLabelsMC.rawIteratorAt(lambda1405Cand.kinkDauId); + auto mcLabSigma = trackLabelsMC.rawIteratorAt(lambda1405Cand.sigmaId); + auto mcLabPi = trackLabelsMC.rawIteratorAt(lambda1405Cand.piId); + if (!mcLabSigma.has_mcParticle() || !mcLabPiKink.has_mcParticle() || !mcLabPi.has_mcParticle()) { continue; // Skip if no valid MC association } + rLambda1405.fill(HIST("hRecoL1405"), 1., lambda1405Cand.pt()); // All with associated MC particle + auto mcTrackKink = mcLabPiKink.mcParticle_as(); auto mcTrackSigma = mcLabSigma.mcParticle_as(); auto mcTrackPi = mcLabPi.mcParticle_as(); @@ -384,14 +928,17 @@ struct lambda1405analysis { if (!isSigmaMinusKink && !isSigmaPlusToPiKink && !isSigmaPlusToPrKink) { continue; // Skip if not a valid Sigma kink decay } + rLambda1405.fill(HIST("hRecoL1405"), 2., lambda1405Cand.pt()); // Has kink decay in MC - if (std::abs(mcTrackPi.pdgCode()) != 211) { + if (std::abs(mcTrackPi.pdgCode()) != PDG_t::kPiPlus) { continue; // Skip if not a valid pion candidate } + rLambda1405.fill(HIST("hRecoL1405"), 3., lambda1405Cand.pt()); // Has bach pi if (!mcTrackSigma.has_mothers() || !mcTrackPi.has_mothers()) { continue; // Skip if no mothers found } + rLambda1405.fill(HIST("hRecoL1405"), 4., lambda1405Cand.pt()); // Has mothers for Sigma and Pi // check that labpi and labsigma have the same mother (a lambda1405 candidate) int lambda1405Id = -1; @@ -406,35 +953,31 @@ struct lambda1405analysis { if (lambda1405Id == -1) { continue; // Skip if the Sigma and pion do not share the same lambda1405 candidate } + rLambda1405.fill(HIST("hRecoL1405"), 4., lambda1405Cand.pt()); // Has same mother + auto lambda1405Mother = particlesMC.rawIteratorAt(lambda1405Id); float lambda1405Mass = std::sqrt(lambda1405Mother.e() * lambda1405Mother.e() - lambda1405Mother.p() * lambda1405Mother.p()); if (lambda1405Cand.isSigmaMinus) { - rLambda1405.fill(HIST("h2PtMass_0"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtMassSigma_0"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMinusMass); - rLambda1405.fill(HIST("h2SigmaMassVsMass_0"), lambda1405Cand.mass, lambda1405Cand.sigmaMinusMass); - rLambda1405.fill(HIST("h2PtPiNSigma_0"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); - rLambda1405.fill(HIST("h2MassResolution_0"), lambda1405Mass, lambda1405Mass - lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtResolution_0"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); + rSigmaMinus.fill(HIST("h2SigmaMinusMassVsLambdaMass"), lambda1405Cand.massL1405, lambda1405Cand.sigmaMinusMass); + rLambda1405.fill(HIST("h2MassResolutionFromSigmaMinus"), lambda1405Mass, lambda1405Mass - lambda1405Cand.massL1405); + rLambda1405.fill(HIST("h2PtResolutionFromSigmaMinus"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); } if (lambda1405Cand.isSigmaPlus) { - rLambda1405.fill(HIST("h2PtMass_1"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtMassSigma_1"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaPlusMass); - rLambda1405.fill(HIST("h2SigmaMassVsMass_1"), lambda1405Cand.mass, lambda1405Cand.sigmaPlusMass); - rLambda1405.fill(HIST("h2PtPiNSigma_1"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); - rLambda1405.fill(HIST("h2MassResolution_1"), lambda1405Mass, lambda1405Mass - lambda1405Cand.mass); - rLambda1405.fill(HIST("h2PtResolution_1"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); + rSigmaPlus.fill(HIST("h2SigmaPlusMassVsLambdaMass"), lambda1405Cand.massL1405, lambda1405Cand.sigmaPlusMass); + rLambda1405.fill(HIST("h2MassResolutionFromSigmaPlus"), lambda1405Mass, lambda1405Mass - lambda1405Cand.massL1405); + rLambda1405.fill(HIST("h2PtResolutionFromSigmaPlus"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); } if (fillOutputTree) { outputDataTableMC(lambda1405Cand.px, lambda1405Cand.py, lambda1405Cand.pz, - lambda1405Cand.mass, lambda1405Cand.massXi1530, + lambda1405Cand.massL1405, lambda1405Cand.massXi1530, lambda1405Cand.sigmaMinusMass, lambda1405Cand.sigmaPlusMass, lambda1405Cand.xiMinusMass, lambda1405Cand.sigmaPt, lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP, lambda1405Cand.sigmaRadius, lambda1405Cand.kinkPt, - lambda1405Cand.kinkTPCNSigmaPi, lambda1405Cand.kinkTOFNSigmaPi, - lambda1405Cand.kinkTPCNSigmaPr, lambda1405Cand.kinkTOFNSigmaPr, - lambda1405Cand.dcaKinkDauToPV, - lambda1405Cand.nSigmaTPCPi, lambda1405Cand.nSigmaTOFPi, + lambda1405Cand.kinkPiNSigTpc, lambda1405Cand.kinkPiNSigTof, + lambda1405Cand.kinkPrNSigTpc, lambda1405Cand.kinkPrNSigTof, + lambda1405Cand.kinkDcaDauToPv, + lambda1405Cand.bachPiNSigTpc, lambda1405Cand.bachPiNSigTof, lambda1405Mother.pt(), lambda1405Mass, mcTrackSigma.pdgCode(), mcTrackKink.pdgCode()); } } @@ -446,30 +989,51 @@ struct lambda1405analysis { if (std::abs(mcPart.pdgCode()) != lambda1405PdgCode) { continue; // Only consider Lambda(1405) candidates } - - if (!mcPart.has_daughters()) { - continue; // Skip if no daughters + std::array idxsSigmaKinkBachPi{-1, -1, -1}; + int decayChannel = matchGenDecay(mcPart, particlesMC, idxsSigmaKinkBachPi); + if (decayChannel == -1) { + continue; // Skip if it doesn't match the decay channels of interest } + rLambda1405.fill(HIST("hGenL1405"), decayChannel, mcPart.pt()); - // Check if the Lambda(1405) has a Sigma daughter - bool hasSigmaDaughter = false; - int dauPdgCode = 0; - for (const auto& daughter : mcPart.daughters_as()) { - if (std::abs(daughter.pdgCode()) == 3122 || std::abs(daughter.pdgCode()) == 3222) { // Sigma PDG code - hasSigmaDaughter = true; - dauPdgCode = daughter.pdgCode(); - break; // Found a Sigma daughter, exit loop - } + auto bachPi = particlesMC.rawIteratorAt(idxsSigmaKinkBachPi[0]); + auto sigmaDaug = particlesMC.rawIteratorAt(idxsSigmaKinkBachPi[1]); + auto sigmaKinkDaug = particlesMC.rawIteratorAt(idxsSigmaKinkBachPi[2]); + // Generated Armenteros-Podolanski variables + float genSigmaAlphaAP = alphaAP({sigmaDaug.px(), sigmaDaug.py(), sigmaDaug.pz()}, {sigmaKinkDaug.px(), sigmaKinkDaug.py(), sigmaKinkDaug.pz()}); + float genSigmaQtAP = qtAP({sigmaDaug.px(), sigmaDaug.py(), sigmaDaug.pz()}, {sigmaKinkDaug.px(), sigmaKinkDaug.py(), sigmaKinkDaug.pz()}); + if (decayChannel == kSigmaMinusPiToPiPiNeutron) { + rLambda1405.fill(HIST("h2GenSigmaMinusArmPod"), genSigmaAlphaAP, genSigmaQtAP); + rLambda1405.fill(HIST("h2GenPtVsBachPtSigmaMinusPiToPiPiNeutron"), mcPart.pt(), bachPi.pt()); + rLambda1405.fill(HIST("h2GenPtVsSigmaPtSigmaMinusPiToPiPiNeutron"), mcPart.pt(), sigmaDaug.pt()); + rLambda1405.fill(HIST("h2GenSigmaPtVsKinkPtSigmaMinusPiToPiPiNeutron"), sigmaDaug.pt(), sigmaKinkDaug.pt()); } - if (!hasSigmaDaughter) { - continue; // Skip if no Sigma daughter found + if (decayChannel == kSigmaPlusPiToPiPiNeutron) { + rLambda1405.fill(HIST("h2GenSigmaPlusArmPod"), genSigmaAlphaAP, genSigmaQtAP); + rLambda1405.fill(HIST("h2GenPtVsBachPtSigmaPlusPiToPiPiN"), mcPart.pt(), bachPi.pt()); + rLambda1405.fill(HIST("h2GenPtVsSigmaPtSigmaPlusPiToPiPiN"), mcPart.pt(), sigmaDaug.pt()); + rLambda1405.fill(HIST("h2GenSigmaPtVsKinkPtSigmaPlusPiToPiPiN"), sigmaDaug.pt(), sigmaKinkDaug.pt()); + } + if (decayChannel == kSigmaPlusPiToPiPiProton) { + rLambda1405.fill(HIST("h2GenSigmaPlusArmPod"), genSigmaAlphaAP, genSigmaQtAP); + rLambda1405.fill(HIST("h2GenPtVsBachPtSigmaPlusPiToPiPiP"), mcPart.pt(), bachPi.pt()); + rLambda1405.fill(HIST("h2GenPtVsSigmaPtSigmaPlusPiToPiPiP"), mcPart.pt(), sigmaDaug.pt()); + rLambda1405.fill(HIST("h2GenSigmaPtVsKinkPtSigmaPlusPiToPiPiP"), sigmaDaug.pt(), sigmaKinkDaug.pt()); } - - float mcMass = std::sqrt(mcPart.e() * mcPart.e() - mcPart.p() * mcPart.p()); - dauPdgCode ? rLambda1405.fill(HIST("h2PtMassMC_0"), mcPart.pt(), mcMass) : rLambda1405.fill(HIST("h2PtMassMC_1"), mcPart.pt(), mcMass); } } - PROCESS_SWITCH(lambda1405analysis, processMC, "MC processing", false); + + void processMc(CollisionsFullMc const& collisions, aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const& tracks) + { + fillOutputMc(collisions, kinkCands, trackLabelsMC, tracks, particlesMC); + } + PROCESS_SWITCH(lambda1405analysis, processMc, "MC processing", false); + + void processMcWCentSel(McRecoCollisionsCentSel const& collisions, aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const& tracks) + { + fillOutputMc(collisions, kinkCands, trackLabelsMC, tracks, particlesMC); + } + PROCESS_SWITCH(lambda1405analysis, processMcWCentSel, "MC processing with centrality selection", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Utils/svPoolCreator.h b/PWGLF/Utils/svPoolCreator.h index 68a621fd977..bcb62b95f61 100644 --- a/PWGLF/Utils/svPoolCreator.h +++ b/PWGLF/Utils/svPoolCreator.h @@ -87,8 +87,8 @@ class svPoolCreator } } - template - void appendTrackCand(const T& trackCand, const C& collisions, int pdgHypo, o2::aod::AmbiguousTracks const& ambiTracks, BC const&) + template + void appendTrackCand(const T& trackCand, const C& collisions, int pdgHypo, const AT& ambiTracks, BC const&) { if (pdgHypo != track0Pdg && pdgHypo != track1Pdg) { LOGP(debug, "Wrong pdg hypothesis"); @@ -106,11 +106,11 @@ class svPoolCreator if (ambTrack.trackId() != trackCand.globalIndex()) { continue; } - if (!ambTrack.has_bc() || ambTrack.bc_as().size() == 0) { + if (!ambTrack.has_bc() || ambTrack.template bc_as().size() == 0) { globalBC = BcInvalid; break; } - globalBC = ambTrack.bc_as().begin().globalBC(); + globalBC = ambTrack.template bc_as().begin().globalBC(); break; } } else { @@ -170,7 +170,6 @@ class svPoolCreator } else if (TESTBIT(trackCand.flags(), o2::aod::track::TrackTimeResIsRange)) { thresholdTime = std::sqrt(sigmaTimeRes2); thresholdTime += timeMarginNS; - } else { thresholdTime = 4. * std::sqrt(sigmaTimeRes2); thresholdTime += timeMarginNS; @@ -197,6 +196,7 @@ class svPoolCreator // is Sorting Needed ? TBD } + template std::vector& getSVCandPool(const C& collisions, bool combineLikeSign = false) { @@ -208,37 +208,34 @@ class svPoolCreator mVtxTrack0[i].clear(); mVtxTrack0[i].resize(collisions.size(), -1); } - - for (int pn = 0; pn < 2; pn++) { - auto& vtxFirstT = mVtxTrack0[pn]; - const auto& signTrack0Pool = track0Pool[pn]; + for (int iCharge = 0; iCharge < 2; iCharge++) { + auto& vtxFirstT = mVtxTrack0[iCharge]; + const auto& signTrack0Pool = track0Pool[iCharge]; for (unsigned i = 0; i < signTrack0Pool.size(); i++) { const auto& track0Seed = signTrack0Pool[i]; - LOG(debug) << "Processsing track0 with index: " << track0Seed.Idxtr << " min bracket: " << track0Seed.collBracket.getMin() << " max bracket: " << track0Seed.collBracket.getMax(); for (int j{track0Seed.collBracket.getMin()}; j <= track0Seed.collBracket.getMax(); ++j) { if (vtxFirstT[j] == -1) { vtxFirstT[j] = i; } } } - int track1sign = combineLikeSign ? pn : 1 - pn; + int track1sign = combineLikeSign ? iCharge : 1 - iCharge; auto& signTrack1 = track1Pool[track1sign]; - for (unsigned itp = 0; itp < signTrack1.size(); itp++) { - auto& track1Seed = signTrack1[itp]; - LOG(debug) << "Processing track1 with index: " << track1Seed.Idxtr << " min bracket: " << track1Seed.collBracket.getMin() << " max bracket: " << track1Seed.collBracket.getMax(); - int firsOverlapIdx = -1; + for (unsigned iTrack1 = 0; iTrack1 < signTrack1.size(); iTrack1++) { + auto& track1Seed = signTrack1[iTrack1]; + int firstOverlapIdx = -1; for (int j{track1Seed.collBracket.getMin()}; j <= track1Seed.collBracket.getMax(); ++j) { LOG(debug) << "Checking vtxFirstT at position " << j << " with value " << vtxFirstT[j]; if (vtxFirstT[j] != -1) { - firsOverlapIdx = vtxFirstT[j]; + firstOverlapIdx = vtxFirstT[j]; break; } } - if (firsOverlapIdx < 0) { + if (firstOverlapIdx < 0) { continue; } - for (unsigned itn = firsOverlapIdx; itn < signTrack0Pool.size(); itn++) { - auto& track0Seed = signTrack0Pool[itn]; + for (unsigned iTrack0 = firstOverlapIdx; iTrack0 < signTrack0Pool.size(); iTrack0++) { + auto& track0Seed = signTrack0Pool[iTrack0]; if (track0Seed.collBracket.getMin() > track1Seed.collBracket.getMax()) { break; From 55281d8d6692b3093d44dd2ca8488d02475342d6 Mon Sep 17 00:00:00 2001 From: navneetkumar231295 <71565461+navneetkumar231295@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:48:58 +0530 Subject: [PATCH 424/449] [PWGLF] To fix the background issue (#16536) Co-authored-by: Navneet --- .../Tasks/Resonances/chargedkstaranalysis.cxx | 96 +++++++++++++++---- 1 file changed, 75 insertions(+), 21 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx index e04c58be4d2..8caa58152ca 100644 --- a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx @@ -116,10 +116,10 @@ struct Chargedkstaranalysis { Configurable activateProductionFrame{"activateProductionFrame", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; Configurable activateBeamAxisFrame{"activateBeamAxisFrame", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; Configurable activateRandomFrame{"activateRandomFrame", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; - Configurable cRotations{"cRotations", 5, "Number of random rotations in the rotational background"}; - Configurable cBoostKShot{"cBoostKShot", true, "Boost the Kshot in Charged Kstar frame of reference"}; + Configurable cRotations{"cRotations", 4, "Number of random rotations in the rotational background"}; + Configurable cCosWithKShot{"cCosWithKShot", true, "Measure the angle with Kshort in Charged Kstar frame of reference"}; // Other cuts on Ks - Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable rotationalCut{"rotationalCut", 6, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; // fixed variables float rapidityMotherData = 0.5; @@ -807,7 +807,7 @@ struct Chargedkstaranalysis { ROOT::Math::PxPyPzMVector fourVecDauCM, daughterRot, motherRot, daughterRotCM; ROOT::Math::XYZVectorF beam1CM, beam2CM, zAxisCS, yAxisCS, xAxisCS; ROOT::Math::XYZVectorF v1CM, zaxisHE, yaxisHE, xaxisHE; - ROOT::Math::XYZVector randomVec, beamVec, normalVec; + ROOT::Math::XYZVector randomVec, beamVec, normalVec, normalVecRot, randomVecRot; float theta2; // //polarization calculations // zBeam = ROOT::Math::XYZVector(0.f, 0.f, 1.f); // ẑ: beam direction in lab frame @@ -857,13 +857,20 @@ struct Chargedkstaranalysis { if (doRotation) { for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); + if (helicityCfgs.cCosWithKShot) { + daughterRot = ROOT::Math::PxPyPzMVector(daughter2.Px() * std::cos(theta2) - daughter2.Py() * std::sin(theta2), daughter2.Px() * std::sin(theta2) + daughter2.Py() * std::cos(theta2), daughter2.Pz(), daughter2.M()); - daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); - - motherRot = daughterRot + daughter2; + motherRot = daughterRot + daughter1; + } else { + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + motherRot = daughterRot + daughter2; + } ROOT::Math::Boost boost2{motherRot.BoostToCM()}; - daughterRotCM = boost2(daughterRot); + if (helicityCfgs.cCosWithKShot) + daughterRotCM = boost2(daughter1); + else + daughterRotCM = boost2(daughterRot); auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); auto phiHelicityRot = std::atan2(yaxisHE.Dot(daughterRotCM.Vect().Unit()), xaxisHE.Dot(daughterRotCM.Vect().Unit())); @@ -883,9 +890,15 @@ struct Chargedkstaranalysis { for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); - daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + if (helicityCfgs.cCosWithKShot) { + daughterRot = ROOT::Math::PxPyPzMVector(daughter2.Px() * std::cos(theta2) - daughter2.Py() * std::sin(theta2), daughter2.Px() * std::sin(theta2) + daughter2.Py() * std::cos(theta2), daughter2.Pz(), daughter2.M()); - motherRot = daughterRot + daughter2; + motherRot = daughterRot + daughter1; + } else { + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + + motherRot = daughterRot + daughter2; + } ROOT::Math::Boost boost2{motherRot.BoostToCM()}; daughterRotCM = boost2(daughterRot); @@ -910,11 +923,26 @@ struct Chargedkstaranalysis { if (doRotation) { for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); - daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); - motherRot = daughterRot + daughter2; + if (helicityCfgs.cCosWithKShot) { + daughterRot = ROOT::Math::PxPyPzMVector(daughter2.Px() * std::cos(theta2) - daughter2.Py() * std::sin(theta2), daughter2.Px() * std::sin(theta2) + daughter2.Py() * std::cos(theta2), daughter2.Pz(), daughter2.M()); + + motherRot = daughterRot + daughter1; + } else { + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + + motherRot = daughterRot + daughter2; + } + ROOT::Math::Boost boost2{motherRot.BoostToCM()}; + if (helicityCfgs.cCosWithKShot) + daughterRotCM = boost2(daughter1); + else + daughterRotCM = boost2(daughterRot); + + normalVecRot = ROOT::Math::XYZVector(motherRot.Py(), -motherRot.Px(), 0.f); + auto cosThetaProductionRot = normalVecRot.Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(normalVecRot.Mag2())); if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { - fillKstarHist(true, multiplicity, motherRot, cosThetaProduction); + fillKstarHist(true, multiplicity, motherRot, cosThetaProductionRot); } } } @@ -929,9 +957,17 @@ struct Chargedkstaranalysis { if (doRotation) { for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); - daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); - motherRot = daughterRot + daughter2; + if (helicityCfgs.cCosWithKShot) { + daughterRot = ROOT::Math::PxPyPzMVector(daughter2.Px() * std::cos(theta2) - daughter2.Py() * std::sin(theta2), daughter2.Px() * std::sin(theta2) + daughter2.Py() * std::cos(theta2), daughter2.Pz(), daughter2.M()); + + motherRot = daughterRot + daughter1; + } else { + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + + motherRot = daughterRot + daughter2; + } + if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { fillKstarHist(true, multiplicity, motherRot, cosThetaStarBeam); } @@ -950,12 +986,30 @@ struct Chargedkstaranalysis { } if (doRotation) { for (int i = 0; i < helicityCfgs.cRotations; i++) { + auto phiRandomRot = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandomRot = gRandom->Uniform(0.f, constants::math::PI); + randomVecRot = ROOT::Math::XYZVector(std::sin(thetaRandomRot) * std::cos(phiRandomRot), std::sin(thetaRandomRot) * std::sin(phiRandomRot), std::cos(thetaRandomRot)); theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); - daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); - motherRot = daughterRot + daughter2; + if (helicityCfgs.cCosWithKShot) { + daughterRot = ROOT::Math::PxPyPzMVector(daughter2.Px() * std::cos(theta2) - daughter2.Py() * std::sin(theta2), daughter2.Px() * std::sin(theta2) + daughter2.Py() * std::cos(theta2), daughter2.Pz(), daughter2.M()); + + motherRot = daughterRot + daughter1; + } else { + daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); + + motherRot = daughterRot + daughter2; + } + + ROOT::Math::Boost boost2{motherRot.BoostToCM()}; + if (helicityCfgs.cCosWithKShot) + daughterRotCM = boost2(daughter1); + else + daughterRotCM = boost2(daughterRot); + auto cosThetaStarRandomRot = randomVecRot.Dot(daughterRotCM.Vect()) / std::sqrt(daughterRotCM.Vect().Mag2()); + if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { - fillKstarHist(true, multiplicity, motherRot, cosThetaStarRandom); + fillKstarHist(true, multiplicity, motherRot, cosThetaStarRandomRot); } } } @@ -1152,7 +1206,7 @@ struct Chargedkstaranalysis { histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); } - if (helicityCfgs.cBoostKShot) { + if (helicityCfgs.cCosWithKShot) { fillInvMass(lResoKstar, collision.centFT0M(), lResoSecondary, lDecayDaughter_bach, IsMix); } else { fillInvMass(lResoKstar, collision.centFT0M(), lDecayDaughter_bach, lResoSecondary, IsMix); @@ -1361,7 +1415,7 @@ struct Chargedkstaranalysis { const float lCentrality = iter->second; histos.fill(HIST("EffKstar/genKstar"), part.pt(), lCentrality); - if (helicityCfgs.cBoostKShot) { + if (helicityCfgs.cCosWithKShot) { fillInvMass(lResoKstar, lCentrality, lResoSecondary, lDecayDaughter_bach, eventCutCfgs.confIsMix); } else { fillInvMass(lResoKstar, lCentrality, lDecayDaughter_bach, lResoSecondary, eventCutCfgs.confIsMix); @@ -1453,7 +1507,7 @@ struct Chargedkstaranalysis { } histos.fill(HIST("EffKstar/recoKstar"), ptreco, lCentrality); - if (helicityCfgs.cBoostKShot) { + if (helicityCfgs.cCosWithKShot) { fillInvMass(lResoKstar, lCentrality, lResoSecondary, lDecayDaughter_bach, eventCutCfgs.confIsMix); } else { fillInvMass(lResoKstar, lCentrality, lDecayDaughter_bach, lResoSecondary, eventCutCfgs.confIsMix); From 541866ec467cc5b8f165fec2b04590a40ecc421e Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:57:11 +0530 Subject: [PATCH 425/449] [PWGLF] Added some event selection cuts, and TOF pid cuts for low momentum (#16533) --- PWGLF/Tasks/Resonances/deltaAnalysis.cxx | 84 ++++++++++++++++++------ 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/PWGLF/Tasks/Resonances/deltaAnalysis.cxx b/PWGLF/Tasks/Resonances/deltaAnalysis.cxx index c2cc29ac62d..2a343c0f57e 100644 --- a/PWGLF/Tasks/Resonances/deltaAnalysis.cxx +++ b/PWGLF/Tasks/Resonances/deltaAnalysis.cxx @@ -13,6 +13,7 @@ /// \brief Delta(1232) resonance analysis via proton-pion invariant mass reconstruction with advance PID and background rejection cuts /// \author Durgesh Bhatt +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" @@ -78,6 +79,10 @@ struct DeltaAnalysis { // FIX name/configurable: single space between type and name; member name == JSON key; lowerCamelCase Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted |z-vertex| range [cm]"}; + + Configurable cfgUseNoSameBunchPileupCut{"cfgUseNoSameBunchPileupCut", false, "Apply kNoSameBunchPileup event selection"}; + + Configurable cfgUseGoodZvtxFT0vsPVCut{"cfgUseGoodZvtxFT0vsPVCut", false, "Apply kIsGoodZvtxFT0vsPV event selection"}; Configurable applyOccupancyInTimeRangeCut{"applyOccupancyInTimeRangeCut", false, "Apply occupancy-in-time-range cut"}; Configurable cfgOccupancyMin{"cfgOccupancyMin", 0, "Minimum track occupancy in time range"}; Configurable cfgOccupancyMax{"cfgOccupancyMax", 9999, "Maximum track occupancy in time range"}; @@ -103,6 +108,7 @@ struct DeltaAnalysis { Configurable requirePrimaryTrack{"requirePrimaryTrack", true, "Require isPrimaryTrack flag"}; Configurable requireGlobalTrackNoDCA{"requireGlobalTrackNoDCA", true, "Require isGlobalTrackWoDCA flag"}; Configurable requirePVContributor{"requirePVContributor", true, "Require PV-contributor flag"}; + Configurable cfgLowPtTofNsigmaCut{"cfgLowPtTofNsigmaCut", 3.0f, "Low pt nSigma TOF cut for selecting pions and protons"}; Configurable cfgCutDCAz{"cfgCutDCAz", 0.1f, "Maximum |DCAz| for all tracks [cm]"}; Configurable> protonDCAPtBinEdges{"protonDCAPtBinEdges", {0.0f, 0.5f, 1.0f, 2.0f, 1000.f}, "Proton pT bin edges for DCAxy cut [GeV/c]"}; @@ -113,6 +119,7 @@ struct DeltaAnalysis { Configurable useTPCOnlyPID{"useTPCOnlyPID", false, "Use TPC-only PID (ignore TOF even if present)"}; Configurable requireTOFForProton{"requireTOFForProton", false, "Require TOF signal for proton candidates"}; Configurable requireTOFForPion{"requireTOFForPion", false, "Require TOF signal for pion candidates"}; + Configurable applyTOFCutWhenAvailableBelowThreshold{"applyTOFCutWhenAvailableBelowThreshold", false, "Apply TOF PID only when TOF information exists below momentum threshold"}; Configurable minProtonMomentum{"minProtonMomentum", 0.f, "Minimum proton momentum for TOF PID [GeV/c]"}; Configurable minTPCNSigmaProton{"minTPCNSigmaProton", -6.0f, "Minimum (lower bound) TPC nSigma for proton"}; @@ -198,7 +205,7 @@ struct DeltaAnalysis { mPionMaxDCAxy = pionMaxDCAxyPerPtBin.value; const AxisSpec ptAxis{200, 0., 10., "p_{T} (GeV/c)"}; - const AxisSpec massAxis{numberOfInvMassBins, 0.8, 1.8, "M_{inv} (GeV/#it{c}^{2})"}; + const AxisSpec massAxis{numberOfInvMassBins, 1.0, 8.0, "M_{inv} (GeV/#it{c}^{2})"}; const AxisSpec centAxis{cfgCentAxis, "Centrality (%)"}; const AxisSpec vtxAxis{cfgVtxAxis, "Vertex z [cm]"}; const AxisSpec rapAxis{cfgRapAxis, "Rapidity y"}; @@ -367,6 +374,7 @@ struct DeltaAnalysis { } } + // passesEventSelection with optional EventSelection cuts template bool passesEventSelection(CollisionType const& collision) { @@ -382,6 +390,16 @@ struct DeltaAnalysis { const float cent = getCentrality(collision); if (cent < cfgCentMin || cent > cfgCentMax) return false; + + if (cfgUseNoSameBunchPileupCut && + !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (cfgUseGoodZvtxFT0vsPVCut && + !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } return true; } @@ -480,19 +498,32 @@ struct DeltaAnalysis { tofPassed = true; } } + // ── Part 2: low-momentum region with TOF available ────────────────── if (totalMomentum < minProtonMomentum && tpcNSigPr < static_cast(maxTPCNSigmaProton)) { tpcPassed = true; - tofPassed = true; + if (applyTOFCutWhenAvailableBelowThreshold) { + // TOF is available (track.hasTOF() is true in this branch): require TOF nSigma + tofPassed = (tofNSigPr < cfgLowPtTofNsigmaCut); + } else { + tofPassed = true; + } } } else { - tofPassed = true; - if (track.tpcNSigmaPr() < minTPCNSigmaProton) - return false; - for (int i = 0; i < nTPCBins - 1; ++i) { - if (totalMomentum >= mProtonTPCMomBins[i] && totalMomentum < mProtonTPCMomBins[i + 1] && - tpcNSigPr < mProtonTPCNSigCuts[i] && tpcNSigPi > tpcNSigmaVetoThreshold) { - tpcPassed = true; - break; + // No TOF available (or useTPCOnlyPID == true) + if (totalMomentum < minProtonMomentum && tpcNSigPr < static_cast(maxTPCNSigmaProton)) { + // ── Part 2: low-momentum, no TOF → TPC-only regardless of configurable ── + tpcPassed = true; + tofPassed = true; + } else { + tofPassed = true; + if (track.tpcNSigmaPr() < minTPCNSigmaProton) + return false; + for (int i = 0; i < nTPCBins - 1; ++i) { + if (totalMomentum >= mProtonTPCMomBins[i] && totalMomentum < mProtonTPCMomBins[i + 1] && + tpcNSigPr < mProtonTPCNSigCuts[i] && tpcNSigPi > tpcNSigmaVetoThreshold) { + tpcPassed = true; + break; + } } } } @@ -535,19 +566,32 @@ struct DeltaAnalysis { tofPassed = true; } } + // ── Part 2: low-momentum region with TOF available ────────────────── if (totalMomentum < minPionMomentum && tpcNSigPi < static_cast(maxTPCNSigmaPion)) { tpcPassed = true; - tofPassed = true; + if (applyTOFCutWhenAvailableBelowThreshold) { + // TOF is available (track.hasTOF() is true in this branch): require TOF nSigma + tofPassed = (tofNSigPi < cfgLowPtTofNsigmaCut); + } else { + tofPassed = true; + } } } else { - tofPassed = true; - if (track.tpcNSigmaPi() < minTPCNSigmaPion) - return false; - for (int i = 0; i < nTPCBins - 1; ++i) { - if (totalMomentum >= mPionTPCMomBins[i] && totalMomentum < mPionTPCMomBins[i + 1] && - tpcNSigPi < mPionTPCNSigCuts[i] && tpcNSigPr > tpcNSigmaVetoThreshold) { - tpcPassed = true; - break; + // No TOF available (or useTPCOnlyPID == true) + if (totalMomentum < minPionMomentum && tpcNSigPi < static_cast(maxTPCNSigmaPion)) { + // ── Part 2: low-momentum, no TOF → TPC-only regardless of configurable ── + tpcPassed = true; + tofPassed = true; + } else { + tofPassed = true; + if (track.tpcNSigmaPi() < minTPCNSigmaPion) + return false; + for (int i = 0; i < nTPCBins - 1; ++i) { + if (totalMomentum >= mPionTPCMomBins[i] && totalMomentum < mPionTPCMomBins[i + 1] && + tpcNSigPi < mPionTPCNSigCuts[i] && tpcNSigPr > tpcNSigmaVetoThreshold) { + tpcPassed = true; + break; + } } } } @@ -961,7 +1005,7 @@ struct DeltaAnalysis { constexpr float kGenCentrality = 1.f; for (auto const& collision : collisions) { - if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) + if (!passesEventSelection(collision)) continue; const float centrality = getCentrality(collision); histos.fill(HIST("Event/hNcontributor"), collision.numContrib()); From 3bcf61cb6b0c10647c944d0093434c130b232e3e Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 5 Jun 2026 11:27:48 +0200 Subject: [PATCH 426/449] [PWGDQ] fixes to the feature extraction in the ML response class (#16538) --- PWGDQ/Core/MuonMatchingMlResponse.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Core/MuonMatchingMlResponse.h b/PWGDQ/Core/MuonMatchingMlResponse.h index 71a16ad9920..4714036ef51 100644 --- a/PWGDQ/Core/MuonMatchingMlResponse.h +++ b/PWGDQ/Core/MuonMatchingMlResponse.h @@ -206,6 +206,24 @@ float getPullR(T1 const& mftprop, T2 const& mchprop) return deltaR / errR; } +template +float getPullPt(T1 const& mftprop, T2 const& mchprop) +{ + double invPtMFT = std::abs(mftprop.getInvQPt()); + double ptMFT = (invPtMFT != 0) ? 1.0 / invPtMFT : 0; + double invPtErr2MFT = mftprop.getCovariances()(4, 4); + double ptErr2MFT = invPtErr2MFT * ptMFT * ptMFT * ptMFT * ptMFT; + + double invPtMCH = std::abs(mchprop.getInvQPt()); + double ptMCH = (invPtMCH != 0) ? 1.0 / invPtMCH : 0; + double invPtErr2MCH = mchprop.getCovariances()(4, 4); + double ptErr2MCH = invPtErr2MCH * ptMCH * ptMCH * ptMCH * ptMCH; + + float delta = ptMCH - ptMFT; + float err = std::sqrt(ptErr2MCH + ptErr2MFT); + return (err > 0 ? delta / err : 0); +} + template float getDeltaDirection(T1 const& mftprop, T2 const& mchprop) { @@ -317,7 +335,7 @@ class MlResponseMFTMuonMatch : public MlResponse CHECK_AND_FILL_FEATURE(pullPhi, getPull(mftprop.getPhi(), mftprop.getCovariances()(2, 2), mchprop.getPhi(), mchprop.getCovariances()(2, 2))); CHECK_AND_FILL_FEATURE(pullTgl, getPull(mftprop.getTgl(), mftprop.getCovariances()(3, 3), mchprop.getTgl(), mchprop.getCovariances()(3, 3))); /*dummy value*/ CHECK_AND_FILL_FEATURE(pullEta, 0); - /*dummy value*/ CHECK_AND_FILL_FEATURE(pullPt, 0); + CHECK_AND_FILL_FEATURE(pullPt, getPullPt(mftprop, mchprop)); CHECK_AND_FILL_FEATURE(pullR, getPullR(mftprop, mchprop)); // primary vertex parameters CHECK_AND_FILL_FEATURE(posX, collision.posX()); @@ -342,7 +360,7 @@ class MlResponseMFTMuonMatch : public MlResponse CHECK_AND_FILL_FEATURE(chi2MCHMFT, muon.chi2MatchMCHMFT()); CHECK_AND_FILL_FEATURE(chi2GlobMUON, muon.chi2()); CHECK_AND_FILL_FEATURE_OPTIONAL(dcaX, muon, fwdDcaX); - CHECK_AND_FILL_FEATURE_OPTIONAL(dcaY, muon, fwdDcaX); + CHECK_AND_FILL_FEATURE_OPTIONAL(dcaY, muon, fwdDcaY); CHECK_AND_FILL_FEATURE_OPTIONAL(isAmbig, muon, compatibleCollIds, (muon.compatibleCollIds().size() == 1) ? 0 : 1); } return inputFeature; From 653b637d524f993e3b3090b2feb93600621d662f Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 5 Jun 2026 13:13:16 +0200 Subject: [PATCH 427/449] [PWGEM/Dilepton] cleanup unnecessary lines (#16539) --- PWGEM/Dilepton/Core/DielectronCut.cxx | 44 +++++---------- PWGEM/Dilepton/Core/DielectronCut.h | 56 ++++++-------------- PWGEM/Dilepton/Core/Dilepton.h | 2 + PWGEM/Dilepton/Core/DileptonHadronMPC.h | 2 +- PWGEM/Dilepton/Core/DileptonMC.h | 2 + PWGEM/Dilepton/Core/SingleTrackQC.h | 3 ++ PWGEM/Dilepton/Core/SingleTrackQCMC.h | 3 ++ PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx | 2 +- PWGEM/Dilepton/Tasks/prefilterDielectron.cxx | 2 - 9 files changed, 39 insertions(+), 77 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx index 64d564cf36a..e879828035a 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.cxx +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -79,11 +79,11 @@ void DielectronCut::SetMindEtadPhi(bool flag1, bool flag2, float min_deta, float mMinDeltaPhi = min_dphi; LOG(info) << "Dielectron Cut, set apply deta-dphi cut: " << mApplydEtadPhi << " apply deta-dphi* cut: " << mApplydEtadPhiPosition << " min_deta: " << mMinDeltaEta << " min_dphi: " << mMinDeltaPhi; } -void DielectronCut::SetRequireDifferentSides(bool flag) -{ - mRequireDiffSides = flag; - LOG(info) << "Dielectron Cut, require 2 tracks to be from different sides: " << mRequireDiffSides; -} +// void DielectronCut::SetRequireDifferentSides(bool flag) +// { +// mRequireDiffSides = flag; +// LOG(info) << "Dielectron Cut, require 2 tracks to be from different sides: " << mRequireDiffSides; +// } void DielectronCut::SetTrackPtRange(float minPt, float maxPt) { mMinTrackPt = minPt; @@ -163,8 +163,6 @@ void DielectronCut::SetMeanClusterSizeITS(float min, float max) { mMinMeanClusterSizeITS = min; mMaxMeanClusterSizeITS = max; - // mMinP_ITSClusterSize = minP; - // mMaxP_ITSClusterSize = maxP; LOG(info) << "Dielectron Cut, set mean cluster size ITS range: " << mMinMeanClusterSizeITS << " - " << mMaxMeanClusterSizeITS; } void DielectronCut::SetChi2TOF(float min, float max) @@ -174,21 +172,22 @@ void DielectronCut::SetChi2TOF(float min, float max) LOG(info) << "Dielectron Cut, set chi2 TOF range: " << mMinChi2TOF << " - " << mMaxChi2TOF; } -void DielectronCut::SetTrackDca3DRange(float min, float max) +void DielectronCut::SetTrackMaxDcaSigma(float max, uint dcaType) { - mMinDca3D = min; - mMaxDca3D = max; - LOG(info) << "Dielectron Cut, set DCA 3D range in sigma: " << mMinDca3D << " - " << mMaxDca3D; + mMaxDcaSigma = max; + mDCAType = dcaType; + LOG(info) << "Dielectron Cut, set max DCA in sigma: " << mMaxDcaSigma; + LOG(info) << "Dielectron Cut, set DCA type: " << mDCAType; } void DielectronCut::SetTrackMaxDcaXY(float maxDcaXY) { mMaxDcaXY = maxDcaXY; - LOG(info) << "Dielectron Cut, set max DCA xy: " << mMaxDcaXY; + LOG(info) << "Dielectron Cut, set max DCA xy in cm: " << mMaxDcaXY; } void DielectronCut::SetTrackMaxDcaZ(float maxDcaZ) { mMaxDcaZ = maxDcaZ; - LOG(info) << "Dielectron Cut, set max DCA z: " << mMaxDcaZ; + LOG(info) << "Dielectron Cut, set max DCA z in cm: " << mMaxDcaZ; } void DielectronCut::SetTrackMaxDcaXYPtDep(std::function ptDepCut) @@ -201,11 +200,6 @@ void DielectronCut::ApplyPhiV(bool flag) mApplyPhiV = flag; LOG(info) << "Dielectron Cut, apply phiv cut: " << mApplyPhiV; } -void DielectronCut::ApplyPrefilter(bool flag) -{ - mApplyPF = flag; - LOG(info) << "Dielectron Cut, apply prefilter: " << mApplyPF; -} void DielectronCut::SetPIDScheme(int scheme) { @@ -323,20 +317,6 @@ void DielectronCut::SetTOFNsigmaPrRange(float min, float max) // mMaxITSNsigmaPr = max; // LOG(info) << "Dielectron Cut, set ITS n sigma Pr range: " << mMinITSNsigmaPr << " - " << mMaxITSNsigmaPr; // } -// -// void DielectronCut::SetPRangeForITSNsigmaKa(float min, float max) -// { -// mMinP_ITSNsigmaKa = min; -// mMaxP_ITSNsigmaKa = max; -// LOG(info) << "Dielectron Cut, set p range for ITS n sigma Ka: " << mMinP_ITSNsigmaKa << " - " << mMaxP_ITSNsigmaKa; -// } -// -// void DielectronCut::SetPRangeForITSNsigmaPr(float min, float max) -// { -// mMinP_ITSNsigmaPr = min; -// mMaxP_ITSNsigmaPr = max; -// LOG(info) << "Dielectron Cut, set p range for ITS n sigma Pr: " << mMinP_ITSNsigmaPr << " - " << mMaxP_ITSNsigmaPr; -// } void DielectronCut::SetPinRangeForPionRejectionTPC(float min, float max) { diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index feba64b0410..0905c509657 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -66,14 +67,13 @@ class DielectronCut : public TNamed kTPCFracSharedClusters, kRelDiffPin, kTPCChi2NDF, - kDCA3Dsigma, + kDCAsigma, kDCAxy, kDCAz, kITSNCls, kITSChi2NDF, kITSClusterSize, kTTCA, - kPrefilter, kNCuts }; @@ -144,9 +144,9 @@ class DielectronCut : public TNamed return false; } - if (mRequireDiffSides && t1.eta() * t2.eta() > 0.0) { - return false; - } + // if (mRequireDiffSides && t1.eta() * t2.eta() > 0.0) { + // return false; + // } if (mApplydEtadPhi && mApplydEtadPhiPosition) { // applying both cuts is not allowed. return false; @@ -195,7 +195,7 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kTrackPhiPositionRange)) { return false; } - if (!IsSelectedTrack(track, DielectronCuts::kDCA3Dsigma)) { + if (!IsSelectedTrack(track, DielectronCuts::kDCAsigma)) { return false; } if (!IsSelectedTrack(track, DielectronCuts::kDCAxy)) { @@ -263,9 +263,6 @@ class DielectronCut : public TNamed return false; } } - if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { - return false; - } // PID cuts if (!PassPID(track)) { @@ -336,8 +333,6 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = (track.tpcInnerParam() > mMinPinForPionRejectionTPC && track.tpcInnerParam() < mMaxPinForPionRejectionTPC) ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) && (track.hasTOF() && track.tofChi2() < mMaxChi2TOF); - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } @@ -347,8 +342,6 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) && (track.hasTOF() && track.tofChi2() < mMaxChi2TOF); - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } @@ -361,8 +354,6 @@ class DielectronCut : public TNamed bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) : true; - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC && is_el_included_TOF; } @@ -370,8 +361,6 @@ class DielectronCut : public TNamed bool PassTPConly(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC; } @@ -383,8 +372,6 @@ class DielectronCut : public TNamed bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC; } @@ -394,8 +381,6 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) : true; - // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } @@ -462,8 +447,8 @@ class DielectronCut : public TNamed case DielectronCuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; - case DielectronCuts::kDCA3Dsigma: - return mMinDca3D < o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) && o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg + case DielectronCuts::kDCAsigma: + return (std::array{std::fabs(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track)), std::fabs(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(track)), std::fabs(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(track))}[mDCAType]) < mMaxDcaSigma; case DielectronCuts::kDCAxy: return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); @@ -483,9 +468,6 @@ class DielectronCut : public TNamed case DielectronCuts::kTTCA: return mEnableTTCA ? true : track.isAssociatedToMPC(); - case DielectronCuts::kPrefilter: - return track.pfb() <= 0; - default: return false; } @@ -500,7 +482,7 @@ class DielectronCut : public TNamed void SetMaxMeePhiVDep(std::function phivDepCut, float min_phiv, float max_phiv); void SelectPhotonConversion(bool flag); void SetMindEtadPhi(bool applydEtadPhi, bool applydEtadPhiPosition, float min_deta, float min_dphi); - void SetRequireDifferentSides(bool flag); + // void SetRequireDifferentSides(bool flag); void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); @@ -537,18 +519,14 @@ class DielectronCut : public TNamed // void SetITSNsigmaKaRange(float min, float max); // void SetITSNsigmaPrRange(float min, float max); - // void SetPRangeForITSNsigmaKa(float min, float max); - // void SetPRangeForITSNsigmaPr(float min, float max); - void SetPinRangeForPionRejectionTPC(float min, float max); void RequireITSibAny(bool flag); void RequireITSib1st(bool flag); - void SetTrackDca3DRange(float min, float max); // in sigma - void SetTrackMaxDcaXY(float maxDcaXY); // in cm - void SetTrackMaxDcaZ(float maxDcaZ); // in cm + void SetTrackMaxDcaSigma(float max, uint dcaType); // in sigma + void SetTrackMaxDcaXY(float maxDcaXY); // in cm + void SetTrackMaxDcaZ(float maxDcaZ); // in cm void SetTrackMaxDcaXYPtDep(std::function ptDepCut); - void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); void IncludeITSsa(bool flag, float maxpt); void EnableTTCA(bool flag); @@ -589,7 +567,7 @@ class DielectronCut : public TNamed float mMinDeltaEta{0.f}; float mMinDeltaPhi{0.f}; float mMinOpAng{0.f}, mMaxOpAng{1e10f}; - bool mRequireDiffSides{false}; // flag to require 2 tracks to be from different sides. (A-C combination). If one wants 2 tracks to be in the same side (A-A or C-C), one can simply use track eta cut. + // bool mRequireDiffSides{false}; // flag to require 2 tracks to be from different sides. (A-C combination). If one wants 2 tracks to be in the same side (A-A or C-C), one can simply use track eta cut. // kinematic cuts float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT @@ -614,15 +592,13 @@ class DielectronCut : public TNamed bool mRequireITSib1st{false}; float mMinChi2TOF{-1e10f}, mMaxChi2TOF{1e10f}; // max tof chi2 per - float mMinDca3D{0.0f}; // min dca in 3D in units of sigma - float mMaxDca3D{1e+10}; // max dca in 3D in units of sigma + uint mDCAType{0}; // 0:3D, 1:XY, 2:Z, else:3D + float mMaxDcaSigma{1e+10}; // max dca in units of sigma float mMaxDcaXY{1.0f}; // max dca in xy plane float mMaxDcaZ{1.0f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; - bool mApplyPF{false}; float mMinMeanClusterSizeITS{0.0}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) - // float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; bool mIncludeITSsa{false}; float mMaxPtITSsa{1e+10}; @@ -649,8 +625,6 @@ class DielectronCut : public TNamed // float mMinITSNsigmaPi{-1e+10}, mMaxITSNsigmaPi{+1e+10}; // float mMinITSNsigmaKa{-1e+10}, mMaxITSNsigmaKa{+1e+10}; // float mMinITSNsigmaPr{-1e+10}, mMaxITSNsigmaPr{+1e+10}; - // float mMinP_ITSNsigmaKa{0.0}, mMaxP_ITSNsigmaKa{0.0}; - // float mMinP_ITSNsigmaPr{0.0}, mMaxP_ITSNsigmaPr{0.0}; // o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; std::vector mMLBins{}; // binning for a feature variable. e.g. tpcInnerParam diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index e5aa7fbfe02..ee453f77b4e 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -234,6 +234,7 @@ struct Dilepton { o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca_sigma{"cfg_max_dca_sigma", 1e+10, "max dca for single track in sigma"}; o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -783,6 +784,7 @@ struct Dilepton { fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaSigma(dielectroncuts.cfg_max_dca_sigma, cfgDCAType); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 8fd7755e18f..45b258aa033 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -628,7 +628,7 @@ struct DileptonHadronMPC { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, dielectroncuts.cfg_apply_detadphiposition, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(0.f, 6.3); - fDielectronCut.SetRequireDifferentSides(false); + // fDielectronCut.SetRequireDifferentSides(false); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index a4950ca0233..7503a321ae5 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -229,6 +229,7 @@ struct DileptonMC { o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca_sigma{"cfg_max_dca_sigma", 1e+10, "max dca for single track in sigma"}; o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -752,6 +753,7 @@ struct DileptonMC { fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaSigma(dielectroncuts.cfg_max_dca_sigma, cfgDCAType); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 32b1d5fec41..41c33a83918 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -155,6 +155,8 @@ struct SingleTrackQC { o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca_sigma{"cfg_max_dca_sigma", 1e+10, "max dca for single track in sigma"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA. 0:3D, 1:XY, 2:Z, else:3D"}; o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -486,6 +488,7 @@ struct SingleTrackQC { fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaSigma(dielectroncuts.cfg_max_dca_sigma, dielectroncuts.cfgDCAType); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 746cc1eb84e..dcbe9ddcccc 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -164,6 +164,8 @@ struct SingleTrackQCMC { o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca_sigma{"cfg_max_dca_sigma", 1e+10, "max dca for single track in sigma"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA. 0:3D, 1:XY, 2:Z, else:3D"}; o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -533,6 +535,7 @@ struct SingleTrackQCMC { fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaSigma(dielectroncuts.cfg_max_dca_sigma, dielectroncuts.cfgDCAType); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx index bbd9f9b77f6..641fbe69bbf 100644 --- a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -849,7 +849,7 @@ struct checkMCPairTemplate { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index b35ef08c80f..b8076747676 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -279,10 +279,8 @@ struct prefilterDielectron { fDielectronCut.SetPairYRange(-1e+10, +1e+10); fDielectronCut.SetPairDCARange(0.f, 1e+10); // in sigma fDielectronCut.ApplyPhiV(false); - fDielectronCut.ApplyPrefilter(false); fDielectronCut.SetMindEtadPhi(false, false, 1.f, 1.f); fDielectronCut.SetPairOpAng(0.f, 3.2f); - fDielectronCut.SetRequireDifferentSides(false); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); From 6884cb037b65f0cd63188ae7d48775dc03cf0300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E6=99=93=E5=AE=87=28Xiaoyu=20Hu=29?= <13971168438@163.com> Date: Fri, 5 Jun 2026 21:16:16 +0800 Subject: [PATCH 428/449] [PWGDQ] Add track-rotation option for dielectron pair filling (#16473) Co-authored-by: ayatsuji <13807650+asakuratou@user.noreply.gitee.com> --- PWGDQ/Core/VarManager.h | 64 ++++++++++++++++++++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 77 ++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index d2de7e5e44c..6ab59d62135 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1389,6 +1389,8 @@ class VarManager : public TObject static void FillGlobalMuonRefitCov(T1 const& muontrack, T2 const& mfttrack, const C& collision, C2 const& mftcov, float* values = nullptr); template static void FillPair(T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillPairRotation(T1 const& t1, T2 const& t2, float* values = nullptr); template static void FillPairCollision(C const& collision, T1 const& t1, T2 const& t2, float* values = nullptr); template @@ -3787,6 +3789,68 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) } } +// change_start: rotation pair +template +void VarManager::FillPairRotation(T1 const& t1, T2 const& t2, float* values) +{ + if (!values) { + values = fgValues; + } + + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + if constexpr (pairType == kDecayToMuMu) { + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; + } + + if constexpr (pairType == kDecayToPiPi) { + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; + } + + if constexpr (pairType == kDecayToKPi) { + m1 = o2::constants::physics::MassKaonCharged; + m2 = o2::constants::physics::MassPionCharged; + // Make the TPC information of the kaon available for pair histograms + values[kPin_leg1] = t1.tpcInnerParam(); + values[kTPCnSigmaKa_leg1] = t1.tpcNSigmaKa(); + } + + if constexpr (pairType == kElectronMuon) { + m2 = o2::constants::physics::MassMuon; + } + + double dphi = gRandom->Uniform(0., 2. * TMath::Pi()); + double rotationphi2 = t2.phi() + dphi; + + if (rotationphi2 > 2. * TMath::Pi()) + rotationphi2 -= 2. * TMath::Pi(); + + values[kCharge] = t1.sign() + t2.sign(); + values[kCharge1] = t1.sign(); + values[kCharge2] = t2.sign(); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), rotationphi2, m2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + // values[kPhi] = v12.Phi(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; + values[kRap] = -v12.Rapidity(); + double Ptot1 = TMath::Sqrt(v1.Px() * v1.Px() + v1.Py() * v1.Py() + v1.Pz() * v1.Pz()); + double Ptot2 = TMath::Sqrt(v2.Px() * v2.Px() + v2.Py() * v2.Py() + v2.Pz() * v2.Pz()); + values[kDeltaPtotTracks] = Ptot1 - Ptot2; + + values[kPt1] = t1.pt(); + values[kEta1] = t1.eta(); + values[kPhi1] = t1.phi(); + values[kPt2] = t2.pt(); + values[kEta2] = t2.eta(); + values[kPhi2] = rotationphi2; +} + template void VarManager::FillPairCollision(const C& collision, T1 const& t1, T2 const& t2, float* values) { diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 0b916cef236..38e6a67c83a 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1322,6 +1322,10 @@ struct AnalysisSameEventPairing { Configurable fConfigQA{"cfgQA", true, "If true, fill output histograms"}; Configurable fConfigAmbiguousMuonHistograms{"cfgAmbiguousMuonHistograms", true, "If true, fill ambiguous histograms"}; + // option for TR pair fill + Configurable fConfigTRPairs{"cfgFillTRPairs", false, "If true, fill Track rotation pairs"}; + Configurable fConfigNRotations{"cfgNRotations", 20, "Number of rotations for track rotation method"}; + struct : ConfigurableGroup { Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -1515,6 +1519,7 @@ struct AnalysisSameEventPairing { if (fEnableBarrelHistos) { names = { + // change define histname Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; @@ -1523,11 +1528,16 @@ struct AnalysisSameEventPairing { names.push_back(Form("PairsBarrelSEPP_ambiguousextra_%s", objArray->At(icut)->GetName())); names.push_back(Form("PairsBarrelSEMM_ambiguousextra_%s", objArray->At(icut)->GetName())); histNames += Form("%s;%s;%s;", names[3].Data(), names[4].Data(), names[5].Data()); + if (fConfigTRPairs) { + names.push_back(Form("PairsBarrelTRPM_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsBarrelTRPM_ambiguousextra_%s", objArray->At(icut)->GetName())); + histNames += Form("%s;%s;", names[6].Data(), names[7].Data()); + } if (fEnableBarrelMixingHistos) { names.push_back(Form("PairsBarrelMEPM_%s", objArray->At(icut)->GetName())); names.push_back(Form("PairsBarrelMEPP_%s", objArray->At(icut)->GetName())); names.push_back(Form("PairsBarrelMEMM_%s", objArray->At(icut)->GetName())); - histNames += Form("%s;%s;%s;", names[6].Data(), names[7].Data(), names[8].Data()); + histNames += Form("%s;%s;%s;", names[(fConfigTRPairs ? 8 : 6)].Data(), names[(fConfigTRPairs ? 9 : 7)].Data(), names[(fConfigTRPairs ? 10 : 8)].Data()); } fTrackHistNames[icut] = names; @@ -2208,6 +2218,71 @@ struct AnalysisSameEventPairing { } // end loop (pair cuts) } } // end loop (cuts) + + // edit + // rotation 20 times + if (fConfigTRPairs) { + if constexpr (TPairType == VarManager::kDecayToEE) { + twoTrackFilter = a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & a2.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; + + if (!twoTrackFilter) { // the tracks must have at least one filter bit in common to continue + continue; + } + + auto t1 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedtrack_as(); + sign1 = t1.sign(); + sign2 = t2.sign(); + if (t1.barrelAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 28); + } + if (t2.barrelAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 29); + } + if (t1.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 30); + } + if (t2.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 31); + } + + for (int icut = 0; icut < ncuts; icut++) { + if (twoTrackFilter & (static_cast(1) << icut)) { + isAmbiInBunch = (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)); + isAmbiOutOfBunch = (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)); + isUnambiguous = !(isAmbiInBunch || isAmbiOutOfBunch); + isLeg1Ambi = (twoTrackFilter & (static_cast(1) << 28) || (twoTrackFilter & (static_cast(1) << 30))); + isLeg2Ambi = (twoTrackFilter & (static_cast(1) << 29) || (twoTrackFilter & (static_cast(1) << 31))); + if constexpr (TPairType == VarManager::kDecayToEE) { + if (isLeg1Ambi && isLeg2Ambi) { + std::pair iPair(a1.reducedtrackId(), a2.reducedtrackId()); + if (fAmbiguousPairs.find(iPair) != fAmbiguousPairs.end()) { + if (fAmbiguousPairs[iPair] & (static_cast(1) << icut)) { // if this pair is already stored with this cut + isAmbiExtra = true; + } else { + fAmbiguousPairs[iPair] |= static_cast(1) << icut; + } + } else { + fAmbiguousPairs[iPair] = static_cast(1) << icut; + } + } + } + if (sign1 * sign2 < 0) { + for (int i = 0; i < fConfigNRotations.value; i++) { + VarManager::FillPairRotation(t1, t2); + if constexpr (TPairType == VarManager::kDecayToEE) { + fHistMan->FillHistClass(Form("PairsBarrelTRPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + if (isAmbiExtra) { + fHistMan->FillHistClass(Form("PairsBarrelTRPM_ambiguousextra_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + } + } + } + } + } + // end } // end loop over pairs of track associations VarManager::fgValues[VarManager::kNPairsPerEvent] = fNPairPerEvent; if (fEnableBarrelHistos && fConfigQA) { From 9d0340255399fb1ea65d845cf61df9a1f8065af4 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Fri, 5 Jun 2026 19:13:53 +0200 Subject: [PATCH 429/449] [PWGLF] Add process function in straevselextrasconverter.cxx (#16542) Co-authored-by: ALICE Builder --- .../Converters/straevselextrasconverter.cxx | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx index 27e7d930ebc..d182e385506 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselextrasconverter.cxx @@ -8,26 +8,43 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +// +/// \file straevselextrasconverter.cxx +/// \brief Converts straevselsextrasconverter1 converts StraEvSelExtras_000 into StraEvSelExtras_001 +/// +/// \author David Dobrigkeit Chinellato , Austrian Academy of Sciences & MBI +/// \author Romain Schotter , Austrian Academy of Sciences & MBI +// +//__________________________________________________ +// #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::aod::evsel; -// Converts straevselsextrasconverter1 converts StraEvSelExtras_000 into StraEvSelExtras_001 struct straevselextrasconverter { Produces straEvSelExtras_001; - void process(soa::Join const& straEvSels_005) + void init(InitContext&) + { + LOGF(info, "Initializing now: cross-checking correctness..."); + if (doprocessAll + doprocessStraEvSelsOnly > 1) { + LOGF(fatal, "You have enabled more than one process function. Please check your configuration! Aborting now."); + } + } + + void processAll(soa::Join const& straEvSels_005) { - for (auto& values : straEvSels_005) { + straEvSelExtras_001.reserve(straEvSels_005.size()); + for (const auto& values : straEvSels_005) { straEvSelExtras_001(values.multZNA(), values.multZNC(), values.multZEM1(), @@ -57,6 +74,42 @@ struct straevselextrasconverter { values.energyCommonZNC()); } } + + void processStraEvSelsOnly(aod::StraEvSels_005 const& straEvSels_005) + { + straEvSelExtras_001.reserve(straEvSels_005.size()); + for (const auto& values : straEvSels_005) { + straEvSelExtras_001(values.multZNA(), + values.multZNC(), + values.multZEM1(), + values.multZEM2(), + values.multZPA(), + values.multZPC(), + values.multNTracksITSTPC(), + values.multAllTracksTPCOnly(), + values.multAllTracksITSTPC(), + values.trackOccupancyInTimeRange(), + values.ft0cOccupancyInTimeRange(), + -999., // dummy timeFDDA, + -999., // dummy timeFDDC, + -999., // dummy timeFV0A, + -999., // dummy timeFT0A, + -999., // dummy timeFT0C, + 0, // dummy triggerMaskFT0, + values.gapSide(), + values.totalFT0AmplitudeA(), + values.totalFT0AmplitudeC(), + values.totalFV0AmplitudeA(), + values.totalFDDAmplitudeA(), + values.totalFDDAmplitudeC(), + -999., // dummy timeZNA, + -999., // dummy timeZNC, + values.energyCommonZNA(), + values.energyCommonZNC()); + } + } + PROCESS_SWITCH(straevselextrasconverter, processAll, "Store StraEvSels005 and StraEvSelExtras000 into StraEvSelExtras001", true); + PROCESS_SWITCH(straevselextrasconverter, processStraEvSelsOnly, "Store only StraEvSels005 into StraEvSelExtras001. Other columns are set to dummy values", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 0284e521fa4b6bc7b8c6f2b0b5839f27aa9a5f91 Mon Sep 17 00:00:00 2001 From: yongzhen <58928668+yhou-git@users.noreply.github.com> Date: Fri, 5 Jun 2026 19:14:38 +0200 Subject: [PATCH 430/449] [PWGJE] Add leading hadron-jet process in chargedJetHadron.cxx (#16537) --- PWGJE/Tasks/chargedJetHadron.cxx | 538 +++++++++++-------------------- 1 file changed, 186 insertions(+), 352 deletions(-) diff --git a/PWGJE/Tasks/chargedJetHadron.cxx b/PWGJE/Tasks/chargedJetHadron.cxx index f08f17b1433..16a3e75e5d3 100644 --- a/PWGJE/Tasks/chargedJetHadron.cxx +++ b/PWGJE/Tasks/chargedJetHadron.cxx @@ -55,6 +55,7 @@ struct ChargedJetHadron { Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", 0.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 100.0, "maximum centrality"}; + Configurable triggerHadronPtMin{"triggerHadronPtMin", 20.0, "minimum trigger hadron pT for h-jet control"}; Configurable leadingjetptMin{"leadingjetptMin", 20.0, "minimum leadingjetpt"}; Configurable subleadingjetptMin{"subleadingjetptMin", 10.0, "minimum subleadingjetpt"}; Configurable dijetDphiCut{"dijetDphiCut", 0.5, "minimum dijetDphiCut"}; @@ -102,8 +103,10 @@ struct ChargedJetHadron { SliceCache cache; using FilterCollisions = soa::Filtered>; using FilterCollision = soa::Filtered>::iterator; - using FilterMcpCollision = soa::Filtered>::iterator; + using FilterMcdCollisions = soa::Filtered>; + using FilterMcdCollision = soa::Filtered>::iterator; using FilterMcpCollisions = soa::Filtered>; + using FilterMcpCollision = soa::Filtered>::iterator; using FilterJetTracks = soa::Filtered; using CorrChargedJets = soa::Join; using CorrChargedMCDJets = soa::Join; @@ -184,11 +187,13 @@ struct ChargedJetHadron { registry.add("h_jet_phi", "jet phi; #phi_{jet}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area", "jet Area_{jet}; Area_{jet}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks", "jet N_{jet tracks}; N_{jet, tracks}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("h2_jet_pt_track_pt", "jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); registry.add("h_jet_pt_rhoareasubtracted", "jet pt; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_jet_eta_rhoareasubtracted", "jet eta; #eta_{jet}; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_jet_phi_rhoareasubtracted", "jet phi; #phi_{jet}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area_rhoareasubtracted", "jet Area_{jet}; Area_{jet}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks_rhoareasubtracted", "jet N_{jet tracks}; N_{jet,tracks}; counts", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h2_jet_pt_track_pt_rhoareasubtracted", "jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, trackPtAxis}}); } //========jet-hadron correlations====================== @@ -238,6 +243,10 @@ struct ChargedJetHadron { registry.add("h_leadjet_phi", "leading jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_subleadjet_eta", "subleading jet eta;#eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_subleadjet_phi", "subleading jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}); + registry.add("h2_leadjet_corrpt_constituent_pt", "leading jet;#it{p}_{T,jet}^{corr};#it{p}_{T}^{const}", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); + registry.add("h2_subleadjet_corrpt_constituent_pt", "subleading jet;#it{p}_{T,jet}^{corr};#it{p}_{T}^{const}", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); + registry.add("h_leadjet_leadingconstituent_pt", "leading jet leading constituent;#it{p}_{T}^{leading const} (GeV/#it{c});counts", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h_subleadjet_leadingconstituent_pt", "subleading jet leading constituent;#it{p}_{T}^{leading const} (GeV/#it{c});counts", {HistType::kTH1F, {trackPtAxis}}); registry.add("h2_dijet_detanoflip_dphi", "dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); registry.add("h2_dijet_Asymmetry", "dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); registry.add("h3_dijet_deta_pt", "dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #it{p}_{T,jet1} (GeV/#it{c}); #it{p}_{T,jet2} (GeV/#it{c})", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); @@ -256,37 +265,19 @@ struct ChargedJetHadron { registry.add("thn_ljeth_correlations", "leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; #Delta#eta_{jet1,2}; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {8, 0., 8.}, {16, 0, 1.6}, detaAxis, dphiAxis}); } } - - if (doprocessMixLeadingJetHadron || doprocessMixLeadingJetHadronMCD) { - registry.add("h_mixdijet_pair_counts_cut", "ME: number of pairs with leadingjet & subleadingjet cut pair; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); - registry.add("h_mixleadjet_corrpt", "ME: leading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mixsubleadjet_corrpt", "ME: subleading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mixleadjet_eta", "ME: leading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); - registry.add("h_mixsubleadjet_eta", "ME: subleading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); - registry.add("h2_mixdijet_detanoflip_dphi", "ME: dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_mixdijet_Asymmetry", "ME: dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_mixdijet_deta_pt", "ME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); - registry.add("h_mixjeth_detatot", "ME: jeth correlations; no flip #Delta#eta", {HistType::kTH1F, {detaAxis}}); - registry.add("h_mixjeth_deta", "ME: jeth correlations; #Delta#eta", {HistType::kTH1F, {detaAxis}}); - registry.add("h_mixjeth_dphi", "ME: jeth correlations; #Delta#phi", {HistType::kTH1F, {dphiAxis}}); - if (doDijetEta) { - registry.add("h2_mixdijet_TimeEtaThan0_pt", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); - registry.add("h2_mixdijet_TimeEtaLess0_pt", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); - registry.add("h2_mixjeth_heta_dphi", "ME: jeth heta vs dphi; hadron #eta; #Delta#phi", {HistType::kTH2F, {etaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations", "ME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; track #eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {8, 0., 8.}, jetmultetaAxis, etaAxis, dphiAxis}); - } else { - registry.add("h2_mixjeth_physicalcutsup_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsmd_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsdw_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations", "ME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; #Delta#eta_{jet1,2}; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {8, 0., 8.}, {16, 0, 1.6}, detaAxis, dphiAxis}); - } - - registry.add("h_mix_event_stats", "Mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); - registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); - registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(2, "Total dijets"); - registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(3, "Total dijets with cuts"); - registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(4, "Total Lj-h pairs"); - registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(5, "Total Lj-h pairs with cut"); + if (doprocessHadronJetHadron || doprocessHadronJetHadronMCD) { + registry.add("h_hjet_trigtrack_pt", "trigger hadron pT;#it{p}_{T,trig} (GeV/#it{c}); counts", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h_hjet_trigtrack_eta", "trigger hadron #eta;#eta_{trig}; counts", {HistType::kTH1F, {etaAxis}}); + registry.add("h_hjet_trigtrack_phi", "trigger hadron #varphi;#varphi_{trig}; counts", {HistType::kTH1F, {phiAxis}}); + registry.add("h_hjet_recoiljet_corrpt", "recoil jet corrected pT;#it{p}_{T,recoil jet}^{corr} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_hjet_recoiljet_eta", "recoil jet #eta;#eta_{recoil jet}; counts", {HistType::kTH1F, {etaAxis}}); + registry.add("h_hjet_recoiljet_phi", "recoil jet #varphi;#varphi_{recoil jet}; counts", {HistType::kTH1F, {phiAxis}}); + registry.add("h_hjet_dphi", "hjet #Delta#varphi; #Delta#varphi_{hjet}; counts", {HistType::kTH1F, {{63, 0., 6.3}}}); + registry.add("h2_recojet_corrpt_constituent_pt", "recoil jet;#it{p}_{T,jet}^{corr};#it{p}_{T}^{const}", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); + registry.add("h2_hjet_TimeEtaThan0_pt", "h-jet #eta_{trig}#eta_{recoil jet} > 0;#it{p}_{T,trig};#it{p}_{T,recoil jet}^{corr}", {HistType::kTH2F, {trackPtAxis, jetPtAxis}}); + registry.add("h2_hjet_TimeEtaLess0_pt", "h-jet #eta_{trig}#eta_{recoil jet} < 0;#it{p}_{T,trig};#it{p}_{T,recoil jet}^{corr}", {HistType::kTH2F, {trackPtAxis, jetPtAxis}}); + registry.add("h2_hjet_heta_dphi", "hjet heta vs dphi; hadron #eta; #Delta#phi", {HistType::kTH2F, {etaAxis, dphiAxis}}); + registry.add("thn_hjeth_correlations", "h-jet-h correlations; triggerHadronpT; recoilJetpT; trackpT; timehjeteta; track #eta; hh#Delta#varphi", HistType::kTHnSparseF, {trackPtAxis, jetPtAxis, {8, 0., 8.}, jetmultetaAxis, etaAxis, dphiAxis}); } if (doprocessCollisionsQCMCP) { @@ -314,16 +305,19 @@ struct ChargedJetHadron { registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(3, "event weight"); } registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); - registry.add("h_jet_pt_part", "partvjet pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_inclusivejet_corrpt_part", "part inclusive jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_part", "part jet pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); registry.add("h_jet_eta_part", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_jet_phi_part", "part jet #varphi;#phi^{part}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area_part", "part jet Area_{jet}; Area_{jet}^{part}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks_part", "part jet N_{jet tracks}; N_{jet, tracks}^{part}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("h2_jet_pt_part_track_pt_part", "part jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); registry.add("h_jet_pt_part_rhoareasubtracted", "part jet corr pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_jet_eta_part_rhoareasubtracted", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area_part_rhoareasubtracted", "part jet Area_{jet}; Area_{jet}^{part}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks_part_rhoareasubtracted", "part jet N_{jet tracks}; N_{jet, tracks}^{part}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("h2_jet_pt_part_track_pt_part_rhoareasubtracted", "part jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, trackPtAxis}}); } if (doprocessJetHadronMCP || doprocessMixJetHadronMCP) { @@ -377,38 +371,6 @@ struct ChargedJetHadron { } } - if (doprocessMixLeadingJetHadronMCP) { - //...........mcp mixed events: leading jet correlations................. - registry.add("h_mixdijet_pair_counts_cut_part", "mcpME: number of pairs with leadingjet & subleadingjet cut pair; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); - registry.add("h_mixleadjet_corrpt_part", "mcpME: leading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mixsubleadjet_corrpt_part", "mcpME: subleading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mixleadjet_eta_part", "mcpME: leading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); - registry.add("h_mixsubleadjet_eta_part", "mcpME: subleading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); - registry.add("h2_mixdijet_detanoflip_dphi_part", "mcpME: dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_mixdijet_Asymmetry_part", "mcpME: dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_mixdijet_deta_pt_part", "mcpME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); - registry.add("h_mixjeth_detatot_part", "mcpME: jeth correlations; no flip #Delta#eta", {HistType::kTH1F, {detaAxis}}); - registry.add("h_mixjeth_deta_part", "mcpME: jeth correlations; #Delta#eta", {HistType::kTH1F, {detaAxis}}); - registry.add("h_mixjeth_dphi_part", "mcpME: jeth correlations; #Delta#phi", {HistType::kTH1F, {dphiAxis}}); - if (doDijetEta) { - registry.add("h2_mixdijet_TimeEtaThan0_pt_part", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); - registry.add("h2_mixdijet_TimeEtaLess0_pt_part", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); - registry.add("h2_mixjeth_heta_dphi_part", "mcpME: jeth heta vs dphi; hadron #eta; #Delta#phi", {HistType::kTH2F, {etaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations_part", "mcpME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; track #eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {8, 0., 8.}, jetmultetaAxis, etaAxis, dphiAxis}); - } else { - registry.add("h2_mixjeth_physicalcutsup_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsmd_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsdw_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations_part", "mcpME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; #Delta#eta_{jet1,2}; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {8, 0., 8.}, {16, 0, 1.6}, detaAxis, dphiAxis}); - } - - registry.add("h_mixevent_stats_part", "MCP: mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); - registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); - registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(2, "Total dijets"); - registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(3, "Total dijets with cuts"); - registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(4, "Total Lj-h pairs"); - registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(5, "Total Lj-h pairs with cut"); - } if (!(acceptSplitCollisions == NonSplitOnly || acceptSplitCollisions == SplitOkCheckAnyAssocColl || acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly)) { LOGF(fatal, "Configurable acceptSplitCollisions has wrong input value; stopping workflow"); } @@ -533,9 +495,9 @@ struct ChargedJetHadron { } // ========================================================== template - void fillTrackHistograms(TTracks const& track, float weight = 1.0) + void fillTrackHistograms(TTracks const& track, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + // float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (track.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) return; if (doEventWeighted) { @@ -548,9 +510,8 @@ struct ChargedJetHadron { } template - void fillJetHistograms(TJets const& jet, float weight = 1.0) + void fillJetHistograms(TJets const& jet, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) return; if (jet.r() == round(selectedJetsRadius * 100.0f)) { @@ -560,12 +521,14 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_area"), jet.area(), weight); registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size(), weight); } + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); + } } template - void fillJetAreaSubHistograms(TJets const& jet, float rho, float weight = 1.0) + void fillJetAreaSubHistograms(TJets const& jet, float rho, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) return; double jetcorrpt = jet.pt() - (rho * jet.area()); @@ -578,12 +541,14 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_ntracks_rhoareasubtracted"), jet.tracksIds().size(), weight); } } + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_track_pt_rhoareasubtracted"), jetcorrpt, constituent.pt(), weight); + } } template - void fillParticleHistograms(const TParticles& particle, float weight = 1.0) + void fillParticleHistograms(const TParticles& particle, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (particle.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) return; registry.fill(HIST("h2_particle_eta_phi"), particle.eta(), particle.phi(), weight); @@ -592,9 +557,8 @@ struct ChargedJetHadron { } template - void fillMCPHistograms(TJets const& jet, float weight = 1.0) + void fillMCPHistograms(TJets const& jet, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) return; if (jet.r() == round(selectedJetsRadius * 100.0f)) { @@ -604,16 +568,18 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_area_part"), jet.area(), weight); registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size(), weight); } + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); + } } template - void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0) + void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) return; + double jetcorrpt = jet.pt() - (rho * jet.area()); if (jet.r() == round(selectedJetsRadius * 100.0f)) { - double jetcorrpt = jet.pt() - (rho * jet.area()); registry.fill(HIST("h_jet_pt_part_rhoareasubtracted"), jetcorrpt, weight); if (jetcorrpt > 0) { registry.fill(HIST("h_jet_eta_part_rhoareasubtracted"), jet.eta(), weight); @@ -622,15 +588,17 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_ntracks_part_rhoareasubtracted"), jet.tracksIds().size(), weight); } } + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_part_track_pt_part_rhoareasubtracted"), jetcorrpt, constituent.pt(), weight); + } } // ========================================================== //..........jet - hadron correlations........................ // ========================================================== template - void fillJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0) + void fillJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); using TracksTable = std::decay_t; for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -706,9 +674,8 @@ struct ChargedJetHadron { //........MCP..jet - hadron correlations.......................................... template - void fillMCPJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0) + void fillMCPJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); using ParticlesTable = std::decay_t; for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -781,17 +748,18 @@ struct ChargedJetHadron { //..........leading jet - hadron correlations................ // ========================================================== template - void fillLeadingJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0) + void fillLeadingJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); using TracksTable = std::decay_t; registry.fill(HIST("h_centrality"), getCentrality(collision)); typename TJets::iterator leadingJet; typename TJets::iterator subleadingJet; bool hasLeading = false; bool hasSubleading = false; - double ptLeadingCorr = -1.0; - double ptSubleadingCorr = -1.0; + double ptLeadingCorr = -999.0; + double ptSubleadingCorr = -999.0; + float leadingJetLeadingConstPt = 0.0; + float subleadingJetLeadingConstPt = 0.0; for (auto it = jets.begin(); it != jets.end(); ++it) { const auto& jet = *it; @@ -856,6 +824,19 @@ struct ChargedJetHadron { else if (doDijetEta && multEta1Eta2 < 0) registry.fill(HIST("h2_dijet_TimeEtaLess0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); + for (const auto& constituent : leadingJet.template tracks_as()) { + registry.fill(HIST("h2_leadjet_corrpt_constituent_pt"), ptLeadingCorr, constituent.pt(), weight); + if (constituent.pt() > leadingJetLeadingConstPt) + leadingJetLeadingConstPt = constituent.pt(); + } + for (const auto& constituent : subleadingJet.template tracks_as()) { + registry.fill(HIST("h2_subleadjet_corrpt_constituent_pt"), ptSubleadingCorr, constituent.pt(), weight); + if (constituent.pt() > subleadingJetLeadingConstPt) + subleadingJetLeadingConstPt = constituent.pt(); + } + registry.fill(HIST("h_leadjet_leadingconstituent_pt"), leadingJetLeadingConstPt, weight); + registry.fill(HIST("h_subleadjet_leadingconstituent_pt"), subleadingJetLeadingConstPt, weight); + for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; @@ -889,138 +870,17 @@ struct ChargedJetHadron { } } - //.......mixed events leadingjet-hadrons......................... - template - void fillMixLeadingJetHadronHistograms(const TCollisions& collisions, const TJets& jets, const TTracks& tracks, float weight = 1.0) - { - using TracksTable = std::decay_t; - auto tracksTuple = std::make_tuple(jets, tracks); - Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; - for (const auto& [c1, jets1, c2, tracks2] : pairData) { - weight = doEventWeighted ? c1.weight() : 1.f; - const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); - registry.fill(HIST("h_mix_event_stats"), 1); - // int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), getCentrality(c2))); - if (!isGoodCollision(c1) || !isGoodCollision(c2)) - continue; - - typename TJets::iterator leadingJet; - typename TJets::iterator subleadingJet; - bool hasLeading = false; - bool hasSubleading = false; - double ptLeadingCorr = -1.0; - double ptSubleadingCorr = -1.0; - - for (auto it = jets1.begin(); it != jets1.end(); ++it) { - const auto& jet = *it; - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) - continue; - if (!isAcceptedJet(jet)) - continue; - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) - continue; - - double ptCorr = jet.pt() - jet.area() * c1.rho(); - if (ptCorr > ptLeadingCorr) { - if (hasLeading) { - subleadingJet = leadingJet; - ptSubleadingCorr = ptLeadingCorr; - hasSubleading = true; - } - leadingJet = it; - ptLeadingCorr = ptCorr; - hasLeading = true; - } else if (ptCorr > ptSubleadingCorr) { - subleadingJet = it; - ptSubleadingCorr = ptCorr; - hasSubleading = true; - } - } - if (!hasLeading || !hasSubleading) - continue; - - double phiLead = leadingJet.phi(); - double phiSub = subleadingJet.phi(); - double deltaPhiJets = phiLead - phiSub; - deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, -PIHalf); - if (std::abs(deltaPhiJets) < dijetDphiCut * PI) - continue; - - registry.fill(HIST("h_mix_event_stats"), 2); - double etaJet1Raw = leadingJet.eta(); - double etaJet2Raw = subleadingJet.eta(); - double multEta1Eta2 = etaJet1Raw * etaJet2Raw; - double flip = (etaJet1Raw > etaJet2Raw) ? 1.0 : -1.0; - double inverse = (etaJet1Raw > 0) ? 1.0 : -1.0; // Dr.Yang suggestion - double etajet1 = flip * etaJet1Raw; - double etajet2 = flip * etaJet2Raw; - double deltaEtaJetsNoflip = etaJet1Raw - etaJet2Raw; - double deltaEtaJets = etajet1 - etajet2; - registry.fill(HIST("h_mixleadjet_corrpt"), ptLeadingCorr, weight); - registry.fill(HIST("h_mixsubleadjet_corrpt"), ptSubleadingCorr, weight); - - if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) - continue; - registry.fill(HIST("h_mix_event_stats"), 3); - registry.fill(HIST("h_mixdijet_pair_counts_cut"), 2); - registry.fill(HIST("h_mixleadjet_eta"), etaJet1Raw, weight); - registry.fill(HIST("h_mixsubleadjet_eta"), etaJet2Raw, weight); - registry.fill(HIST("h2_mixdijet_detanoflip_dphi"), deltaEtaJetsNoflip, deltaPhiJets, weight); - registry.fill(HIST("h2_mixdijet_Asymmetry"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); - registry.fill(HIST("h3_mixdijet_deta_pt"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); - if (doDijetEta && multEta1Eta2 > 0) - registry.fill(HIST("h2_mixdijet_TimeEtaThan0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); - else if (doDijetEta && multEta1Eta2 < 0) - registry.fill(HIST("h2_mixdijet_TimeEtaLess0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); - - for (auto const& track : tracks2) { - registry.fill(HIST("h_mix_event_stats"), 4); - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) - continue; - registry.fill(HIST("h_mix_event_stats"), 5); - double hpt = track.pt(); - double heta = inverse * (track.eta()); // Dr.Yang - double detatot = track.eta() - etaJet1Raw; - double deta = flip * (track.eta() - etajet1); - double dphi = track.phi() - phiLead; - dphi = RecoDecay::constrainAngle(dphi, -PIHalf); - - if (hpt > assoHadronPtMaxCut) - continue; - registry.fill(HIST("h_mixjeth_detatot"), detatot, weight); - registry.fill(HIST("h_mixjeth_deta"), deta, weight); - registry.fill(HIST("h_mixjeth_dphi"), dphi, weight); - if (doDijetEta) { - registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, heta, dphi, weight); - if (hpt >= assoHadronPtMin && hpt < assoHadronPtMax && multEta1Eta2 > 0) - registry.fill(HIST("h2_mixjeth_heta_dphi"), heta, dphi, weight); - } else { - registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, deltaEtaJets, deta, dphi, weight); - if (hpt >= assoHadronPtMin && hpt < assoHadronPtMax) { - if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi"), deta, dphi, weight); - if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi"), deta, dphi, weight); - if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi"), deta, dphi, weight); - } - } - } - } - } - //........MCP..leading jet - hadron correlations..................... template - void fillMCPLeadingJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0) + void fillMCPLeadingJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); using ParticlesTable = std::decay_t; typename TJets::iterator leadingJet; typename TJets::iterator subleadingJet; bool hasLeading = false; bool hasSubleading = false; - double ptLeadingCorr = -1.0; - double ptSubleadingCorr = -1.0; + double ptLeadingCorr = -999.0; + double ptSubleadingCorr = -999.0; for (auto it = jets.begin(); it != jets.end(); ++it) { const auto& jet = *it; @@ -1032,6 +892,7 @@ struct ChargedJetHadron { return; double ptCorr = jet.pt() - jet.area() * mccollision.rho(); + registry.fill(HIST("h_inclusivejet_corrpt_part"), ptCorr, weight); if (ptCorr > ptLeadingCorr) { if (hasLeading) { subleadingJet = leadingJet; @@ -1111,121 +972,104 @@ struct ChargedJetHadron { } } - //..........MCP..mixed events......................................... - template - void fillMCPMixLeadingJetHadronHistograms(const TmcCollisions& mccollisions, const TCollisions& collisions, const TJets& jets, const TParticles& particles, float weight = 1.0) + // ========================================================== + //..........hadron-triggered recoil-jet - hadron correlations. + //..........suggestion test: replace Jet1 by trigger track. + // ========================================================== + template + void fillHadronJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0) { - using ParticlesTable = std::decay_t; - auto particlesTuple = std::make_tuple(jets, particles); - Pair pairMCData{corrBinningMC, numberEventsMixed, -1, mccollisions, particlesTuple, &cache}; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + using TracksTable = std::decay_t; - for (const auto& [c1, jets1, c2, particles2] : pairMCData) { - weight = doEventWeighted ? c1.weight() : 1.f; - const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); - registry.fill(HIST("h_mixevent_stats_part"), 1); - // int poolBin = corrBinningMC.getBin(std::make_tuple(c2.posZ(), getMultiplicity(c2))); - if (!applyMCCollisionCuts(c1, collisions) || !applyMCCollisionCuts(c2, collisions)) + // ----- Step 1: find leading trigger track, not leading jet ----- + typename TTracks::iterator triggerTrack; + bool hasTriggerTrack = false; + double ptTrig = -1.0; + for (auto it = tracks.begin(); it != tracks.end(); ++it) { + const auto& track = *it; + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; + if (track.pt() < triggerHadronPtMin) + continue; + if (track.pt() > ptTrig) { + triggerTrack = it; + ptTrig = track.pt(); + hasTriggerTrack = true; + } + } + if (!hasTriggerTrack) + return; + double etaTrigRaw = triggerTrack.eta(); + double phiTrig = triggerTrack.phi(); - typename TJets::iterator leadingJet; - typename TJets::iterator subleadingJet; - bool hasLeading = false; - bool hasSubleading = false; - double ptLeadingCorr = -1.0; - double ptSubleadingCorr = -1.0; - - for (auto it = jets1.begin(); it != jets1.end(); ++it) { - const auto& jet = *it; - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) - continue; - if (!isAcceptedJet(jet, true)) - continue; - if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) - return; + // ----- Step 2: find away-side recoil jet relative to trigger track ----- + typename TJets::iterator recoilJet; + bool hasRecoilJet = false; + double ptRecoilCorr = -999.0; - double ptCorr = jet.pt() - jet.area() * c1.rho(); - if (ptCorr > ptLeadingCorr) { - if (hasLeading) { - subleadingJet = leadingJet; - ptSubleadingCorr = ptLeadingCorr; - hasSubleading = true; - } - leadingJet = it; - ptLeadingCorr = ptCorr; - hasLeading = true; - } else if (ptCorr > ptSubleadingCorr) { - subleadingJet = it; - ptSubleadingCorr = ptCorr; - hasSubleading = true; - } - } - if (!hasLeading || !hasSubleading) + for (auto it = jets.begin(); it != jets.end(); ++it) { + const auto& jet = *it; + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - - double deltaPhiJets = leadingJet.phi() - subleadingJet.phi(); - deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, -PIHalf); - if (std::abs(deltaPhiJets) < dijetDphiCut * PI) + if (!isAcceptedJet(jet)) + continue; + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) continue; - registry.fill(HIST("h_mixevent_stats_part"), 2); - - double etaJet1Raw = leadingJet.eta(); - double etaJet2Raw = subleadingJet.eta(); - double multEta1Eta2 = etaJet1Raw * etaJet2Raw; - double deltaEtaJetsNoflip = etaJet1Raw - etaJet2Raw; - double inverse = (etaJet1Raw > 0) ? 1.0 : -1.0; // Dr.Yang suggestion - double flip = (etaJet1Raw > etaJet2Raw) ? 1.0 : -1.0; - double etajet1 = flip * etaJet1Raw; - double etajet2 = flip * etaJet2Raw; - double deltaEtaJets = etajet1 - etajet2; - registry.fill(HIST("h_mixleadjet_corrpt_part"), ptLeadingCorr, weight); - registry.fill(HIST("h_mixsubleadjet_corrpt_part"), ptSubleadingCorr, weight); - - if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) - return; - registry.fill(HIST("h_mixevent_stats_part"), 3); - registry.fill(HIST("h_mixdijet_pair_counts_cut_part"), 1); - registry.fill(HIST("h_mixleadjet_eta_part"), etaJet1Raw, weight); - registry.fill(HIST("h_mixsubleadjet_eta_part"), etaJet2Raw, weight); - registry.fill(HIST("h2_mixdijet_detanoflip_dphi_part"), deltaEtaJetsNoflip, deltaPhiJets, weight); - registry.fill(HIST("h2_mixdijet_Asymmetry_part"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); - registry.fill(HIST("h3_mixdijet_deta_pt_part"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); - if (doDijetEta && multEta1Eta2 > 0) - registry.fill(HIST("h2_mixdijet_TimeEtaThan0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); - else if (doDijetEta && multEta1Eta2 < 0) - registry.fill(HIST("h2_mixdijet_TimeEtaLess0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); - - for (auto const& particle : particles2) { - registry.fill(HIST("h_mixevent_stats_part"), 4); - double hpt = particle.pt(); - double heta = inverse * particle.eta(); // Dr.Yang - double detatot = particle.eta() - etaJet1Raw; - double deta = flip * (particle.eta() - etaJet1Raw); - double dphi = particle.phi() - leadingJet.phi(); - dphi = RecoDecay::constrainAngle(dphi, -PIHalf); - if (hpt > assoHadronPtMaxCut) - continue; - registry.fill(HIST("h_mixevent_stats_part"), 5); - registry.fill(HIST("h_mixjeth_detatot_part"), detatot, weight); - registry.fill(HIST("h_mixjeth_deta_part"), deta, weight); - registry.fill(HIST("h_mixjeth_dphi_part"), dphi, weight); - if (doDijetEta) { - registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, heta, dphi, weight); - if (hpt >= assoHadronPtMin && hpt < assoHadronPtMax && multEta1Eta2 > 0) - registry.fill(HIST("h2_mixjeth_heta_dphi_part"), heta, dphi, weight); - } else { - registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, deltaEtaJets, deta, dphi, weight); - if (hpt >= assoHadronPtMin && hpt < assoHadronPtMax) { - if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi_part"), deta, dphi, weight); - if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi_part"), deta, dphi, weight); - if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi_part"), deta, dphi, weight); - } - } + double dphiHJ = phiTrig - jet.phi(); + dphiHJ = RecoDecay::constrainAngle(dphiHJ, -PIHalf); + if (std::abs(dphiHJ) < dijetDphiCut * PI) + continue; + registry.fill(HIST("h_hjet_dphi"), dphiHJ, weight); + double ptCorr = jet.pt() - jet.area() * collision.rho(); + if (ptCorr > ptRecoilCorr) { + recoilJet = it; + ptRecoilCorr = ptCorr; + hasRecoilJet = true; } } + if (!hasRecoilJet) + return; + if (ptRecoilCorr < subleadingjetptMin) + return; + + double etaRecoilRaw = recoilJet.eta(); + double phiRecoil = recoilJet.phi(); + double multEtaHJet = etaTrigRaw * etaRecoilRaw; + double inverse = (etaTrigRaw > 0) ? 1.0 : -1.0; + registry.fill(HIST("h_hjet_trigtrack_pt"), ptTrig, weight); + registry.fill(HIST("h_hjet_trigtrack_eta"), etaTrigRaw, weight); + registry.fill(HIST("h_hjet_trigtrack_phi"), phiTrig, weight); + registry.fill(HIST("h_hjet_recoiljet_corrpt"), ptRecoilCorr, weight); + registry.fill(HIST("h_hjet_recoiljet_eta"), etaRecoilRaw, weight); + registry.fill(HIST("h_hjet_recoiljet_phi"), phiRecoil, weight); + for (const auto& constituent : recoilJet.template tracks_as()) { + registry.fill(HIST("h2_recojet_corrpt_constituent_pt"), ptRecoilCorr, constituent.pt(), weight); + } + + if (multEtaHJet > 0) + registry.fill(HIST("h2_hjet_TimeEtaThan0_pt"), ptTrig, ptRecoilCorr, weight); + else if (multEtaHJet < 0) + registry.fill(HIST("h2_hjet_TimeEtaLess0_pt"), ptTrig, ptRecoilCorr, weight); + + // ----- Step 3: associated hadrons relative to trigger-track axis ----- + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) + continue; + // remove trigger particle itself from associated-hadron loop + if (track.globalIndex() == triggerTrack.globalIndex()) + continue; + double hpt = track.pt(); + if (hpt > assoHadronPtMaxCut) + continue; + double heta = inverse * track.eta(); + double dphi = track.phi() - phiTrig; + dphi = RecoDecay::constrainAngle(dphi, -PIHalf); + if (hpt >= assoHadronPtMin && hpt < assoHadronPtMax && multEtaHJet > 0) + registry.fill(HIST("h2_hjet_heta_dphi"), heta, dphi, weight); + registry.fill(HIST("thn_hjeth_correlations"), ptTrig, ptRecoilCorr, hpt, multEtaHJet, heta, dphi, weight); + } } // ========================================================== @@ -1284,17 +1128,17 @@ struct ChargedJetHadron { return; fillLeadingJetHadronHistograms(collision, jets, tracks); } - PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadron, "ame event subleading jet-h for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadron, "same event subleading jet-h for Data", false); - void processMixLeadingJetHadron(FilterCollisions const& collisions, - CorrChargedJets const& jets, - FilterJetTracks const& tracks) + void processHadronJetHadron(FilterCollision const& collision, + CorrChargedJets const& jets, + FilterJetTracks const& tracks) { - if (collisions.size() == 0) + if (!isGoodCollision(collision)) return; - fillMixLeadingJetHadronHistograms(collisions, jets, tracks); + fillHadronJetHadronHistograms(collision, jets, tracks); } - PROCESS_SWITCH(ChargedJetHadron, processMixLeadingJetHadron, "mixed event leading jet-h for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processHadronJetHadron, "same event h-jet-hadron correlations for Data", false); void processJetHadron(FilterCollision const& collision, CorrChargedJets const& jets, @@ -1376,12 +1220,12 @@ struct ChargedJetHadron { for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - fillTrackHistograms(track, eventWeight); + fillTrackHistograms(track, eventWeight, collision.mcCollision().ptHard()); } } PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCD, "QC of collisions and tracks for MCD", false); - void processSpectraAreaSubMCD(FilterCollision const& collision, + void processSpectraAreaSubMCD(FilterMcdCollision const& collision, CorrChargedMCDJets const& jets, aod::JetTracks const&) { @@ -1395,13 +1239,13 @@ struct ChargedJetHadron { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet, eventWeight); - fillJetAreaSubHistograms(jet, collision.rho(), eventWeight); + fillJetHistograms(jet, eventWeight, collision.mcCollision().ptHard()); + fillJetAreaSubHistograms(jet, collision.rho(), eventWeight, collision.mcCollision().ptHard()); } } PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubMCD, "jet spectra with rho-area subtraction for MCD", false); - void processLeadingJetHadronMCD(FilterCollision const& collision, + void processLeadingJetHadronMCD(FilterMcdCollision const& collision, CorrChargedMCDJets const& jets, FilterJetTracks const& tracks) { @@ -1409,28 +1253,29 @@ struct ChargedJetHadron { if (!isGoodCollision(collision)) { return; } - fillLeadingJetHadronHistograms(collision, jets, tracks, eventWeight); + fillLeadingJetHadronHistograms(collision, jets, tracks, eventWeight, collision.mcCollision().ptHard()); } PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadronMCD, "same event leading jet-hadron correlations for MCD", false); - void processMixLeadingJetHadronMCD(FilterCollisions const& collisions, - CorrChargedMCDJets const& jets, - FilterJetTracks const& tracks) + void processHadronJetHadronMCD(FilterCollision const& collision, + CorrChargedMCDJets const& jets, + FilterJetTracks const& tracks) { - if (collisions.size() == 0) + const float eventWeight = doEventWeighted ? collision.weight() : 1.f; + if (!isGoodCollision(collision)) return; - fillMixLeadingJetHadronHistograms(collisions, jets, tracks); + fillHadronJetHadronHistograms(collision, jets, tracks, eventWeight); } - PROCESS_SWITCH(ChargedJetHadron, processMixLeadingJetHadronMCD, "mixed event leading jet-hadron correlations for MCD", false); + PROCESS_SWITCH(ChargedJetHadron, processHadronJetHadronMCD, "same event h-jet-hadron correlations for MCD", false); - void processJetHadronMCD(FilterCollision const& collision, + void processJetHadronMCD(FilterMcdCollision const& collision, CorrChargedMCDJets const& jets, FilterJetTracks const& tracks) { const float eventWeight = doEventWeighted ? collision.weight() : 1.f; if (!isGoodCollision(collision)) return; - fillJetHadronHistograms(collision, jets, tracks, eventWeight); + fillJetHadronHistograms(collision, jets, tracks, eventWeight, collision.mcCollision().ptHard()); } PROCESS_SWITCH(ChargedJetHadron, processJetHadronMCD, "same event jet-hadron correlations for MCD", false); @@ -1471,7 +1316,7 @@ struct ChargedJetHadron { registry.fill(HIST("h_mcpColl_centrality"), mccollision.centFT0M(), eventWeight); registry.fill(HIST("h_mcpColl_multFT0"), getMultiplicity(mccollision), eventWeight); for (auto const& particle : particles) { - fillParticleHistograms(particle, eventWeight); + fillParticleHistograms(particle, eventWeight, mccollision.ptHard()); } } PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCP, "QC of collisions and particles for MCP", false); @@ -1498,8 +1343,8 @@ struct ChargedJetHadron { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - fillMCPHistograms(jet, eventWeight); - fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight); + fillMCPHistograms(jet, eventWeight, mccollision.ptHard()); + fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight, mccollision.ptHard()); } } PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubMCP, "jet spectra without and with UE subtraction of area-based for MCP", false); @@ -1513,21 +1358,10 @@ struct ChargedJetHadron { if (!applyMCCollisionCuts(mccollision, collisions)) return; - fillMCPLeadingJetHadronHistograms(mccollision, jets, particles, eventWeight); + fillMCPLeadingJetHadronHistograms(mccollision, jets, particles, eventWeight, mccollision.ptHard()); } PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadronMCP, "same event leading jet-hadron for MCP", false); - void processMixLeadingJetHadronMCP(FilterMcpCollisions const& mccollisions, - soa::SmallGroups const& collisions, - CorrChargedMCPJets const& jets, - soa::Filtered const& particles) - { - if (mccollisions.size() < 1 || collisions.size() < 1) - return; - fillMCPMixLeadingJetHadronHistograms(mccollisions, collisions, jets, particles); - } - PROCESS_SWITCH(ChargedJetHadron, processMixLeadingJetHadronMCP, "mixed event leading jet-hadron for MCP", false); - void processJetHadronMCP(FilterMcpCollision const& mccollision, soa::SmallGroups const& collisions, CorrChargedMCPJets const& jets, @@ -1537,7 +1371,7 @@ struct ChargedJetHadron { if (!applyMCCollisionCuts(mccollision, collisions)) return; - fillMCPJetHadronHistograms(mccollision, jets, particles, eventWeight); + fillMCPJetHadronHistograms(mccollision, jets, particles, eventWeight, mccollision.ptHard()); } PROCESS_SWITCH(ChargedJetHadron, processJetHadronMCP, "same event jet-hadron for MCP", false); From 20d32e19f89d5fe85ec16203351d13c88f1ebc39 Mon Sep 17 00:00:00 2001 From: JBae <110481228+joonsukbae@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:36:53 +0900 Subject: [PATCH 431/449] [PWGJE] jet-spectra-charged: weighted-bind fix + add gen-only spectra task (#16545) Co-authored-by: Joonsuk Bae Co-authored-by: Claude Opus 4.7 (1M context) --- PWGJE/Tasks/CMakeLists.txt | 4 + PWGJE/Tasks/jetSpectraCharged.cxx | 63 +++++- PWGJE/Tasks/jetSpectraChargedGen.cxx | 285 +++++++++++++++++++++++++++ 3 files changed, 342 insertions(+), 10 deletions(-) create mode 100644 PWGJE/Tasks/jetSpectraChargedGen.cxx diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 0475580147f..e87a75535d2 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -277,6 +277,10 @@ if(FastJet_FOUND) SOURCES jetSpectraCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-spectra-charged-gen + SOURCES jetSpectraChargedGen.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(charged-jet-hadron SOURCES chargedJetHadron.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index 6e19be7a128..8b32a44aff4 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -95,6 +95,7 @@ struct JetSpectraCharged { float configSwitchHigh = 9998.0; float ptHardCalcMethodSwitch = 999.0; + static constexpr float kBrokenPtHardSentinel = 1.0f; enum AcceptSplitCollisionsOptions { NonSplitOnly = 0, @@ -921,7 +922,7 @@ struct JetSpectraCharged { void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::JetTracks const&, - aod::JetMcCollisions const&) + aod::JetMcCollisions const& mccollisions) { bool fillHistograms = false; bool isWeighted = true; @@ -929,7 +930,16 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // collision.mcCollision() auto-resolves to the wrong JMcCollisions binding here; bind via rawIteratorAt. + float ptHardFromMc = ptHardCalcMethodSwitch; + if (collision.mcCollisionId() >= 0) { + float storedPtHard = mccollisions.rawIteratorAt(collision.mcCollisionId()).ptHard(); + // LHC26b5 ships placeholder ptHard=1.0; fall back to weight-derived. + if (storedPtHard > kBrokenPtHardSentinel && storedPtHard < ptHardCalcMethodSwitch) { + ptHardFromMc = storedPtHard; + } + } + float pTHat = ptHardFromMc < ptHardCalcMethodSwitch ? ptHardFromMc : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); @@ -948,7 +958,7 @@ struct JetSpectraCharged { void processSpectraAreaSubMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& jets, aod::JetTracks const&, - aod::JetMcCollisions const&) + aod::JetMcCollisions const& mccollisions) { bool fillHistograms = false; bool isWeighted = true; @@ -956,7 +966,16 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // See note in processSpectraMCDWeighted: avoid the wrong-type bind by + // looking the MC collision up explicitly via the named subscribed table. + float ptHardFromMc = ptHardCalcMethodSwitch; + if (collision.mcCollisionId() >= 0) { + float storedPtHard = mccollisions.rawIteratorAt(collision.mcCollisionId()).ptHard(); + if (storedPtHard > kBrokenPtHardSentinel && storedPtHard < ptHardCalcMethodSwitch) { + ptHardFromMc = storedPtHard; + } + } + float pTHat = ptHardFromMc < ptHardCalcMethodSwitch ? ptHardFromMc : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : (centrality = (useFT0CVariant ? collision.centFT0CVariant1() : collision.centFT0C())); @@ -1199,7 +1218,8 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = mccollision.ptHard() < ptHardCalcMethodSwitch ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // LHC26b5 ships placeholder ptHard=1.0; fall back to weight-derived. + float pTHat = (mccollision.ptHard() > kBrokenPtHardSentinel && mccollision.ptHard() < ptHardCalcMethodSwitch) ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1231,7 +1251,9 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = mccollision.ptHard() < ptHardCalcMethodSwitch ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // See note in processSpectraMCPWeighted re: ptHard=1.0 placeholder in + // current LHC26b5-class MC. + float pTHat = (mccollision.ptHard() > kBrokenPtHardSentinel && mccollision.ptHard() < ptHardCalcMethodSwitch) ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_mccollisions_rho"), mccollision.rho(), eventWeight); for (auto const& jet : jets) { @@ -1314,7 +1336,7 @@ struct JetSpectraCharged { ChargedMCDMatchedJets const& mcdjets, ChargedMCPMatchedJets const&, aod::JetTracks const&, aod::JetParticles const&, - aod::JetMcCollisions const&) + aod::JetMcCollisions const& mccollisions) { bool fillHistograms = false; bool isWeighted = true; @@ -1322,7 +1344,16 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // See note in processSpectraMCDWeighted: avoid the wrong-type bind by + // looking the MC collision up explicitly via the named subscribed table. + float ptHardFromMc = ptHardCalcMethodSwitch; + if (collision.mcCollisionId() >= 0) { + float storedPtHard = mccollisions.rawIteratorAt(collision.mcCollisionId()).ptHard(); + if (storedPtHard > kBrokenPtHardSentinel && storedPtHard < ptHardCalcMethodSwitch) { + ptHardFromMc = storedPtHard; + } + } + float pTHat = ptHardFromMc < ptHardCalcMethodSwitch ? ptHardFromMc : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (const auto& mcdjet : mcdjets) { if (!isAcceptedJet(mcdjet)) { continue; @@ -1365,9 +1396,21 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < ptHardCalcMethodSwitch ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + // Here we already have JetBkgRhoMcCollisions explicitly subscribed; use the + // mcCollision_as() cast to dodge the wrong-type bind + // (same root cause as processSpectraMCDWeighted) and also guard against the + // ptHard=1.0 placeholder seen in current LHC26b5-class MC. + bool hasMc = collision.has_mcCollision(); + float ptHardFromMc = ptHardCalcMethodSwitch; + if (hasMc) { + float storedPtHard = collision.mcCollision_as().ptHard(); + if (storedPtHard > kBrokenPtHardSentinel && storedPtHard < ptHardCalcMethodSwitch) { + ptHardFromMc = storedPtHard; + } + } + float pTHat = ptHardFromMc < ptHardCalcMethodSwitch ? ptHardFromMc : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); - double mcrho = collision.has_mcCollision() ? collision.mcCollision_as().rho() : -1; + double mcrho = hasMc ? collision.mcCollision_as().rho() : -1; for (const auto& mcdjet : mcdjets) { if (!isAcceptedJet(mcdjet)) { diff --git a/PWGJE/Tasks/jetSpectraChargedGen.cxx b/PWGJE/Tasks/jetSpectraChargedGen.cxx new file mode 100644 index 00000000000..210b2144a33 --- /dev/null +++ b/PWGJE/Tasks/jetSpectraChargedGen.cxx @@ -0,0 +1,285 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file jetSpectraChargedGen.cxx +/// \brief Charged-particle jet spectra at MC-particle level for generator-only +/// AODs (no reconstruction tables required). Companion to +/// jetSpectraCharged.cxx for productions such as EPOS 4 on-the-fly +/// where only mc-particle and mc-collision tables exist. +/// \author Joonsuk Bae + +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct JetSpectraChargedGen { + + using JetBkgRhoMcCollisions = soa::Join; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable selectedJetsRadius{"selectedJetsRadius", 0.2, "resolution parameter for histograms without radius"}; + Configurable jetEtaMin{"jetEtaMin", -0.7, "minimum jet pseudorapidity"}; + Configurable jetEtaMax{"jetEtaMax", 0.7, "maximum jet pseudorapidity"}; + Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum particle pseudorapidity"}; + Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum particle pseudorapidity"}; + Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "minimum area fraction relative to pi R^2"}; + Configurable leadingConstituentPtMin{"leadingConstituentPtMin", -99.0, "minimum pT of the leading constituent"}; + Configurable leadingConstituentPtMax{"leadingConstituentPtMax", 9999.0, "maximum pT of the leading constituent"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum jet pT in units of pTHat (outlier rejection)"}; + Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum pTHat"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the back-calculation of pTHat"}; + Configurable simPtRef{"simPtRef", 10.0, "reference pT for the back-calculation of pTHat from the event weight"}; + Configurable vertexZCut{"vertexZCut", 10.0, "truth vertex-z cut; <=0 disables"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable jetPtMax{"jetPtMax", 200.0, "max of the jet pT axis"}; + + static constexpr float kConfigSwitchLow = -98.0f; + static constexpr float kConfigSwitchHigh = 9998.0f; + + void init(InitContext const&) + { + AxisSpec jetPtAxis = {static_cast(jetPtMax), 0.0, jetPtMax, "#it{p}_{T,jet} (GeV/#it{c})"}; + AxisSpec etaAxis = {100, -1.0, 1.0, "#eta_{jet}"}; + AxisSpec phiAxis = {160, -1.0, 7.0, "#varphi_{jet}"}; + AxisSpec rhoAxis = {200, 0.0, 200.0, "#rho (GeV/#it{c})"}; + + registry.add("h_mccollisions", "MC collisions counter;;entries", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("h_mccollisions_rho", "#rho distribution;#rho (GeV/#it{c});entries", {HistType::kTH1F, {rhoAxis}}); + registry.add("p_xSection", ";;<#sigma_{gen}> from HepMC (pb)", {HistType::kTProfile, {{1, 0.0, 1.0}}}); + + registry.add("h_jet_pt_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta_part", ";#eta_{jet}^{part};entries", {HistType::kTH1F, {etaAxis}}); + registry.add("h_jet_phi_part", ";#varphi_{jet}^{part};entries", {HistType::kTH1F, {phiAxis}}); + registry.add("h3_jet_pt_jet_eta_jet_phi_part", ";#it{p}_{T,jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", + {HistType::kTH3F, {jetPtAxis, etaAxis, phiAxis}}); + registry.add("h2_jet_pt_part_jet_area_part", ";#it{p}_{T,jet}^{part};jet area", + {HistType::kTH2F, {jetPtAxis, {200, 0.0, 4.0}}}); + registry.add("h2_jet_pt_part_jet_ntracks_part", ";#it{p}_{T,jet}^{part};#it{N}_{tracks}", + {HistType::kTH2F, {jetPtAxis, {100, 0.0, 100.0}}}); + registry.add("h2_jet_pt_part_track_pt_part", ";#it{p}_{T,jet}^{part};#it{p}_{T,track}^{part}", + {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); + registry.add("h2_jet_pt_jet_angularity_part", ";#it{p}_{T,jet}^{part};angularity", + {HistType::kTH2F, {jetPtAxis, {200, 0.0, 4.0}}}); + + registry.add("h_jet_pt_part_rhoareasubtracted", ";#it{p}_{T,jet}^{part,sub} (GeV/#it{c});entries", + {HistType::kTH1F, {{static_cast(2 * jetPtMax), -jetPtMax, jetPtMax}}}); + registry.add("h_jet_eta_part_rhoareasubtracted", ";#eta_{jet}^{part};entries", {HistType::kTH1F, {etaAxis}}); + registry.add("h_jet_phi_part_rhoareasubtracted", ";#varphi_{jet}^{part};entries", {HistType::kTH1F, {phiAxis}}); + registry.add("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted", + ";#it{p}_{T,jet}^{part,sub};#eta_{jet}^{part};#varphi_{jet}^{part}", + {HistType::kTH3F, {{static_cast(2 * jetPtMax), -jetPtMax, jetPtMax}, etaAxis, phiAxis}}); + registry.add("h2_jet_pt_part_jet_area_part_rhoareasubtracted", ";#it{p}_{T,jet}^{part,sub};jet area", + {HistType::kTH2F, {{static_cast(2 * jetPtMax), -jetPtMax, jetPtMax}, {200, 0.0, 4.0}}}); + registry.add("h2_jet_pt_part_jet_ntracks_part_rhoareasubtracted", ";#it{p}_{T,jet}^{part,sub};#it{N}_{tracks}", + {HistType::kTH2F, {{static_cast(2 * jetPtMax), -jetPtMax, jetPtMax}, {100, 0.0, 100.0}}}); + } + + // Truth-only zvtx cut: returns true if accepted. + template + bool passVertexZ(TMcColl const& mccollision) + { + if (vertexZCut <= 0.0f) { + return true; + } + return std::abs(mccollision.posZ()) < vertexZCut; + } + + template + bool isAcceptedJet(TJet const& jet) + { + if (jetAreaFractionMin > kConfigSwitchLow) { + if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + return false; + } + } + bool checkMin = (leadingConstituentPtMin > kConfigSwitchLow); + bool checkMax = (leadingConstituentPtMax < kConfigSwitchHigh); + if (!checkMin && !checkMax) { + return true; + } + bool passMin = !checkMin; + bool passMax = checkMax; + for (const auto& constituent : jet.template tracks_as()) { + double pt = constituent.pt(); + if (checkMin && pt >= leadingConstituentPtMin) { + passMin = true; + } + if (checkMax && pt > leadingConstituentPtMax) { + passMax = false; + } + } + return passMin && passMax; + } + + template + void fillRawHistograms(TJet const& jet, float weight, float pTHat) + { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + return; + } + if (jet.r() == std::round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); + registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_part"), jet.pt(), jet.eta(), jet.phi(), weight); + registry.fill(HIST("h2_jet_pt_part_jet_area_part"), jet.pt(), jet.area(), weight); + registry.fill(HIST("h2_jet_pt_part_jet_ntracks_part"), jet.pt(), jet.tracksIds().size(), weight); + } + float angularity = 0.0f; + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.0f)); + registry.fill(HIST("h2_jet_pt_jet_angularity_part"), jet.pt(), angularity, weight); + } + + template + void fillAreaSubHistograms(TJet const& jet, float rho, float weight, float pTHat) + { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + return; + } + if (jet.r() != std::round(selectedJetsRadius * 100.0f)) { + return; + } + double ptSub = jet.pt() - (rho * jet.area()); + registry.fill(HIST("h_jet_pt_part_rhoareasubtracted"), ptSub, weight); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted"), ptSub, jet.eta(), jet.phi(), weight); + if (ptSub > 0.0) { + registry.fill(HIST("h_jet_eta_part_rhoareasubtracted"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi_part_rhoareasubtracted"), jet.phi(), weight); + registry.fill(HIST("h2_jet_pt_part_jet_area_part_rhoareasubtracted"), ptSub, jet.area(), weight); + registry.fill(HIST("h2_jet_pt_part_jet_ntracks_part_rhoareasubtracted"), ptSub, jet.tracksIds().size(), weight); + } + } + + void processDummy(aod::JDummys const&) {} + PROCESS_SWITCH(JetSpectraChargedGen, processDummy, "dummy process", true); + + void processChargedGen(aod::JetMcCollisions::iterator const& mccollision, + soa::Join const& jets, + aod::JetParticles const&) + { + if (!passVertexZ(mccollision)) { + return; + } + registry.fill(HIST("h_mccollisions"), 0.5); + registry.fill(HIST("p_xSection"), 0.5, mccollision.xsectGen()); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillRawHistograms(jet, /*weight*/ 1.0f, /*pTHat*/ 999.0f); + } + } + PROCESS_SWITCH(JetSpectraChargedGen, processChargedGen, + "charged-jet spectra at MC particle level (generator-only AOD)", false); + + void processChargedGenWeighted(aod::JetMcCollisions::iterator const& mccollision, + soa::Join const& jets, + aod::JetParticles const&) + { + if (!passVertexZ(mccollision)) { + return; + } + float weight = mccollision.weight(); + float pTHat = simPtRef / std::pow(weight, 1.0f / pTHatExponent); + registry.fill(HIST("h_mccollisions"), 0.5, weight); + registry.fill(HIST("p_xSection"), 0.5, mccollision.xsectGen(), weight); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillRawHistograms(jet, weight, pTHat); + } + } + PROCESS_SWITCH(JetSpectraChargedGen, processChargedGenWeighted, + "charged-jet spectra at MC particle level, weighted (generator-only AOD)", false); + + void processChargedAreaSubGen(JetBkgRhoMcCollisions::iterator const& mccollision, + soa::Join const& jets, + aod::JetParticles const&) + { + if (!passVertexZ(mccollision)) { + return; + } + registry.fill(HIST("h_mccollisions"), 0.5); + registry.fill(HIST("p_xSection"), 0.5, mccollision.xsectGen()); + registry.fill(HIST("h_mccollisions_rho"), mccollision.rho()); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillAreaSubHistograms(jet, mccollision.rho(), /*weight*/ 1.0f, /*pTHat*/ 999.0f); + } + } + PROCESS_SWITCH(JetSpectraChargedGen, processChargedAreaSubGen, + "charged-jet area-subtracted spectra at MC particle level (generator-only AOD)", false); + + void processChargedAreaSubGenWeighted(JetBkgRhoMcCollisions::iterator const& mccollision, + soa::Join const& jets, + aod::JetParticles const&) + { + if (!passVertexZ(mccollision)) { + return; + } + float weight = mccollision.weight(); + float pTHat = simPtRef / std::pow(weight, 1.0f / pTHatExponent); + registry.fill(HIST("h_mccollisions"), 0.5, weight); + registry.fill(HIST("p_xSection"), 0.5, mccollision.xsectGen(), weight); + registry.fill(HIST("h_mccollisions_rho"), mccollision.rho(), weight); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillAreaSubHistograms(jet, mccollision.rho(), weight, pTHat); + } + } + PROCESS_SWITCH(JetSpectraChargedGen, processChargedAreaSubGenWeighted, + "charged-jet area-subtracted spectra at MC particle level, weighted (generator-only AOD)", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 2e46e255c8bbc75e6582c941d89e9398d5e6bf15 Mon Sep 17 00:00:00 2001 From: JBae <110481228+joonsukbae@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:41:54 +0900 Subject: [PATCH 432/449] [PWGJE] jetCrossSectionEfficiency: cascade variants + hybrid-MC handling (#16546) Co-authored-by: Joonsuk Bae Co-authored-by: Claude Opus 4.7 (1M context) Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/jetCrossSectionEfficiency.cxx | 656 +++++++++------------- 1 file changed, 257 insertions(+), 399 deletions(-) diff --git a/PWGJE/Tasks/jetCrossSectionEfficiency.cxx b/PWGJE/Tasks/jetCrossSectionEfficiency.cxx index 240fb3e7a20..c768e25fa2f 100644 --- a/PWGJE/Tasks/jetCrossSectionEfficiency.cxx +++ b/PWGJE/Tasks/jetCrossSectionEfficiency.cxx @@ -9,7 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Step-by-step event selection efficiency for MC particle-level jets +// Step-by-step event selection efficiency for MC particle-level jets. +// Two ordering variants exposed as separate process functions: +// - CollRecoFirst: reco collision required first, BC bits read from the reco-coll EvSel bitmask. +// - BcBitsFirst: BC bits read from the MC truth BC, then truth-side SBP, then reco at the end. // /// \author Joonsuk Bae @@ -17,6 +20,9 @@ #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" + #include #include #include @@ -26,16 +32,9 @@ #include #include -#include -#include - -#include #include -#include -#include +#include #include -#include -#include using namespace o2; using namespace o2::framework; @@ -45,8 +44,8 @@ struct JetCrossSectionEfficiency { HistogramRegistry registry; - Configurable eventSelections{"eventSelections", "selTVX", "choose event selection (e.g., sel8, selMC, sel8Full, selTVX, etc.)"}; - Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events"}; + Configurable eventSelections{"eventSelections", "sel8", "selTVX | selMC | selMCFull | sel8 | sel8Full"}; + Configurable skipMBGapEvents{"skipMBGapEvents", false, "reject min-bias gap events from hybrid MB+JJ MC productions"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0f, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0f, "maximum centrality"}; @@ -63,12 +62,23 @@ struct JetCrossSectionEfficiency { Configurable leadingConstituentPtMinMCP{"leadingConstituentPtMinMCP", -99.0f, "minimum pT selection on MCP jet constituent"}; Configurable leadingConstituentPtMaxMCP{"leadingConstituentPtMaxMCP", 9999.0f, "maximum pT selection on MCP jet constituent"}; - Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum track occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions"}; - Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum track occupancy of tracks in neighbouring collisions in a given time range; only applied to reconstructed collisions"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum track occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable trackOccupancyInTimeRangeMin{"trackOccupancyInTimeRangeMin", -999999, "minimum track occupancy of tracks in neighbouring collisions in a given time range"}; Configurable acceptSplitCollisions{"acceptSplitCollisions", 0, "0: only look at mcCollisions that are not split; 1: accept split mcCollisions, 2: accept split mcCollisions but only look at the first reco collision associated with it"}; - Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0f, "maximum fraction of hard scattering for jet acceptance in particle MC"}; - Configurable pTHatExponent{"pTHatExponent", 6.0f, "exponent of the event weight for the calculation of pTHat"}; - Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0f, "minimum value of pTHat"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0f, "maximum jet pT in units of pTHat for outlier rejection at MC particle level"}; + Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0f, "minimum pTHat (drops events with pTHat below this)"}; + Configurable pTHatExponent{"pTHatExponent", 6.0f, "exponent in the back-calculation of pTHat from the event weight"}; + Configurable simPtRef{"simPtRef", 10.0f, "reference pT for the back-calculation of pTHat from the event weight"}; + Configurable ptHardCalcMethodSwitch{"ptHardCalcMethodSwitch", 999.0f, "sentinel and threshold for the stored-ptHard branch (set <=0 to force weight-derived)"}; + Configurable applyRCT{"applyRCT", true, "apply RCT_pass step in the cascade (false: force the RCT step to pass)"}; + Configurable rctSelectionsLabel{"rctSelectionsLabel", "CBT_hadronPID", "RCT selection preset name (see RCTSelectionFlags)"}; + + o2::aod::rctsel::RCTFlagsChecker rctChecker; + uint64_t rctMask = 0; + + bool applyTFB = true; + bool applyROFB = true; + bool applySBP = true; enum AcceptSplitCollisionsOptions { NonSplitOnly = 0, @@ -78,42 +88,34 @@ struct JetCrossSectionEfficiency { static constexpr float configSwitchLow = -98.0f; static constexpr float configSwitchHigh = 9998.0f; - - std::vector eventSelectionBits; - - struct StageInfo { - int bit; - int bin; - }; - std::vector activeStages; - - int binInel = 1; - int binNoReco = 2; - int binSplit = 3; - int binZvtx = -1; - int binCentrality = -1; - - const char* getStageLabel(int bit) - { - switch (bit) { - case jetderiveddatautilities::JCollisionSel::selTVX: - return "kTVX"; - case jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder: - return "kTFBorder"; - case jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder: - return "kITSROFBorder"; - case jetderiveddatautilities::JCollisionSel::selNoSameBunchPileup: - return "NoSameBunchPileup"; - case jetderiveddatautilities::JCollisionSel::selIsGoodZvtxFT0vsPV: - return "IsGoodZvtxFT0vsPV"; - case jetderiveddatautilities::JCollisionSel::selNoCollInTimeRangeStandard: - return "NoCollInTimeRangeStd"; - case jetderiveddatautilities::JCollisionSel::selNoCollInRofStandard: - return "NoCollInRofStd"; - default: - return nullptr; - } - } + static constexpr float kBrokenPtHardSentinel = 1.0f; + + // CollRecoFirst: reco collision required first; BC bits read from the reco-coll EvSels. + static constexpr int kBinCRF_Inel = 1; + static constexpr int kBinCRF_RctPass = 2; + static constexpr int kBinCRF_HasColl = 3; + static constexpr int kBinCRF_Zreco = 4; + static constexpr int kBinCRF_NoSplit = 5; + static constexpr int kBinCRF_TVX = 6; + static constexpr int kBinCRF_TFB = 7; + static constexpr int kBinCRF_ROFB = 8; + static constexpr int kBinCRF_SBP = 9; + static constexpr int kBinCRF_N = 9; + + // BcBitsFirst: BC bits read from the MC truth BC; SBP from a Preslice count + // (exactly one MC collision per truth BC) so it works before requiring reco. + static constexpr int kBinBBF_Inel = 1; + static constexpr int kBinBBF_RctPass = 2; + static constexpr int kBinBBF_TVX = 3; + static constexpr int kBinBBF_TFB = 4; + static constexpr int kBinBBF_ROFB = 5; + static constexpr int kBinBBF_TruthSBP = 6; + static constexpr int kBinBBF_HasColl = 7; + static constexpr int kBinBBF_Zreco = 8; + static constexpr int kBinBBF_NoSplit = 9; + static constexpr int kBinBBF_N = 9; + + Preslice mcCollsPerBC = aod::jmccollision::bcId; void init(InitContext&) { @@ -121,116 +123,111 @@ struct JetCrossSectionEfficiency { LOGF(fatal, "Configurable acceptSplitCollisions has wrong input value; stopping workflow"); } - eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); - - auto hasBit = [&](int bit) { - return std::find(eventSelectionBits.begin(), eventSelectionBits.end(), bit) != eventSelectionBits.end(); - }; - - activeStages.clear(); - int nextEventSelectionBin = 4; - std::set addedBits; - - auto addStageIfNotAlreadyAdded = [&](int bit) { - if (addedBits.find(bit) != addedBits.end()) { - return; - } - addedBits.insert(bit); - activeStages.push_back({bit, nextEventSelectionBin++}); - }; - - // sel8, sel7, selKINT7 are composite selections that require multiple sub-bits. - // initialiseEventSelectionBits returns them as single bits, but for step-by-step QA - // we need to expand them into their constituent bits (kTVX, kTFBorder, kITSROFBorder). - // Note: selMC, selMCFull, etc. are already expanded by initialiseEventSelectionBits. - std::vector>> compositeSelections = { - {jetderiveddatautilities::JCollisionSel::sel8, {jetderiveddatautilities::JCollisionSel::selTVX, jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder, jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder}}, - {jetderiveddatautilities::JCollisionSel::sel7, {jetderiveddatautilities::JCollisionSel::selTVX, jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder, jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder}}, - {jetderiveddatautilities::JCollisionSel::selKINT7, {jetderiveddatautilities::JCollisionSel::selTVX, jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder, jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder}}}; - - for (auto const& [compositeBit, subBits] : compositeSelections) { - if (hasBit(compositeBit)) { - for (auto subBit : subBits) { - addStageIfNotAlreadyAdded(subBit); - } - } - } - - std::vector allPossibleBits = { - jetderiveddatautilities::JCollisionSel::selTVX, - jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder, - jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder, - jetderiveddatautilities::JCollisionSel::selNoSameBunchPileup, - jetderiveddatautilities::JCollisionSel::selIsGoodZvtxFT0vsPV, - jetderiveddatautilities::JCollisionSel::selNoCollInTimeRangeStandard, - jetderiveddatautilities::JCollisionSel::selNoCollInRofStandard}; - - for (auto bit : allPossibleBits) { - if (hasBit(bit)) { - addStageIfNotAlreadyAdded(bit); - } + rctChecker.init(static_cast(rctSelectionsLabel)); + rctMask = rctChecker.value(); + + const std::string es = eventSelections; + if (es == "selTVX") { + applyTFB = false; + applyROFB = false; + applySBP = false; + } else if (es == "selMC") { + applyTFB = true; + applyROFB = false; + applySBP = false; + } else if (es == "selMCFull") { + applyTFB = true; + applyROFB = false; + applySBP = true; + } else if (es == "sel8") { + applyTFB = true; + applyROFB = true; + applySBP = false; + } else if (es == "sel8Full") { + applyTFB = true; + applyROFB = true; + applySBP = true; + } else { + LOGF(fatal, "Configurable eventSelections=%s not supported; use selTVX, selMC, selMCFull, sel8, or sel8Full", es.c_str()); } - binZvtx = nextEventSelectionBin++; - binCentrality = nextEventSelectionBin++; - AxisSpec jetPtAxis = {200, 0., jetPtMax, "#it{p}_{T} (GeV/#it{c})"}; - int totalEventSelectionBins = nextEventSelectionBin - 1; - AxisSpec eventSelectionAxis = {totalEventSelectionBins, 0.5, static_cast(nextEventSelectionBin) - 0.5, "event selection"}; - - if (doprocessCrossSectionEfficiency || doprocessCrossSectionEfficiencyWeighted) { - registry.add("h2_jet_pt_part_eventselection", - "part jet pT vs event selection;#it{p}_{T,jet}^{part} (GeV/#it{c});event selection;counts", - {HistType::kTH2F, {jetPtAxis, eventSelectionAxis}}); - auto histJetPtVsEventSelection = registry.get(HIST("h2_jet_pt_part_eventselection")); - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(binInel, "INEL"); - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(binNoReco, "noRecoColl"); - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(binSplit, "splitColl"); - for (auto const& stage : activeStages) { - const char* label = getStageLabel(stage.bit); - if (label) { - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(stage.bin, label); - } - } - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(binZvtx, "zvtx"); - histJetPtVsEventSelection->GetYaxis()->SetBinLabel(binCentrality, "centralitycut"); - } if (doprocessCrossSectionEfficiency) { - registry.add("h_mccollisions_eventselection", - "number of mc events vs event selection;event selection;entries", - {HistType::kTH1F, {{totalEventSelectionBins, 0.5, static_cast(nextEventSelectionBin) - 0.5}}}); - auto histMcCollisionsEventSelection = registry.get(HIST("h_mccollisions_eventselection")); - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(binInel, "INEL"); - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(binNoReco, "noRecoColl"); - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(binSplit, "splitColl"); - for (auto const& stage : activeStages) { - const char* label = getStageLabel(stage.bit); - if (label) { - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(stage.bin, label); - } - } - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(binZvtx, "zvtx"); - histMcCollisionsEventSelection->GetXaxis()->SetBinLabel(binCentrality, "centralitycut"); + AxisSpec axCRF = {kBinCRF_N, 0.5, static_cast(kBinCRF_N) + 0.5, "event selection (CollRecoFirst)"}; + registry.add("h2_jet_pt_part_eventselection_collRecoFirst", + "part jet pT vs event selection (CollRecoFirst);#it{p}_{T,jet}^{part} (GeV/#it{c});event selection;counts", + {HistType::kTH2F, {jetPtAxis, axCRF}}); + auto hCRF2 = registry.get(HIST("h2_jet_pt_part_eventselection_collRecoFirst")); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_Inel, "INEL"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_RctPass, "+RCT_pass"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_HasColl, "+hasRecoColl"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_Zreco, "+|zReco|<10"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_NoSplit, "+noSplit"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_TVX, "+kTVX"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_TFB, "+kNoTFB"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_ROFB, "+kNoITSROFB"); + hCRF2->GetYaxis()->SetBinLabel(kBinCRF_SBP, "+kNoSBP"); + + registry.add("h_mccollisions_eventselection_collRecoFirst", + "number of mc events vs event selection (CollRecoFirst);event selection;entries", + {HistType::kTH1F, {{kBinCRF_N, 0.5, static_cast(kBinCRF_N) + 0.5}}}); + auto hCRF1 = registry.get(HIST("h_mccollisions_eventselection_collRecoFirst")); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_Inel, "INEL"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_RctPass, "+RCT_pass"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_HasColl, "+hasRecoColl"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_Zreco, "+|zReco|<10"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_NoSplit, "+noSplit"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_TVX, "+kTVX"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_TFB, "+kNoTFB"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_ROFB, "+kNoITSROFB"); + hCRF1->GetXaxis()->SetBinLabel(kBinCRF_SBP, "+kNoSBP"); } - if (doprocessCrossSectionEfficiencyWeighted) { - registry.add("h_mccollisions_eventselection_weighted", - "number of weighted mc events vs event selection;event selection;weighted entries", - {HistType::kTH1F, {{totalEventSelectionBins, 0.5, static_cast(nextEventSelectionBin) - 0.5}}}); - auto histMcCollisionsEventSelectionWeighted = registry.get(HIST("h_mccollisions_eventselection_weighted")); - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(binInel, "INEL"); - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(binNoReco, "noRecoColl"); - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(binSplit, "splitColl"); - for (auto const& stage : activeStages) { - const char* label = getStageLabel(stage.bit); - if (label) { - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(stage.bin, label); - } - } - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(binZvtx, "zvtx"); - histMcCollisionsEventSelectionWeighted->GetXaxis()->SetBinLabel(binCentrality, "centralitycut"); + if (doprocessCrossSectionEfficiencyBcBitsFirst) { + AxisSpec axBBF = {kBinBBF_N, 0.5, static_cast(kBinBBF_N) + 0.5, "event selection (BcBitsFirst)"}; + registry.add("h2_jet_pt_part_eventselection_bcBitsFirst", + "part jet pT vs event selection (BcBitsFirst);#it{p}_{T,jet}^{part} (GeV/#it{c});event selection;counts", + {HistType::kTH2F, {jetPtAxis, axBBF}}); + auto hBBF2 = registry.get(HIST("h2_jet_pt_part_eventselection_bcBitsFirst")); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_Inel, "INEL"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_RctPass, "+RCT_pass"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_TVX, "+kTVX(truth)"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_TFB, "+kNoTFB(truth)"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_ROFB, "+kNoITSROFB(truth)"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_TruthSBP, "+kNoSBP(truth)"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_HasColl, "+hasColl"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_Zreco, "+|zReco|<10"); + hBBF2->GetYaxis()->SetBinLabel(kBinBBF_NoSplit, "+noSplit"); + + registry.add("h_mccollisions_eventselection_bcBitsFirst", + "number of mc events vs event selection (BcBitsFirst);event selection;entries", + {HistType::kTH1F, {{kBinBBF_N, 0.5, static_cast(kBinBBF_N) + 0.5}}}); + auto hBBF1 = registry.get(HIST("h_mccollisions_eventselection_bcBitsFirst")); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_Inel, "INEL"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_RctPass, "+RCT_pass"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_TVX, "+kTVX(truth)"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_TFB, "+kNoTFB(truth)"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_ROFB, "+kNoITSROFB(truth)"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_TruthSBP, "+kNoSBP(truth)"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_HasColl, "+hasColl"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_Zreco, "+|zReco|<10"); + hBBF1->GetXaxis()->SetBinLabel(kBinBBF_NoSplit, "+noSplit"); + } + } + + template + float computePtHat(TMcCollision const& mccollision) + { + float ptHardFromMc = ptHardCalcMethodSwitch; + float storedPtHard = mccollision.ptHard(); + if (storedPtHard > kBrokenPtHardSentinel && storedPtHard < ptHardCalcMethodSwitch) { + ptHardFromMc = storedPtHard; } + float weight = mccollision.weight(); + return ptHardFromMc < ptHardCalcMethodSwitch + ? ptHardFromMc + : simPtRef / std::pow(weight, 1.0f / pTHatExponent); } template @@ -267,293 +264,154 @@ struct JetCrossSectionEfficiency { void processCrossSectionEfficiency(aod::JetMcCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, soa::Join const& jets, - aod::JetParticles const&) + aod::JetParticles const&, + aod::JBCs const&) { - bool hasRecoColl = (collisions.size() >= 1); - bool passesZvtxCut = (std::abs(mccollision.posZ()) <= vertexZCut); - bool passesSplitCollCut = !(acceptSplitCollisions == NonSplitOnly && collisions.size() > 1); + if (skipMBGapEvents && mccollision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + bool hasRecoColl = (collisions.size() >= 1); + bool passesZvtxCutReco = false; if (hasRecoColl) { - bool occupancyIsGood = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - auto const& collision = collisions.begin(); - if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { - occupancyIsGood = true; - } + auto const& col = collisions.begin(); + passesZvtxCutReco = (std::abs(col.posZ()) <= vertexZCut); } else { - for (auto const& collision : collisions) { - if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { - occupancyIsGood = true; + for (auto const& col : collisions) { + if (std::abs(col.posZ()) <= vertexZCut) { + passesZvtxCutReco = true; break; } } } - if (!occupancyIsGood) { - return; - } } + bool noSplitPass = (acceptSplitCollisions == NonSplitOnly) ? (collisions.size() == 1) : true; - std::vector stagePassed(activeStages.size(), false); - bool hasCustomEventSel = false; - bool centralityIsGood = false; - float centrality = mccollision.centFT0M(); - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - if (hasRecoColl) { - auto const& collision = collisions.begin(); - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (collision.eventSel() & (1 << activeStages[i].bit)) { - stagePassed[i] = true; - } - } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { - hasCustomEventSel = true; - } - } - if ((centralityMin < centrality) && (centrality < centralityMax)) { - centralityIsGood = true; - } - } else { - for (auto const& collision : collisions) { - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (collision.eventSel() & (1 << activeStages[i].bit)) { - stagePassed[i] = true; - } - } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { - hasCustomEventSel = true; - } - float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); - if ((centralityMin < centrality) && (centrality < centralityMax)) { - centralityIsGood = true; - } - } + bool passesTVX = false, passesNoTFB = false, passesNoITSROFB = false, passesNoSBP = false; + if (hasRecoColl) { + auto const& col = collisions.begin(); + auto evSel = col.eventSel(); + passesTVX = (evSel & (1u << jetderiveddatautilities::JCollisionSel::selTVX)) != 0u; + passesNoTFB = (evSel & (1u << jetderiveddatautilities::JCollisionSel::selNoTimeFrameBorder)) != 0u; + passesNoITSROFB = (evSel & (1u << jetderiveddatautilities::JCollisionSel::selNoITSROFrameBorder)) != 0u; + passesNoSBP = (evSel & (1u << jetderiveddatautilities::JCollisionSel::selNoSameBunchPileup)) != 0u; } - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(binInel)); - if (!hasRecoColl) { - } else { - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(binNoReco)); - if (!passesSplitCollCut) { - goto endEventCounter; - } - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(binSplit)); - - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (!stagePassed[i]) { - goto endEventCounter; - } - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(activeStages[i].bin)); - } - - if (!hasCustomEventSel || !passesZvtxCut) { - goto endEventCounter; - } - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(binZvtx)); - - if (!centralityIsGood) { - goto endEventCounter; - } - registry.fill(HIST("h_mccollisions_eventselection"), static_cast(binCentrality)); + bool passesRct = applyRCT ? (mccollision.bc_as().rct_raw() & rctMask) == 0 : true; + bool pass[kBinCRF_N + 1] = {false, true, passesRct, hasRecoColl, passesZvtxCutReco, + hasRecoColl && noSplitPass, passesTVX, + applyTFB ? passesNoTFB : true, + applyROFB ? passesNoITSROFB : true, + applySBP ? passesNoSBP : true}; + + // Unified weight handling: MB MC -> weight=1 (no-op), JJ MC -> per-event sigma fraction. + float weight = mccollision.weight(); + + int sMax = 0; + for (int s = kBinCRF_Inel; s <= kBinCRF_N; ++s) { + if (!pass[s]) + break; + registry.fill(HIST("h_mccollisions_eventselection_collRecoFirst"), static_cast(s), weight); + sMax = s; + } + if (sMax == 0) { + return; } - endEventCounter: + float pTHat = computePtHat(mccollision); + if (pTHat < pTHatAbsoluteMin) { + return; + } for (auto const& jet : jets) { - if (jet.r() != round(selectedJetsRadius * 100.0f)) { - continue; - } - if (jet.pt() < jetPtMin) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || + jet.pt() < jetPtMin || jet.pt() > pTHatMaxMCP * pTHat || + !isAcceptedJet(jet)) { continue; } - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; + for (int s = kBinCRF_Inel; s <= sMax; ++s) { + registry.fill(HIST("h2_jet_pt_part_eventselection_collRecoFirst"), jet.pt(), static_cast(s), weight); } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binInel)); - - if (!hasRecoColl) { - continue; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binNoReco)); - - if (!passesSplitCollCut) { - continue; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binSplit)); - - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (!stagePassed[i]) { - goto nextJetUnweighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(activeStages[i].bin)); - } - - if (!hasCustomEventSel || !passesZvtxCut) { - goto nextJetUnweighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binZvtx)); - - if (!centralityIsGood) { - goto nextJetUnweighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binCentrality)); - - nextJetUnweighted:; } } - PROCESS_SWITCH(JetCrossSectionEfficiency, processCrossSectionEfficiency, "jet spectra QC for MC particle level with step-by-step cuts", false); - - void processCrossSectionEfficiencyWeighted(aod::JetMcCollisions::iterator const& mccollision, - soa::SmallGroups const& collisions, - soa::Join const& jets, - aod::JetParticles const&) + PROCESS_SWITCH(JetCrossSectionEfficiency, processCrossSectionEfficiency, + "Cascade efficiency with collision-reco required first, BC bits read from the reco-coll EvSels bitmask", true); + + void processCrossSectionEfficiencyBcBitsFirst(aod::JetMcCollisions::iterator const& mccollision, + soa::SmallGroups const& collisions, + soa::Join const& jets, + aod::JetParticles const&, + aod::JBCs const&, + aod::JetMcCollisions const& allMcCollisions) { - bool hasRecoColl = (collisions.size() >= 1); - bool passesZvtxCut = (std::abs(mccollision.posZ()) <= vertexZCut); - bool passesSplitCollCut = !(acceptSplitCollisions == NonSplitOnly && collisions.size() > 1); + if (skipMBGapEvents && mccollision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + + auto truthBC = mccollision.bc_as(); + bool passesTVXTruth = truthBC.selection_bit(aod::evsel::kIsTriggerTVX); + bool passesNoTFBTruth = truthBC.selection_bit(aod::evsel::kNoTimeFrameBorder); + bool passesNoITSROFBTruth = truthBC.selection_bit(aod::evsel::kNoITSROFrameBorder); + auto sameBC = allMcCollisions.sliceBy(mcCollsPerBC, mccollision.bcId()); + bool truthNoSBP = (sameBC.size() == 1); + + bool hasRecoColl = (collisions.size() >= 1); + bool passesZvtxCutReco = false; if (hasRecoColl) { - bool occupancyIsGood = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - auto const& collision = collisions.begin(); - if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { - occupancyIsGood = true; - } + auto const& col = collisions.begin(); + passesZvtxCutReco = (std::abs(col.posZ()) <= vertexZCut); } else { - for (auto const& collision : collisions) { - if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { - occupancyIsGood = true; + for (auto const& col : collisions) { + if (std::abs(col.posZ()) <= vertexZCut) { + passesZvtxCutReco = true; break; } } } - if (!occupancyIsGood) { - return; - } } - - std::vector stagePassed(activeStages.size(), false); - bool hasCustomEventSel = false; - bool centralityIsGood = false; - float centrality = mccollision.centFT0M(); - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - if (hasRecoColl) { - auto const& collision = collisions.begin(); - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (collision.eventSel() & (1 << activeStages[i].bit)) { - stagePassed[i] = true; - } - } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { - hasCustomEventSel = true; - } - } - if ((centralityMin < centrality) && (centrality < centralityMax)) { - centralityIsGood = true; - } - } else { - for (auto const& collision : collisions) { - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (collision.eventSel() & (1 << activeStages[i].bit)) { - stagePassed[i] = true; - } - } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { - hasCustomEventSel = true; - } - float centrality = -1.0; - checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); - if ((centralityMin < centrality) && (centrality < centralityMax)) { - centralityIsGood = true; - } - } + bool noSplitPass = (acceptSplitCollisions == NonSplitOnly) ? (collisions.size() == 1) : true; + + bool passesRct = applyRCT ? (truthBC.rct_raw() & rctMask) == 0 : true; + bool pass[kBinBBF_N + 1] = {false, true, passesRct, passesTVXTruth, + applyTFB ? passesNoTFBTruth : true, + applyROFB ? passesNoITSROFBTruth : true, + applySBP ? truthNoSBP : true, + hasRecoColl, passesZvtxCutReco, hasRecoColl && noSplitPass}; + + float weight = mccollision.weight(); + + int sMax = 0; + for (int s = kBinBBF_Inel; s <= kBinBBF_N; ++s) { + if (!pass[s]) + break; + registry.fill(HIST("h_mccollisions_eventselection_bcBitsFirst"), static_cast(s), weight); + sMax = s; } - - float eventWeight = mccollision.weight(); - - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(binInel), eventWeight); - if (!hasRecoColl) { - } else { - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(binNoReco), eventWeight); - if (!passesSplitCollCut) { - goto endEventCounterWeighted; - } - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(binSplit), eventWeight); - - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (!stagePassed[i]) { - goto endEventCounterWeighted; - } - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(activeStages[i].bin), eventWeight); - } - - if (!hasCustomEventSel || !passesZvtxCut) { - goto endEventCounterWeighted; - } - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(binZvtx), eventWeight); - - if (!centralityIsGood) { - goto endEventCounterWeighted; - } - registry.fill(HIST("h_mccollisions_eventselection_weighted"), static_cast(binCentrality), eventWeight); + if (sMax == 0) { + return; } - endEventCounterWeighted: - - float pTHat = 10.0f / (std::pow(eventWeight, 1.0f / pTHatExponent)); + float pTHat = computePtHat(mccollision); + if (pTHat < pTHatAbsoluteMin) { + return; + } for (auto const& jet : jets) { - if (jet.r() != round(selectedJetsRadius * 100.0f)) { - continue; - } - if (jet.pt() < jetPtMin) { - continue; - } - if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || + jet.pt() < jetPtMin || jet.pt() > pTHatMaxMCP * pTHat || + !isAcceptedJet(jet)) { continue; } - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; + for (int s = kBinBBF_Inel; s <= sMax; ++s) { + registry.fill(HIST("h2_jet_pt_part_eventselection_bcBitsFirst"), jet.pt(), static_cast(s), weight); } - if (!isAcceptedJet(jet)) { - continue; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binInel), eventWeight); - - if (!hasRecoColl) { - continue; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binNoReco), eventWeight); - - if (!passesSplitCollCut) { - continue; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binSplit), eventWeight); - - for (std::size_t i = 0; i < activeStages.size(); ++i) { - if (!stagePassed[i]) { - goto nextJetWeighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(activeStages[i].bin), eventWeight); - } - - if (!hasCustomEventSel || !passesZvtxCut) { - goto nextJetWeighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binZvtx), eventWeight); - - if (!centralityIsGood) { - goto nextJetWeighted; - } - registry.fill(HIST("h2_jet_pt_part_eventselection"), jet.pt(), static_cast(binCentrality), eventWeight); - - nextJetWeighted:; } } - PROCESS_SWITCH(JetCrossSectionEfficiency, processCrossSectionEfficiencyWeighted, "jet spectra QC for MC particle level with step-by-step cuts (weighted)", false); + PROCESS_SWITCH(JetCrossSectionEfficiency, processCrossSectionEfficiencyBcBitsFirst, + "Cascade efficiency with BC bits evaluated on MC truth BC before collision reco", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 226996ff1156fdac3efbdc0d71047c49633e9b1e Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Sat, 6 Jun 2026 00:32:51 +0530 Subject: [PATCH 433/449] [PWGCF] Added calculation profiles for number of triplet weighted average (#16544) --- .../Tasks/v0ptHadPiKaProt.cxx | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index 921c33cfed4..ef4c6fca5f8 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -155,6 +155,7 @@ struct V0ptHadPiKaProt { Configurable cfgLoadPtEffWeights{"cfgLoadPtEffWeights", false, "Load pt-dependent efficiency weights from CCDB to take care of detector inefficiency"}; Configurable cfgMinNoOfParticles{"cfgMinNoOfParticles", 4, "Minimum no. of particles for calculating v02(pT)"}; Configurable cfgV02WeightedFill{"cfgV02WeightedFill", false, "Fill profiles related to v2 with multiplicity-based weights?"}; + Configurable cfgV02WeightedOption3Fill{"cfgV02WeightedOption3Fill", false, "Fill profiles related to v2 with multiplicity-based weights according to Option3, triplet weighting for "}; Configurable cfgUseDominanceCut{"cfgUseDominanceCut", true, "Require particle selecting species' nSigma to be smallest among other two"}; // pT dep DCAxy and DCAz cuts @@ -210,6 +211,7 @@ struct V0ptHadPiKaProt { std::vector>> subSample; std::vector>> subSampleV02; std::vector>> subSampleV02weighted; + std::vector>> subSampleV02weightedOption3; TRandom3* funRndm = new TRandom3(0); // Phi weight histograms initialization @@ -428,10 +430,23 @@ struct V0ptHadPiKaProt { histos.add("Prof_Z_weighted_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); } + if (cfgV02WeightedOption3Fill) { + histos.add("Prof_XY_weightedOption3", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_XYZ_weightedOption3_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weightedOption3_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weightedOption3_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weightedOption3_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weightedOption3_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weightedOption3_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_weightedOption3_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_weightedOption3_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + } + // initial array subSample.resize(cfgNSubsample); subSampleV02.resize(cfgNSubsample); subSampleV02weighted.resize(cfgNSubsample); + subSampleV02weightedOption3.resize(cfgNSubsample); for (int i = 0; i < cfgNSubsample; i++) { subSample[i].resize(20); subSampleV02[i].resize(9); @@ -483,6 +498,18 @@ struct V0ptHadPiKaProt { subSampleV02weighted[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_XYZ_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); subSampleV02weighted[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02weighted_%d/Prof_Z_weighted_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); } + + if (cfgV02WeightedOption3Fill) { + subSampleV02weightedOption3[i][0] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_XY_weightedOption3", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSampleV02weightedOption3[i][1] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_XYZ_weightedOption3_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][2] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_Z_weightedOption3_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][3] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_XYZ_weightedOption3_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][4] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_Z_weightedOption3_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][5] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_XYZ_weightedOption3_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][6] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_Z_weightedOption3_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_XYZ_weightedOption3_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02weightedOption3[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02weightedOption3_%d/Prof_Z_weightedOption3_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + } } if (cfgEvSelMultCorrelation) { @@ -1642,6 +1669,11 @@ struct V0ptHadPiKaProt { histos.get(HIST("Prof_XY_weighted"))->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); subSampleV02weighted[sampleIndex][0]->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); } + + if (cfgV02WeightedOption3Fill) { + histos.get(HIST("Prof_XY_weightedOption3"))->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); + subSampleV02weightedOption3[sampleIndex][0]->Fill(cent, 0.5, twoParCorr, (nSumInWinA * nSumInWinC)); + } // hadrons for (int i = 0; i < cfgNbinsV02pt; i++) { double threeParCorrHad = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileHadInWinB->GetBinContent(i + 1)).Re(); @@ -1658,6 +1690,13 @@ struct V0ptHadPiKaProt { subSampleV02weighted[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinC)); subSampleV02weighted[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); } + + if (cfgV02WeightedOption3Fill) { + histos.get(HIST("Prof_XYZ_weightedOption3_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinB * nSumInWinC)); + histos.get(HIST("Prof_Z_weightedOption3_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + subSampleV02weightedOption3[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad, (nSumInWinA * nSumInWinB * nSumInWinC)); + subSampleV02weightedOption3[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + } } // pions @@ -1676,6 +1715,13 @@ struct V0ptHadPiKaProt { subSampleV02weighted[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinC)); subSampleV02weighted[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); } + + if (cfgV02WeightedOption3Fill) { + histos.get(HIST("Prof_XYZ_weightedOption3_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinB * nSumInWinC)); + histos.get(HIST("Prof_Z_weightedOption3_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + subSampleV02weightedOption3[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi, (nSumInWinA * nSumInWinB * nSumInWinC)); + subSampleV02weightedOption3[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + } } // kaons @@ -1694,6 +1740,13 @@ struct V0ptHadPiKaProt { subSampleV02weighted[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinC)); subSampleV02weighted[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); } + + if (cfgV02WeightedOption3Fill) { + histos.get(HIST("Prof_XYZ_weightedOption3_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinB * nSumInWinC)); + histos.get(HIST("Prof_Z_weightedOption3_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + subSampleV02weightedOption3[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa, (nSumInWinA * nSumInWinB * nSumInWinC)); + subSampleV02weightedOption3[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + } } // protons @@ -1712,6 +1765,13 @@ struct V0ptHadPiKaProt { subSampleV02weighted[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinC)); subSampleV02weighted[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); } + + if (cfgV02WeightedOption3Fill) { + histos.get(HIST("Prof_XYZ_weightedOption3_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinB * nSumInWinC)); + histos.get(HIST("Prof_Z_weightedOption3_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + subSampleV02weightedOption3[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt, (nSumInWinA * nSumInWinB * nSumInWinC)); + subSampleV02weightedOption3[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB), nSumInWinB); + } } } From 09315dda3e11dcb78302024efbef8ad4e760a7dd Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Sat, 6 Jun 2026 01:29:06 +0200 Subject: [PATCH 434/449] [PWGCF] Add multNTracksPV multiplicity estimator in the task (#16547) --- .../TwoParticleCorrelations/TableProducer/longrangeMaker.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index 03a5d861653..0eaaf4a4f82 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -117,6 +117,7 @@ struct LongrangeMaker { Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, "Enable NoCollInRofStrict cut"}; Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, "Enable NoHighMultCollInPrevRof cut"}; Configurable isApplyCentFT0C{"isApplyCentFT0C", false, "Centrality based on FT0C"}; + Configurable isApplyMultNTracksPV{"isApplyMultNTracksPV", false, "Multiplicity based on MultNTracksPV"}; Configurable isApplyCentFV0A{"isApplyCentFV0A", false, "Centrality based on FV0A"}; Configurable isApplyCentFT0M{"isApplyCentFT0M", false, "Centrality based on FT0A + FT0C"}; Configurable isApplyOccuSelection{"isApplyOccuSelection", false, "Enable occupancy selection"}; @@ -1140,6 +1141,9 @@ struct LongrangeMaker { float selColCent(CheckColCent const& col) { auto cent = -1; + if (cfgevtsel.isApplyMultNTracksPV) { + cent = col.multNTracksPV(); + } if (cfgevtsel.isApplyCentFT0C) { cent = col.centFT0C(); } From 06a4f14a223f4dd7198aa956f50ccb0263802bae Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Sat, 6 Jun 2026 12:53:54 +0530 Subject: [PATCH 435/449] [PWGCF] Fix: define size of vector (#16548) --- PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index ef4c6fca5f8..701dd2d8eaa 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -451,6 +451,7 @@ struct V0ptHadPiKaProt { subSample[i].resize(20); subSampleV02[i].resize(9); subSampleV02weighted[i].resize(9); + subSampleV02weightedOption3[i].resize(9); } for (int i = 0; i < cfgNSubsample; i++) { subSample[i][0] = std::get>(histos.add(Form("subSample_%d/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); From 059b90d502394163b66ab6806e1f2e0edbf5cd4c Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Sat, 6 Jun 2026 10:27:41 +0200 Subject: [PATCH 436/449] change axes --- PWGUD/Tasks/upcRhoAnalysis.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index db20d94afb3..b6a0501082f 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -292,13 +292,13 @@ struct UpcRhoAnalysis { rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); // tracks rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {100, 0.0, 1.0}, {180, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaEl", ";TPC #it{n#sigma}(e);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaEl", ";TPC #it{n#sigma}(e);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {100, 0.0, 1.0}, {180, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaKa", ";TPC #it{n#sigma}(K);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaKa", ";TPC #it{n#sigma}(K);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {100, 0.0, 1.0}, {180, -0.9, 0.9}}); rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPr", ";TPC #it{n#sigma}(p);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {200, 0.0, 4.0}, {18, -0.9, 0.9}}); + rQC.add("QC/tracks/all/hPtVsEtaVsTpcNSigmaPr", ";TPC #it{n#sigma}(p);#it{p}_{T} (GeV/#it{c});#it{#eta}", kTH3D, {{100, -10.0, 10.0}, {100, 0.0, 1.0}, {180, -0.9, 0.9}}); rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{9, -0.5, 8.5}}); rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); From 81d90aafee287efb92527c97e1137983ad5b1638 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Tue, 9 Jun 2026 22:24:08 +0200 Subject: [PATCH 437/449] add phi resolution plots for MC --- PWGUD/Tasks/upcRhoAnalysis.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index b6a0501082f..ee188351307 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -437,6 +437,8 @@ struct UpcRhoAnalysis { rResolution.add("MC/resolution/system/2D/hPtVsPt", ";1/#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); rResolution.add("MC/resolution/system/1D/hY", ";#it{y}_{reco} - #it{y}_{true};counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hYVsY", ";#it{y}_{true};#it{y}_{reco};counts", kTH2D, {yAxis, yAxis}); + rResolution.add("MC/resolution/system/1D/hPhi", ";#it{#phi}_{reco} - #it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hPhiVsPhi", ";#it{#phi}_{true} (rad);#it{#phi}_{reco} (rad);counts", kTH2D, {phiAxis, phiAxis}); rResolution.add("MC/resolution/system/1D/hDeltaPhi", ";#Delta#it{#phi}_{reco} - #Delta#it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hDeltaPhiVsDeltaPhi", ";#Delta#it{#phi}_{true} (rad);#Delta#it{#phi}_{reco} (rad);counts", kTH2D, {deltaPhiAxis, deltaPhiAxis}); } From c0884a5f514b52394da3f666033483b8b51fc52e Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Tue, 9 Jun 2026 22:31:05 +0200 Subject: [PATCH 438/449] ... and fill them --- PWGUD/Tasks/upcRhoAnalysis.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index ee188351307..e8771007837 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -1218,6 +1218,8 @@ struct UpcRhoAnalysis { rResolution.fill(HIST("MC/resolution/system/2D/hPtVsPt"), trueSystem.Pt(), recoSystem.Pt()); rResolution.fill(HIST("MC/resolution/system/1D/hY"), recoSystem.Rapidity() - trueSystem.Rapidity()); rResolution.fill(HIST("MC/resolution/system/2D/hYVsY"), trueSystem.Rapidity(), recoSystem.Rapidity()); + rResolution.fill(HIST("MC/resolution/system/1D/hPhi"), phi(recoSystem.Px(), recoSystem.Py()) - phi(trueSystem.Px(), trueSystem.Py())); + rResolution.fill(HIST("MC/resolution/system/2D/hPhiVsPhi"), phi(trueSystem.Px(), trueSystem.Py()), phi(recoSystem.Px(), recoSystem.Py())); rResolution.fill(HIST("MC/resolution/system/1D/hDeltaPhi"), recoDeltaPhi - trueDeltaPhi); rResolution.fill(HIST("MC/resolution/system/2D/hDeltaPhiVsDeltaPhi"), trueDeltaPhi, recoDeltaPhi); From 278d73d5040bccfe82649fef0cb4dbaa657813f8 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Wed, 10 Jun 2026 16:38:04 +0200 Subject: [PATCH 439/449] small bug in DG process function + adjusted runlist for pass5 --- PWGUD/Tasks/upcRhoAnalysis.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index e8771007837..f760a957fdb 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -190,7 +190,7 @@ struct UpcRhoAnalysis { const float pcEtaCut = 0.9; // physics coordination recommendation const int nPions = 2; // only study dipion final states - const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544911, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544991, 544992, 545004, 545008, 545009, 545041, 545042, 545044, 545047, 545060, 545062, 545063, 545064, 545066, 545086, 545103, 545117, 545171, 545184, 545185, 545210, 545222, 545223, 545246, 545249, 545262, 545289, 545291, 545294, 545295, 545296, 545311, 545312, 545332, 545345, 545367}; + const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}; AxisSpec runNumberAxis = {static_cast(runNumbers.size()), 0.5, static_cast(runNumbers.size()) + 0.5, "run number"}; Configurable isPO{"isPO", false, "processing p-O data?"}; @@ -281,7 +281,7 @@ struct UpcRhoAnalysis { rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); - std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "#it{z} position", "number of contributors", "RCT selections", "reco flag selection", "occupancy selection"}; + std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "vertex #it{z} position", "number of contributors", "RCT selections", "reco flag selection", "occupancy selection"}; rQC.add("QC/collisions/hSelectionCounter", ";;collisions passing selections", kTH1D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}}); rQC.add("QC/collisions/hSelectionCounterPerRun", ";;run number;collisions passing selections", kTH2D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); for (int i = 0; i < static_cast(collisionSelectionCounterLabels.size()); ++i) { @@ -1148,6 +1148,8 @@ struct UpcRhoAnalysis { void processDGdata(FullUdDgCollision const& collision, FullUdTracks const& tracks) { int runIndex = getRunIndex(collision.runNumber(), runNumbers); + rQC.fill(HIST("QC/collisions/hSelectionCounter"), 0); // all collisions + rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 0, runIndex); rQC.fill(HIST("QC/collisions/hSelectionCounter"), 1); // no single-gap collisions in dataset rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 1, runIndex); From 1f111a560f56f2474f78055fe27913001e5964d4 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 11 Jun 2026 22:29:40 +0200 Subject: [PATCH 440/449] add colllision reco mode checker --- PWGUD/Tasks/upcRhoAnalysis.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index f760a957fdb..8b3e0ec0fef 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -276,6 +276,7 @@ struct UpcRhoAnalysis { rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); rQC.add("QC/collisions/all/hOccupancyInTime", ";occupancy in time;counts", kTH1D, {{1100, 0.0, 1100.0}}); + rQC.add("QC/collisions/all/hRecoMode", ";reconstruction mode;counts", kTH1D, {{2, -0.5, 1.5}}); rQC.add("QC/collisions/hNumContribVsPVTracks", ";number of track.isPVContributor() per collision;collision.numContrib();counts", kTH2D, {{101, -0.5, 100.5}, {101, -0.5, 100.5}}); // events with selected rho candidates rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); @@ -469,6 +470,7 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTimeFDDA"), collision.timeFDDA()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTimeFDDC"), collision.timeFDDC()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hOccupancyInTime"), collision.occupancyInTime()); + rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hRecoMode"), collision.flags()); } template From 9ec46fcc2f66c75e1b7101aba725cd8378a1b9a1 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 11 Jun 2026 22:43:32 +0200 Subject: [PATCH 441/449] changes in PID histos --- PWGUD/Tasks/upcRhoAnalysis.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 8b3e0ec0fef..e1b50845d1b 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -317,6 +317,7 @@ struct UpcRhoAnalysis { rQC.addClone("QC/tracks/all/", "QC/tracks/systemSelections/"); rQC.add("QC/tracks/trackSelections/hRemainingTracks", ";remaining tracks;counts", kTH1D, {{21, -0.5, 20.5}}); rQC.add("QC/tracks/trackSelections/hTpcNSigmaPi2D", ";TPC #it{n#sigma}(#pi)_{leading};TPC #it{n#sigma}(#pi)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); + rQC.add("QC/tracks/trackSelections/hTpcNSigmaPi2DAfterCut", ";TPC #it{n#sigma}(#pi)_{leading};TPC #it{n#sigma}(#pi)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); rQC.add("QC/tracks/trackSelections/hTpcNSigmaEl2D", ";TPC #it{n#sigma}(e)_{leading};TPC #it{n#sigma}(e)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); rQC.add("QC/tracks/trackSelections/hTpcNSigmaKa2D", ";TPC #it{n#sigma}(K)_{leading};TPC #it{n#sigma}(K)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); rQC.add("QC/tracks/trackSelections/hTpcNSigmaPr2D", ";TPC #it{n#sigma}(p)_{leading};TPC #it{n#sigma}(p)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); @@ -891,10 +892,6 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/hSelectionCounter"), 15); rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 15, runIndex); } - rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPi2D"), cutTracks[0].tpcNSigmaPi(), cutTracks[1].tpcNSigmaPi()); - rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaEl2D"), cutTracks[0].tpcNSigmaEl(), cutTracks[1].tpcNSigmaEl()); - rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaKa2D"), cutTracks[0].tpcNSigmaKa(), cutTracks[1].tpcNSigmaKa()); - rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPr2D"), cutTracks[0].tpcNSigmaPr(), cutTracks[1].tpcNSigmaPr()); // create a vector of 4-vectors for selected tracks std::vector cutTracksLVs; @@ -906,6 +903,11 @@ struct UpcRhoAnalysis { auto leadingTrack = momentum(cutTracks[0].px(), cutTracks[0].py(), cutTracks[0].pz()) > momentum(cutTracks[1].px(), cutTracks[1].py(), cutTracks[1].pz()) ? cutTracks[0] : cutTracks[1]; auto subleadingTrack = (leadingTrack == cutTracks[0]) ? cutTracks[1] : cutTracks[0]; + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPi2D"), leadingTrack.tpcNSigmaPi(), subleadingTrack.tpcNSigmaPi()); + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaEl2D"), leadingTrack.tpcNSigmaEl(), subleadingTrack.tpcNSigmaEl()); + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaKa2D"), leadingTrack.tpcNSigmaKa(), subleadingTrack.tpcNSigmaKa()); + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPr2D"), leadingTrack.tpcNSigmaPr(), subleadingTrack.tpcNSigmaPr()); + float leadingPt = leadingTrack.pt(); float subleadingPt = subleadingTrack.pt(); float leadingEta = eta(leadingTrack.px(), leadingTrack.py(), leadingTrack.pz()); @@ -931,6 +933,7 @@ struct UpcRhoAnalysis { if (!tracksPassPID(cutTracks)) // apply PID cut return; + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPi2DAfterCut"), leadingTrack.tpcNSigmaPi(), subleadingTrack.tpcNSigmaPi()); for (const auto& cutTrack : cutTracks) { rQC.fill(HIST("QC/tracks/hSelectionCounter"), 16); From 2b21014f38907711cb1e2367070e2e6910a00c42 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 11 Jun 2026 22:45:55 +0200 Subject: [PATCH 442/449] add switch for application of PID before creating derived data --- PWGUD/Tasks/upcRhoAnalysis.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index e1b50845d1b..e104a90a958 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -230,6 +230,7 @@ struct UpcRhoAnalysis { Configurable tracksMaxTpcChi2NClCut{"tracksMaxTpcChi2NClCut", 3.0, "max TPC chi2/Ncls cut"}; Configurable tracksMinTpcNClsCrossedOverFindableCut{"tracksMinTpcNClsCrossedOverFindableCut", 1.0, "min TPC crossed rows / findable clusters cut"}; Configurable tracksMinPtCut{"tracksMinPtCut", 0.1, "min pT cut on tracks"}; + Configurable applyPid{"applyPid", true, "apply PID before creating derived data?"}; Configurable systemMassMinCut{"systemMassMinCut", 0.5, "min M cut for reco system"}; Configurable systemMassMaxCut{"systemMassMaxCut", 1.0, "max M cut for reco system"}; @@ -917,6 +918,9 @@ struct UpcRhoAnalysis { float phiRandom = getPhiRandom(cutTracksLVs); float phiCharge = getPhiCharge(cutTracks, cutTracksLVs); + if (applyPid && !tracksPassPID(cutTracks)) // apply PID cut before creating derived data if desired + return; + // fill recoTree recoTree(collision.flags(), collision.runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.occupancyInTime(), collision.hadronicRate(), collision.globalBC() % o2::constants::lhc::LHCMaxBunches, collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), From fa4c26aefcb70f7a47187abcd1a67f539504ceeb Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Sat, 8 Aug 2026 16:25:50 +0200 Subject: [PATCH 443/449] adding some histos for MC --- PWGUD/Tasks/upcRhoAnalysis.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index e104a90a958..63add607618 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -416,6 +416,8 @@ struct UpcRhoAnalysis { rMC.add("MC/system/hPhiCharge", ";#Delta#it{#phi}_{charge} (rad);counts", kTH1D, {deltaPhiAxis}); rMC.add("MC/system/hPhiRandomVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); rMC.add("MC/system/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); + rMC.add("MC/system/hPhiRandomVsPt", ";#it{p}_{T} (GeV/#it{c});#Delta#it{#phi} (rad);counts", kTH2D, {ptAxis, deltaPhiAxis}); + rMC.add("MC/system/hPhiChargeVsPt", ";#it{p}_{T} (GeV/#it{c});#Delta#it{#phi} (rad);counts", kTH2D, {ptAxis, deltaPhiAxis}); rMC.addClone("MC/system/", "MC/system/selected/"); } @@ -1109,6 +1111,8 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/system/hPhiCharge"), phiCharge); rMC.fill(HIST("MC/system/hPhiRandomVsM"), mass, phiRandom); rMC.fill(HIST("MC/system/hPhiChargeVsM"), mass, phiCharge); + rMC.fill(HIST("MC/system/hPhiRandomVsPt"), pT, phiRandom); + rMC.fill(HIST("MC/system/hPhiChargeVsPt"), pT, phiCharge); if (systemPassesCuts(system)) { rMC.fill(HIST("MC/system/selected/hM"), mass); From 6e1149e0905493a9371ac70290265fc99dc25a9e Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Sat, 8 Aug 2026 17:13:35 +0200 Subject: [PATCH 444/449] removing "magic number" --- PWGUD/Tasks/upcRhoAnalysis.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 63add607618..7028e965710 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -189,7 +189,7 @@ struct UpcRhoAnalysis { SGSelector sgSelector; const float pcEtaCut = 0.9; // physics coordination recommendation - const int nPions = 2; // only study dipion final states + const int nExpectedPions = 2; // only study dipion final states const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}; AxisSpec runNumberAxis = {static_cast(runNumbers.size()), 0.5, static_cast(runNumbers.size()) + 0.5, "run number"}; @@ -889,9 +889,9 @@ struct UpcRhoAnalysis { } rQC.fill(HIST("QC/tracks/trackSelections/hRemainingTracks"), cutTracks.size()); - if (static_cast(cutTracks.size()) != nPions) // further consider only two pion systems + if (static_cast(cutTracks.size()) != nExpectedPions) // further consider only two pion systems return; - for (int i = 0; i < nPions; i++) { + for (int i = 0; i < nExpectedPions; i++) { rQC.fill(HIST("QC/tracks/hSelectionCounter"), 15); rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 15, runIndex); } @@ -1079,7 +1079,7 @@ struct UpcRhoAnalysis { } rMC.fill(HIST("MC/collisions/hNPions"), cutMcParticles.size()); - if (static_cast(cutMcParticles.size()) != 2) + if (static_cast(cutMcParticles.size()) != nExpectedPions) // further consider only two pion systems return; if (mcParticlesLVs.size() != cutMcParticles.size()) // sanity check return; @@ -1219,7 +1219,7 @@ struct UpcRhoAnalysis { recoTracks.push_back(track); } - if (truePionLVs.size() != 2 || recoPionLVs.size() != 2) + if (truePionLVs.size() != nExpectedPions || recoPionLVs.size() != nExpectedPions) return; ROOT::Math::PxPyPzMVector trueSystem = reconstructSystem(truePionLVs); From bfe55c0ce557fe395b9f26cdbc787806018464b4 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 17 Sep 2026 22:23:54 +0200 Subject: [PATCH 445/449] axis name bugfix --- PWGUD/Tasks/upcRhoAnalysis.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 7028e965710..bfc20791966 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -439,7 +439,7 @@ struct UpcRhoAnalysis { rResolution.add("MC/resolution/system/1D/hM", ";#it{m}_{reco} - #it{m}_{true} (GeV/#it{c}^{2});counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hMVsM", ";#it{m}_{true} (GeV/#it{c}^{2});#it{m}_{reco} (GeV/#it{c}^{2});counts", kTH2D, {mAxis, mAxis}); rResolution.add("MC/resolution/system/1D/hPt", ";1/#it{p}_{T, reco} - 1/#it{p}_{T, true} (1/(GeV/#it{c}));counts", kTH1D, {resolutionAxis}); - rResolution.add("MC/resolution/system/2D/hPtVsPt", ";1/#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + rResolution.add("MC/resolution/system/2D/hPtVsPt", ";#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); rResolution.add("MC/resolution/system/1D/hY", ";#it{y}_{reco} - #it{y}_{true};counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hYVsY", ";#it{y}_{true};#it{y}_{reco};counts", kTH2D, {yAxis, yAxis}); rResolution.add("MC/resolution/system/1D/hPhi", ";#it{#phi}_{reco} - #it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); From 0de1eeb612fa380b86ad0447b2b92bd6a579d70c Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 17 Sep 2026 22:25:51 +0200 Subject: [PATCH 446/449] add fit into resolution derived data --- PWGUD/Tasks/upcRhoAnalysis.cxx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index bfc20791966..d99cf0c0d8e 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -156,6 +156,17 @@ DECLARE_SOA_COLUMN(GenPosZ, genPosZ, float); DECLARE_SOA_COLUMN(RecoPosX, recoPosX, float); DECLARE_SOA_COLUMN(RecoPosY, recoPosY, float); DECLARE_SOA_COLUMN(RecoPosZ, recoPosZ, float); +// FIT info +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); +DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFDDAmplitudeA, totalFDDAmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFDDAmplitudeC, totalFDDAmplitudeC, float); +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); +DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float); +DECLARE_SOA_COLUMN(TimeFDDA, timeFDDA, float); +DECLARE_SOA_COLUMN(TimeFDDC, timeFDDC, float); // track info DECLARE_SOA_COLUMN(LeadingSign, leadingSign, int); DECLARE_SOA_COLUMN(LeadingGenPt, leadingGenPt, float); @@ -175,6 +186,8 @@ DECLARE_SOA_COLUMN(SubleadingRecoPhi, subleadingRecoPhi, float); DECLARE_SOA_TABLE(ResolutionTree, "AOD", "RESOLUTIONTREE", resolution_tree::GenPosX, resolution_tree::GenPosY, resolution_tree::GenPosZ, resolution_tree::RecoPosX, resolution_tree::RecoPosY, resolution_tree::RecoPosZ, + resolution_tree::TotalFT0AmplitudeA, resolution_tree::TotalFT0AmplitudeC, resolution_tree::TotalFV0AmplitudeA, resolution_tree::TotalFDDAmplitudeA, resolution_tree::TotalFDDAmplitudeC, + resolution_tree::TimeFT0A, resolution_tree::TimeFT0C, resolution_tree::TimeFV0A, resolution_tree::TimeFDDA, resolution_tree::TimeFDDC, resolution_tree::LeadingSign, resolution_tree::LeadingGenPt, resolution_tree::LeadingGenEta, resolution_tree::LeadingGenPhi, resolution_tree::LeadingRecoPt, resolution_tree::LeadingRecoEta, resolution_tree::LeadingRecoPhi, resolution_tree::SubleadingSign, resolution_tree::SubleadingGenPt, resolution_tree::SubleadingGenEta, resolution_tree::SubleadingGenPhi, @@ -1219,7 +1232,7 @@ struct UpcRhoAnalysis { recoTracks.push_back(track); } - if (truePionLVs.size() != nExpectedPions || recoPionLVs.size() != nExpectedPions) + if (static_cast(truePionLVs.size()) != nExpectedPions || static_cast(recoPionLVs.size()) != nExpectedPions) return; ROOT::Math::PxPyPzMVector trueSystem = reconstructSystem(truePionLVs); @@ -1245,6 +1258,8 @@ struct UpcRhoAnalysis { resolutionTree(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), collision.posX(), collision.posY(), collision.posZ(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC(), leadingTruePion.pdgCode() / std::abs(leadingTruePion.pdgCode()), pt(leadingTruePion.px(), leadingTruePion.py()), eta(leadingTruePion.px(), leadingTruePion.py(), leadingTruePion.pz()), phi(leadingTruePion.px(), leadingTruePion.py()), pt(leadingRecoPion.px(), leadingRecoPion.py()), eta(leadingRecoPion.px(), leadingRecoPion.py(), leadingRecoPion.pz()), phi(leadingRecoPion.px(), leadingRecoPion.py()), subleadingTruePion.pdgCode() / std::abs(subleadingTruePion.pdgCode()), pt(subleadingTruePion.px(), subleadingTruePion.py()), eta(subleadingTruePion.px(), subleadingTruePion.py(), subleadingTruePion.pz()), phi(subleadingTruePion.px(), subleadingTruePion.py()), From e5d918e5627446d21dc400d87e1b6fae747d97d6 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 17 Sep 2026 22:27:28 +0200 Subject: [PATCH 447/449] change default rct flag --- PWGUD/Tasks/upcRhoAnalysis.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index d99cf0c0d8e..997e77f205b 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -220,7 +220,7 @@ struct UpcRhoAnalysis { Configurable useRecoFlag{"useRecoFlag", false, "use UPC/STD reconstruction flag for event selection?"}; Configurable cutRecoFlag{"cutRecoFlag", 1, "0 = std mode, 1 = upc mode"}; Configurable useRctFlag{"useRctFlag", true, "use RCT flags for event selection?"}; - Configurable cutRctFlag{"cutRctFlag", 1, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; + Configurable cutRctFlag{"cutRctFlag", 2, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; Configurable selectRuns{"selectRuns", false, "select runs?"}; Configurable> selectedRuns{"selectedRuns", {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}, "list of selected runs"}; From fa20bfd4d2fa7ebd2afe8619dd5c10ea7df575a4 Mon Sep 17 00:00:00 2001 From: Jakub Juracka Date: Thu, 17 Sep 2026 22:30:43 +0200 Subject: [PATCH 448/449] added new process function to analyze MC reco with truth info --- PWGUD/Tasks/upcRhoAnalysis.cxx | 46 ++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 997e77f205b..364e3d32f3c 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -270,7 +270,7 @@ struct UpcRhoAnalysis { void init(o2::framework::InitContext& context) { - if (context.mOptions.get("processSGdata") || context.mOptions.get("processDGdata")) { + if (context.mOptions.get("processSGdata") || context.mOptions.get("processDGdata") || context.mOptions.get("processMcRecoWithTruth")) { // QA // collisions rQC.add("QC/collisions/all/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); @@ -394,7 +394,7 @@ struct UpcRhoAnalysis { rSystem.addClone("system/selected/AnAn/", "system/selected/XnXn/"); } - if (context.mOptions.get("processMCdata") || context.mOptions.get("processMCdataWithBCs")) { + if (context.mOptions.get("processMCdata") || context.mOptions.get("processMCdataWithBCs") || context.mOptions.get("processMcRecoWithTruth")) { // MC // collisions rMC.add("MC/collisions/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); @@ -1267,6 +1267,48 @@ struct UpcRhoAnalysis { } PROCESS_SWITCH(UpcRhoAnalysis, processResolution, "check resolution of kinematic variables", false); + void processMcRecoWithTruth(soa::Join::iterator const& collision, soa::Join const& tracks, aod::UDMcCollisions const&, aod::UDMcParticles const&) + { + // basically just runs the analysis as for normal data but also accesses the MC truth information for the tracks and collisions + auto mcCollision = collision.udMcCollision(); + const int runIndex = -1; // we don't care here + if (cutGapSide && collision.gapSide() != gapSide) + return; + if (!collisionPassesCuts(collision, runIndex)) // apply collision cuts + return; + + std::vector recoTracks; // store selected tracks + std::vector trueTracks; + for (const auto& track : tracks) { + fillTrackQcHistos<0>(track); // fill QC histograms before cuts + + if (!trackPassesCuts(track, runIndex)) // apply track cuts + continue; + recoTracks.push_back(track); + if (track.has_udMcParticle()) + trueTracks.push_back(track.udMcParticle()); + } + if (static_cast(recoTracks.size()) != nExpectedPions || static_cast(trueTracks.size()) != nExpectedPions) // further consider only two pion systems + return; + if (applyPid && !tracksPassPID(recoTracks)) // apply PID cut before creating derived data if desired + return; + + auto leadingTruePion = momentum(trueTracks[0].px(), trueTracks[0].py(), trueTracks[0].pz()) > momentum(trueTracks[1].px(), trueTracks[1].py(), trueTracks[1].pz()) ? trueTracks[0] : trueTracks[1]; + auto subleadingTruePion = (leadingTruePion == trueTracks[0]) ? trueTracks[1] : trueTracks[0]; + auto leadingRecoPion = momentum(recoTracks[0].px(), recoTracks[0].py(), recoTracks[0].pz()) > momentum(recoTracks[1].px(), recoTracks[1].py(), recoTracks[1].pz()) ? recoTracks[0] : recoTracks[1]; + auto subleadingRecoPion = (leadingRecoPion == recoTracks[0]) ? recoTracks[1] : recoTracks[0]; + + resolutionTree(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), + collision.posX(), collision.posY(), collision.posZ(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC(), + leadingTruePion.pdgCode() / std::abs(leadingTruePion.pdgCode()), pt(leadingTruePion.px(), leadingTruePion.py()), eta(leadingTruePion.px(), leadingTruePion.py(), leadingTruePion.pz()), phi(leadingTruePion.px(), leadingTruePion.py()), + pt(leadingRecoPion.px(), leadingRecoPion.py()), eta(leadingRecoPion.px(), leadingRecoPion.py(), leadingRecoPion.pz()), phi(leadingRecoPion.px(), leadingRecoPion.py()), + subleadingTruePion.pdgCode() / std::abs(subleadingTruePion.pdgCode()), pt(subleadingTruePion.px(), subleadingTruePion.py()), eta(subleadingTruePion.px(), subleadingTruePion.py(), subleadingTruePion.pz()), phi(subleadingTruePion.px(), subleadingTruePion.py()), + pt(subleadingRecoPion.px(), subleadingRecoPion.py()), eta(subleadingRecoPion.px(), subleadingRecoPion.py(), subleadingRecoPion.pz()), phi(subleadingRecoPion.px(), subleadingRecoPion.py())); + } + PROCESS_SWITCH(UpcRhoAnalysis, processMcRecoWithTruth, "process MC reco with access to MC truth", false); + void processCollisionRecoCheck(aod::UDMcCollision const& /* mcCollision */, soa::SmallGroups> const& collisions) { checkNumberOfCollisionReconstructions(collisions); From add2eab3118a37da551a71764e0718086abfcae7 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 17 Sep 2026 21:02:46 +0000 Subject: [PATCH 449/449] Please consider the following formatting changes --- PWGUD/Tasks/upcRhoAnalysis.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 364e3d32f3c..93d0834e106 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -202,7 +202,7 @@ struct UpcRhoAnalysis { SGSelector sgSelector; const float pcEtaCut = 0.9; // physics coordination recommendation - const int nExpectedPions = 2; // only study dipion final states + const int nExpectedPions = 2; // only study dipion final states const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}; AxisSpec runNumberAxis = {static_cast(runNumbers.size()), 0.5, static_cast(runNumbers.size()) + 0.5, "run number"}; @@ -1292,7 +1292,7 @@ struct UpcRhoAnalysis { return; if (applyPid && !tracksPassPID(recoTracks)) // apply PID cut before creating derived data if desired return; - + auto leadingTruePion = momentum(trueTracks[0].px(), trueTracks[0].py(), trueTracks[0].pz()) > momentum(trueTracks[1].px(), trueTracks[1].py(), trueTracks[1].pz()) ? trueTracks[0] : trueTracks[1]; auto subleadingTruePion = (leadingTruePion == trueTracks[0]) ? trueTracks[1] : trueTracks[0]; auto leadingRecoPion = momentum(recoTracks[0].px(), recoTracks[0].py(), recoTracks[0].pz()) > momentum(recoTracks[1].px(), recoTracks[1].py(), recoTracks[1].pz()) ? recoTracks[0] : recoTracks[1];